Diff for /loncom/interface/domainprefs.pm between versions 1.139 and 1.160.6.54

version 1.139, 2010/08/24 13:37:50 version 1.160.6.54, 2014/10/04 02:44:18
Line 45  described at http://www.lon-capa.org. Line 45  described at http://www.lon-capa.org.
 =head1 OVERVIEW  =head1 OVERVIEW
   
 Each institution using LON-CAPA will typically have a single domain designated   Each institution using LON-CAPA will typically have a single domain designated 
 for use by individuals affliated with the institution.  Accordingly, each domain  for use by individuals affiliated with the institution.  Accordingly, each domain
 may define a default set of logos and a color scheme which can be used to "brand"  may define a default set of logos and a color scheme which can be used to "brand"
 the LON-CAPA instance. In addition, an institution will typically have a language  the LON-CAPA instance. In addition, an institution will typically have a language
 and timezone which are used for the majority of courses.  and timezone which are used for the majority of courses.
Line 86  $dom,$settings,$rowtotal,$action. Line 86  $dom,$settings,$rowtotal,$action.
   
 $dom is the domain, $settings is a reference to a hash of current settings for  $dom is the domain, $settings is a reference to a hash of current settings for
 the current context, $rowtotal is a reference to the scalar used to record the   the current context, $rowtotal is a reference to the scalar used to record the 
 number of rows displayed on the page, and $action is the context (either quotas   number of rows displayed on the page, and $action is the context (quotas, 
 or requestcourses).  requestcourses or requestauthor).
   
 The print_quotas routine was orginally created to display/store information  The print_quotas routine was orginally created to display/store information
 about default quota sizes for portfolio spaces for the different types of   about default quota sizes for portfolio spaces for the different types of 
 institutional affiliation in the domain (e.g., Faculty, Staff, Student etc.),   institutional affiliation in the domain (e.g., Faculty, Staff, Student etc.), 
 but is now also used to manage availability of user tools:   but is now also used to manage availability of user tools: 
 i.e., blogs, aboutme page, and portfolios, and the course request tool,  i.e., blogs, aboutme page, and portfolios, and the course request tool,
 used by course owners to request creation of a course.  used by course owners to request creation of a course, and to display/store
   default quota sizes for Authoring Spaces.
   
 Outputs: 1  Outputs: 1
   
Line 102  $datatable  - HTML containing form eleme Line 103  $datatable  - HTML containing form eleme
   
 In the case of course requests, radio buttons are displayed for each institutional  In the case of course requests, radio buttons are displayed for each institutional
 affiliate type (and also default, and _LC_adv) for each of the course types   affiliate type (and also default, and _LC_adv) for each of the course types 
 (official, unofficial and community).  In each case the radio buttons allow the   (official, unofficial, community, and textbook).  In each case the radio buttons 
 selection of one of four values:  allow the selection of one of four values:
   
 0, approval, validate, autolimit=N (where N is blank, or a positive integer).  0, approval, validate, autolimit=N (where N is blank, or a positive integer).
 which have the following effects:  which have the following effects:
Line 140  autolimit Line 141  autolimit
   
 =over  =over
     
 - course requests will be processed autoatically up to a limit of  - course requests will be processed automatically up to a limit of
 N requests for the course type for the particular requestor.  N requests for the course type for the particular requestor.
 If N is undefined, there is no limit to the number of course requests  If N is undefined, there is no limit to the number of course requests
 which a course owner may submit and have processed automatically.   which a course owner may submit and have processed automatically. 
Line 163  use Apache::lonhtmlcommon(); Line 164  use Apache::lonhtmlcommon();
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonmsg();  use Apache::lonmsg();
 use Apache::lonconfigsettings;  use Apache::lonconfigsettings;
   use Apache::lonuserutils();
   use Apache::loncoursequeueadmin();
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
 use LONCAPA::Enrollment;  use LONCAPA::Enrollment;
 use LONCAPA::lonauthcgi();  use LONCAPA::lonauthcgi();
Line 171  use Locale::Language; Line 174  use Locale::Language;
 use DateTime::TimeZone;  use DateTime::TimeZone;
 use DateTime::Locale;  use DateTime::Locale;
   
   my $registered_cleanup;
   my $modified_urls;
   
 sub handler {  sub handler {
     my $r=shift;      my $r=shift;
     if ($r->header_only) {      if ($r->header_only) {
Line 190  sub handler { Line 196  sub handler {
         "/adm/domainprefs:mau:0:0:Cannot modify domain settings";          "/adm/domainprefs:mau:0:0:Cannot modify domain settings";
         return HTTP_NOT_ACCEPTABLE;          return HTTP_NOT_ACCEPTABLE;
     }      }
   
       $registered_cleanup=0;
       @{$modified_urls}=();
   
     &Apache::lonhtmlcommon::clear_breadcrumbs();      &Apache::lonhtmlcommon::clear_breadcrumbs();
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                                             ['phase','actions']);                                              ['phase','actions']);
Line 197  sub handler { Line 207  sub handler {
     if ( exists($env{'form.phase'}) ) {      if ( exists($env{'form.phase'}) ) {
         $phase = $env{'form.phase'};          $phase = $env{'form.phase'};
     }      }
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
     my %domconfig =      my %domconfig =
       &Apache::lonnet::get_dom('configuration',['login','rolecolors',        &Apache::lonnet::get_dom('configuration',['login','rolecolors',
                 'quotas','autoenroll','autoupdate','autocreate',                  'quotas','autoenroll','autoupdate','autocreate',
                 'directorysrch','usercreation','usermodification',                  'directorysrch','usercreation','usermodification',
                 'contacts','defaults','scantron','coursecategories',                  'contacts','defaults','scantron','coursecategories',
                 'serverstatuses','requestcourses','helpsettings',                  'serverstatuses','requestcourses','coursedefaults',
                 'coursedefaults','usersessions'],$dom);                  'usersessions','loadbalancing','requestauthor',
                   'selfenrollment','inststatus'],$dom);
     my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',      my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
                        'autoupdate','autocreate','directorysrch','contacts',                         'autoupdate','autocreate','directorysrch','contacts',
                        'usercreation','usermodification','scantron',                         'usercreation','selfcreation','usermodification','scantron',
                        'requestcourses','coursecategories','serverstatuses','helpsettings',                         'requestcourses','requestauthor','coursecategories',
                        'coursedefaults','usersessions');                         'serverstatuses','coursedefaults','selfenrollment',
                          'usersessions');
       my %existing;
       if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
           %existing = %{$domconfig{'loadbalancing'}};
       }
       if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
           push(@prefs_order,'loadbalancing');
       }
     my %prefs = (      my %prefs = (
         'rolecolors' =>          'rolecolors' =>
                    { text => 'Default color schemes',                     { text => 'Default color schemes',
Line 221  sub handler { Line 241  sub handler {
                                  col2 => '',},                                   col2 => '',},
                                 {col1 => 'Administrator Settings',                                  {col1 => 'Administrator Settings',
                                  col2 => '',}],                                   col2 => '',}],
                         print => \&print_rolecolors,
                         modify => \&modify_rolecolors,
                     },                      },
         'login' =>          'login' =>
                     { text => 'Log-in page options',                      { text => 'Log-in page options',
                       help => 'Domain_Configuration_Login_Page',                        help => 'Domain_Configuration_Login_Page',
                       header => [{col1 => 'Item',                        header => [{col1 => 'Log-in Page Items',
                                   col2 => '',}],                                    col2 => '',},
                                    {col1 => 'Log-in Help',
                                     col2 => 'Value'}],
                         print => \&print_login,
                         modify => \&modify_login,
                     },                      },
   
         'defaults' =>           'defaults' => 
                     { text => 'Default authentication/language/timezone',                      { text => 'Default authentication/language/timezone/portal/types',
                       help => 'Domain_Configuration_LangTZAuth',                        help => 'Domain_Configuration_LangTZAuth',
                       header => [{col1 => 'Setting',                        header => [{col1 => 'Setting',
                                   col2 => 'Value'}],                                    col2 => 'Value'},
                                    {col1 => 'Institutional user types',
                                     col2 => 'Assignable to e-mail usernames'}],
                         print => \&print_defaults,
                         modify => \&modify_defaults,
                     },                      },
         'quotas' =>           'quotas' => 
                     { text => 'User blogs, personal information pages, portfolios',                      { text => 'Blogs, personal web pages, webDAV/quotas, portfolios',
                       help => 'Domain_Configuration_Quotas',                        help => 'Domain_Configuration_Quotas',
                       header => [{col1 => 'User affiliation',                        header => [{col1 => 'User affiliation',
                                   col2 => 'Available tools',                                    col2 => 'Available tools',
                                   col3 => 'Portfolio quota',}],                                    col3 => 'Quotas, MB; (Authoring requires role)',}],
                         print => \&print_quotas,
                         modify => \&modify_quotas,
                     },                      },
         'autoenroll' =>          'autoenroll' =>
                    { text => 'Auto-enrollment settings',                     { text => 'Auto-enrollment settings',
                      help => 'Domain_Configuration_Auto_Enrollment',                       help => 'Domain_Configuration_Auto_Enrollment',
                      header => [{col1 => 'Configuration setting',                       header => [{col1 => 'Configuration setting',
                                  col2 => 'Value(s)'}],                                   col2 => 'Value(s)'}],
                        print => \&print_autoenroll,
                        modify => \&modify_autoenroll,
                    },                     },
         'autoupdate' =>           'autoupdate' => 
                    { text => 'Auto-update settings',                     { text => 'Auto-update settings',
Line 256  sub handler { Line 289  sub handler {
                                 {col1 => 'Setting',                                  {col1 => 'Setting',
                                  col2 => 'Affiliation'},                                   col2 => 'Affiliation'},
                                 {col1 => 'User population',                                  {col1 => 'User population',
                                  col2 => 'Updateable user data'}],                                   col2 => 'Updatable user data'}],
                        print => \&print_autoupdate,
                        modify => \&modify_autoupdate,
                   },                    },
         'autocreate' =>           'autocreate' => 
                   { text => 'Auto-course creation settings',                    { text => 'Auto-course creation settings',
                      help => 'Domain_Configuration_Auto_Creation',                       help => 'Domain_Configuration_Auto_Creation',
                      header => [{col1 => 'Configuration Setting',                       header => [{col1 => 'Configuration Setting',
                                  col2 => 'Value',}],                                   col2 => 'Value',}],
                        print => \&print_autocreate,
                        modify => \&modify_autocreate,
                   },                    },
         'directorysrch' =>           'directorysrch' => 
                   { text => 'Institutional directory searches',                    { text => 'Institutional directory searches',
                     help => 'Domain_Configuration_InstDirectory_Search',                      help => 'Domain_Configuration_InstDirectory_Search',
                     header => [{col1 => 'Setting',                      header => [{col1 => 'Setting',
                                 col2 => 'Value',}],                                  col2 => 'Value',}],
                       print => \&print_directorysrch,
                       modify => \&modify_directorysrch,
                   },                    },
         'contacts' =>          'contacts' =>
                   { text => 'Contact Information',                    { text => 'Contact Information',
                     help => 'Domain_Configuration_Contact_Info',                      help => 'Domain_Configuration_Contact_Info',
                     header => [{col1 => 'Setting',                      header => [{col1 => 'Setting',
                                 col2 => 'Value',}],                                  col2 => 'Value',}],
                       print => \&print_contacts,
                       modify => \&modify_contacts,
                   },                    },
   
         'usercreation' =>           'usercreation' => 
                   { text => 'User creation',                    { text => 'User creation',
                     help => 'Domain_Configuration_User_Creation',                      help => 'Domain_Configuration_User_Creation',
Line 286  sub handler { Line 326  sub handler {
                                 col2 => 'Usernames which may be created',},                                  col2 => 'Usernames which may be created',},
                                {col1 => 'Context',                                 {col1 => 'Context',
                                 col2 => 'Assignable authentication types'}],                                  col2 => 'Assignable authentication types'}],
                       print => \&print_usercreation,
                       modify => \&modify_usercreation,
                     },
           'selfcreation' => 
                     { text => 'Users self-creating accounts',
                       help => 'Domain_Configuration_Self_Creation', 
                       header => [{col1 => 'Self-creation with institutional username',
                                   col2 => 'Enabled?'},
                                  {col1 => 'Institutional user type (login/SSO self-creation)',
                                   col2 => 'Information user can enter'},
                                  {col1 => 'Self-creation with e-mail as username',
                                   col2 => 'Settings'}],
                       print => \&print_selfcreation,
                       modify => \&modify_selfcreation,
                   },                    },
         'usermodification' =>          'usermodification' =>
                   { text => 'User modification',                    { text => 'User modification',
                     help => 'Domain_Configuration_User_Modification',                      help => 'Domain_Configuration_User_Modification',
                     header => [{col1 => 'Target user has role',                      header => [{col1 => 'Target user has role',
                                 col2 => 'User information updateable in author context'},                                  col2 => 'User information updatable in author context'},
                                {col1 => 'Target user has role',                                 {col1 => 'Target user has role',
                                 col2 => 'User information updateable in course context'},                                  col2 => 'User information updatable in course context'}],
                                {col1 => "Status of user",                      print => \&print_usermodification,
                                 col2 => 'Information settable when self-creating account (if directory data blank)'}],                      modify => \&modify_usermodification,
                   },                    },
         'scantron' =>          'scantron' =>
                   { text => 'Bubblesheet format file',                    { text => 'Bubblesheet format file',
Line 303  sub handler { Line 357  sub handler {
                     header => [ {col1 => 'Item',                      header => [ {col1 => 'Item',
                                  col2 => '',                                   col2 => '',
                               }],                                }],
                       print => \&print_scantron,
                       modify => \&modify_scantron,
                   },                    },
         'requestcourses' =>           'requestcourses' => 
                  {text => 'Request creation of courses',                   {text => 'Request creation of courses',
Line 310  sub handler { Line 366  sub handler {
                   header => [{col1 => 'User affiliation',                    header => [{col1 => 'User affiliation',
                               col2 => 'Availability/Processing of requests',},                                col2 => 'Availability/Processing of requests',},
                              {col1 => 'Setting',                               {col1 => 'Setting',
                                 col2 => 'Value'},
                                {col1 => 'Available textbooks',
                                 col2 => ''},
                                {col1 => 'Available templates',
                                 col2 => ''},
                                {col1 => 'Validation (not official courses)',
                                 col2 => 'Value'},],
                     print => \&print_quotas,
                     modify => \&modify_quotas,
                    },
           'requestauthor' =>
                    {text => 'Request Authoring Space',
                     help => 'Domain_Configuration_Request_Author',
                     header => [{col1 => 'User affiliation',
                                 col2 => 'Availability/Processing of requests',},
                                {col1 => 'Setting',
                               col2 => 'Value'}],                                col2 => 'Value'}],
                     print => \&print_quotas,
                     modify => \&modify_quotas,
                  },                   },
         'coursecategories' =>          'coursecategories' =>
                   { text => 'Cataloging of courses/communities',                    { text => 'Cataloging of courses/communities',
                     help => 'Domain_Configuration_Cataloging_Courses',                      help => 'Domain_Configuration_Cataloging_Courses',
                     header => [{col1 => 'Category settings',                      header => [{col1 => 'Catalog type/availability',
                                   col2 => '',},
                                  {col1 => 'Category settings for standard catalog',
                                 col2 => '',},                                  col2 => '',},
                                {col1 => 'Categories',                                 {col1 => 'Categories',
                                 col2 => '',                                  col2 => '',
                                }],                                 }],
                       print => \&print_coursecategories,
                       modify => \&modify_coursecategories,
                   },                    },
         'serverstatuses' =>          'serverstatuses' =>
                  {text   => 'Access to server status pages',                   {text   => 'Access to server status pages',
Line 328  sub handler { Line 406  sub handler {
                               col2 => 'Other named users',                                col2 => 'Other named users',
                               col3 => 'Specific IPs',                                col3 => 'Specific IPs',
                             }],                              }],
                  },                    print => \&print_serverstatuses,
         'helpsettings' =>                    modify => \&modify_serverstatuses,
                  {text   => 'Help page settings',  
                   help   => 'Domain_Configuration_Help_Settings',  
                   header => [{col1 => 'Authenticated Help Settings',  
                               col2 => ''},  
                              {col1 => 'Unauthenticated Help Settings',  
                               col2 => ''}],  
                  },                   },
         'coursedefaults' =>           'coursedefaults' => 
                  {text => 'Course/Community defaults',                   {text => 'Course/Community defaults',
                   help => 'Domain_Configuration_Course_Defaults',                    help => 'Domain_Configuration_Course_Defaults',
                   header => [{col1 => 'Defaults which can be overridden in each course by a CC',                    header => [{col1 => 'Defaults which can be overridden for each course by a DC',
                               col2 => 'Value',},  
                              {col1 => 'Defaults which can be overridden for each course by a DC',  
                               col2 => 'Value',},],                                col2 => 'Value',},],
                     print => \&print_coursedefaults,
                     modify => \&modify_coursedefaults,
                  },                   },
         'privacy' =>           'selfenrollment' => 
                  {text   => 'User Privacy',                   {text   => 'Self-enrollment in Course/Community',
                   help   => 'Domain_Configuration_User_Privacy',                    help   => 'Domain_Configuration_Selfenrollment',
                   header => [{col1 => 'Setting',                    header => [{col1 => 'Configuration Rights',
                               col2 => 'Value',}],                                col2 => 'Configured by Course Personnel or Domain Coordinator?'},
                                {col1 => 'Defaults',
                                 col2 => 'Value'},
                                {col1 => 'Self-enrollment validation (optional)',
                                 col2 => 'Value'},],
                     print => \&print_selfenrollment,
                     modify => \&modify_selfenrollment,
                  },                   },
          'usersessions' =>          'usersessions' =>
                  {text  => 'User session hosting',                   {text  => 'User session hosting/offloading',
                   help  => 'Domain_Configuration_User_Sessions',                    help  => 'Domain_Configuration_User_Sessions',
                   header => [{col1 => 'Hosting of users from other domains',                    header => [{col1 => 'Domain server',
                                 col2 => 'Servers to offload sessions to when busy'},
                                {col1 => 'Hosting of users from other domains',
                               col2 => 'Rules'},                                col2 => 'Rules'},
                              {col1 => "Hosting domain's own users elsewhere",                               {col1 => "Hosting domain's own users elsewhere",
                               col2 => 'Rules'}],                                col2 => 'Rules'}],
                     print => \&print_usersessions,
                     modify => \&modify_usersessions,
                    },
            'loadbalancing' =>
                    {text  => 'Dedicated Load Balancer(s)',
                     help  => 'Domain_Configuration_Load_Balancing',
                     header => [{col1 => 'Balancers',
                                 col2 => 'Default destinations',
                                 col3 => 'User affiliation',
                                 col4 => 'Overrides'},
                               ],
                     print => \&print_loadbalancing,
                     modify => \&modify_loadbalancing,
                  },                   },
     );      );
     my %servers = &dom_servers($dom);  
     if (keys(%servers) > 1) {      if (keys(%servers) > 1) {
         $prefs{'login'}  = { text   => 'Log-in page options',          $prefs{'login'}  = { text   => 'Log-in page options',
                              help   => 'Domain_Configuration_Login_Page',                               help   => 'Domain_Configuration_Login_Page',
                             header => [{col1 => 'Log-in Service',                              header => [{col1 => 'Log-in Service',
                                         col2 => 'Server Setting',},                                          col2 => 'Server Setting',},
                                        {col1 => 'Log-in Page Items',                                         {col1 => 'Log-in Page Items',
                                         col2 => ''}],                                          col2 => ''},
                                          {col1 => 'Log-in Help',
                                           col2 => 'Value'}],
                               print => \&print_login,
                               modify => \&modify_login,
                            };                             };
     }      }
   
     my @roles = ('student','coordinator','author','admin');      my @roles = ('student','coordinator','author','admin');
     my @actions = &Apache::loncommon::get_env_multiple('form.actions');      my @actions = &Apache::loncommon::get_env_multiple('form.actions');
     &Apache::lonhtmlcommon::add_breadcrumb      &Apache::lonhtmlcommon::add_breadcrumb
     ({href=>"javascript:changePage(document.$phase,'pickactions')",      ({href=>"javascript:changePage(document.$phase,'pickactions')",
       text=>"Settings to display/modify"});        text=>"Settings to display/modify"});
     my $confname = $dom.'-domainconfig';      my $confname = $dom.'-domainconfig';
   
     if ($phase eq 'process') {      if ($phase eq 'process') {
         &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,\@roles);          my $result = &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,
                                                                 \%prefs,\%domconfig,$confname,\@roles);
           if ((ref($result) eq 'HASH') && (keys(%{$result}))) {
               $r->rflush();
               &devalidate_remote_domconfs($dom,$result);
           }
     } elsif ($phase eq 'display') {      } elsif ($phase eq 'display') {
         &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname);          my $js = &recaptcha_js().
                    &toggle_display_js();
           if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
               my ($othertitle,$usertypes,$types) =
                   &Apache::loncommon::sorted_inst_types($dom);
               $js .= &lonbalance_targets_js($dom,$types,\%servers,
                                             $domconfig{'loadbalancing'}).
                      &new_spares_js().
                      &common_domprefs_js().
                      &Apache::loncommon::javascript_array_indexof();
           }
           if (grep(/^requestcourses$/,@actions)) {
               my $javascript_validations;
               my $coursebrowserjs=&Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'}); 
               $js .= <<END;
   <script type="text/javascript">
   $javascript_validations
   </script>
   $coursebrowserjs
   END
           }
           &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);
     } else {      } else {
   # check if domconfig user exists for the domain.
           my $servadm = $r->dir_config('lonAdmEMail');
           my ($configuserok,$author_ok,$switchserver) =
               &config_check($dom,$confname,$servadm);
           unless ($configuserok eq 'ok') {
               &Apache::lonconfigsettings::print_header($r,$phase,$context);
               $r->print(&mt('The domain configuration user "[_1]" has yet to be created.',
                             $confname).
                         '<br />'
               );
               if ($switchserver) {
                   $r->print(&mt('Ordinarily, that domain configuration user is created when the ./UPDATE script is run to install LON-CAPA for the first time.').
                             '<br />'.
                             &mt('However, that does not apply when new domains are added to a multi-domain server, and ./UPDATE has not been run recently.').
                             '<br />'.
                             &mt('The "[_1]" user can be created automatically when a Domain Coordinator visits the web-based "Set domain configuration" screen, in a session hosted on the primary library server.',$confname).
                             '<br />'.
                             &mt('To do that now, use the following link: [_1]',$switchserver)
                   );
               } else {
                   $r->print(&mt('To create that user from the command line run the ./UPDATE script found in the top level directory of the extracted LON-CAPA tarball.').
                             '<br />'.
                             &mt('Once that is done, you will be able to use the web-based "Set domain configuration" to configure the domain')
                   );
               }
               $r->print(&Apache::loncommon::end_page());
               return OK;
           }
         if (keys(%domconfig) == 0) {          if (keys(%domconfig) == 0) {
             my $primarylibserv = &Apache::lonnet::domain($dom,'primary');              my $primarylibserv = &Apache::lonnet::domain($dom,'primary');
             my @ids=&Apache::lonnet::current_machine_ids();              my @ids=&Apache::lonnet::current_machine_ids();
Line 420  sub handler { Line 572  sub handler {
 }  }
   
 sub process_changes {  sub process_changes {
     my ($r,$dom,$confname,$action,$roles,$values) = @_;      my ($r,$dom,$confname,$action,$roles,$values,$lastactref) = @_;
     my %domconfig;      my %domconfig;
     if (ref($values) eq 'HASH') {      if (ref($values) eq 'HASH') {
         %domconfig = %{$values};          %domconfig = %{$values};
     }      }
     my $output;      my $output;
     if ($action eq 'login') {      if ($action eq 'login') {
         $output = &modify_login($r,$dom,$confname,%domconfig);          $output = &modify_login($r,$dom,$confname,$lastactref,%domconfig);
     } elsif ($action eq 'rolecolors') {      } elsif ($action eq 'rolecolors') {
         $output = &modify_rolecolors($r,$dom,$confname,$roles,          $output = &modify_rolecolors($r,$dom,$confname,$roles,
                                      %domconfig);                                       $lastactref,%domconfig);
     } elsif ($action eq 'quotas') {      } elsif ($action eq 'quotas') {
         $output = &modify_quotas($dom,$action,%domconfig);          $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);
     } elsif ($action eq 'autoenroll') {      } elsif ($action eq 'autoenroll') {
         $output = &modify_autoenroll($dom,%domconfig);          $output = &modify_autoenroll($dom,$lastactref,%domconfig);
     } elsif ($action eq 'autoupdate') {      } elsif ($action eq 'autoupdate') {
         $output = &modify_autoupdate($dom,%domconfig);          $output = &modify_autoupdate($dom,%domconfig);
     } elsif ($action eq 'autocreate') {      } elsif ($action eq 'autocreate') {
Line 443  sub process_changes { Line 595  sub process_changes {
         $output = &modify_directorysrch($dom,%domconfig);          $output = &modify_directorysrch($dom,%domconfig);
     } elsif ($action eq 'usercreation') {      } elsif ($action eq 'usercreation') {
         $output = &modify_usercreation($dom,%domconfig);          $output = &modify_usercreation($dom,%domconfig);
       } elsif ($action eq 'selfcreation') {
           $output = &modify_selfcreation($dom,%domconfig);
     } elsif ($action eq 'usermodification') {      } elsif ($action eq 'usermodification') {
         $output = &modify_usermodification($dom,%domconfig);          $output = &modify_usermodification($dom,%domconfig);
     } elsif ($action eq 'contacts') {      } elsif ($action eq 'contacts') {
         $output = &modify_contacts($dom,%domconfig);          $output = &modify_contacts($dom,$lastactref,%domconfig);
     } elsif ($action eq 'defaults') {      } elsif ($action eq 'defaults') {
         $output = &modify_defaults($dom,$r);          $output = &modify_defaults($dom,$lastactref,%domconfig);
     } elsif ($action eq 'scantron') {      } elsif ($action eq 'scantron') {
         $output = &modify_scantron($r,$dom,$confname,%domconfig);          $output = &modify_scantron($r,$dom,$confname,$lastactref,%domconfig);
     } elsif ($action eq 'coursecategories') {      } elsif ($action eq 'coursecategories') {
         $output = &modify_coursecategories($dom,%domconfig);          $output = &modify_coursecategories($dom,$lastactref,%domconfig);
     } elsif ($action eq 'serverstatuses') {      } elsif ($action eq 'serverstatuses') {
         $output = &modify_serverstatuses($dom,%domconfig);          $output = &modify_serverstatuses($dom,%domconfig);
     } elsif ($action eq 'requestcourses') {      } elsif ($action eq 'requestcourses') {
         $output = &modify_quotas($dom,$action,%domconfig);          $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);
     } elsif ($action eq 'helpsettings') {      } elsif ($action eq 'requestauthor') {
         $output = &modify_helpsettings($r,$dom,$confname,%domconfig);          $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);
     } elsif ($action eq 'coursedefaults') {      } elsif ($action eq 'coursedefaults') {
         $output = &modify_coursedefaults($dom,%domconfig);          $output = &modify_coursedefaults($dom,$lastactref,%domconfig);
       } elsif ($action eq 'selfenrollment') {
           $output = &modify_selfenrollment($dom,$lastactref,%domconfig)
     } elsif ($action eq 'usersessions') {      } elsif ($action eq 'usersessions') {
         $output = &modify_usersessions($dom,%domconfig);          $output = &modify_usersessions($dom,$lastactref,%domconfig);
       } elsif ($action eq 'loadbalancing') {
           $output = &modify_loadbalancing($dom,%domconfig);
     }      }
     return $output;      return $output;
 }  }
Line 473  sub print_config_box { Line 631  sub print_config_box {
     my $output;      my $output;
     if ($action eq 'coursecategories') {      if ($action eq 'coursecategories') {
         $output = &coursecategories_javascript($settings);          $output = &coursecategories_javascript($settings);
       } elsif ($action eq 'defaults') {
           $output = &defaults_javascript($settings); 
     }      }
     $output .=       $output .=
          '<table class="LC_nested_outer">           '<table class="LC_nested_outer">
           <tr>            <tr>
            <th align="left" valign="middle"><span class="LC_nobreak">'.             <th align="left" valign="middle"><span class="LC_nobreak">'.
Line 488  sub print_config_box { Line 648  sub print_config_box {
     }      }
     if ($numheaders > 1) {      if ($numheaders > 1) {
         my $colspan = '';          my $colspan = '';
         if (($action eq 'rolecolors') || ($action eq 'coursecategories') || ($action eq 'helpsettings')) {          my $rightcolspan = '';
           if (($action eq 'rolecolors') || ($action eq 'defaults') ||
               (($action eq 'login') && ($numheaders < 3))) {
             $colspan = ' colspan="2"';              $colspan = ' colspan="2"';
         }          }
           if ($action eq 'usersessions') {
               $rightcolspan = ' colspan="3"'; 
           }
         $output .= '          $output .= '
           <tr>            <tr>
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[0]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[0]->{'col2'}).'</td>                <td class="LC_right_item"'.$rightcolspan.'>'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
              </tr>';               </tr>';
         $rowtotal ++;          $rowtotal ++;
         if ($action eq 'autoupdate') {          if (($action eq 'autoupdate') || ($action eq 'usercreation') || ($action eq 'selfcreation') ||
             $output .= &print_autoupdate('top',$dom,$settings,\$rowtotal);              ($action eq 'usermodification') || ($action eq 'defaults') ||
         } elsif ($action eq 'usercreation') {              ($action eq 'selfenrollment') || ($action eq 'usersessions')) {
             $output .= &print_usercreation('top',$dom,$settings,\$rowtotal);              $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'usermodification') {  
             $output .= &print_usermodification('top',$dom,$settings,\$rowtotal);  
         } elsif ($action eq 'coursecategories') {          } elsif ($action eq 'coursecategories') {
             $output .= &print_coursecategories('top',$dom,$item,$settings,\$rowtotal);              $output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal);
         } elsif ($action eq 'login') {          } elsif ($action eq 'login') {
             $output .= &print_login('top',$dom,$confname,$phase,$settings,\$rowtotal);              if ($numheaders == 3) {
             $colspan = ' colspan="2"';                  $colspan = ' colspan="2"';
         } elsif ($action eq 'requestcourses') {                  $output .= &print_login('service',$dom,$confname,$phase,$settings,\$rowtotal);
               } else {
                   $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal);
               }
           } elsif (($action eq 'requestcourses') || ($action eq 'requestauthor')) {
             $output .= &print_quotas($dom,$settings,\$rowtotal,$action);              $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
         } elsif ($action eq 'helpsettings') {  
             $output .= &print_helpsettings('top',$dom,$confname,$settings,\$rowtotal);  
         } elsif ($action eq 'usersessions') {  
             $output .= &print_usersessions('top',$dom,$settings,\$rowtotal);   
         } elsif ($action eq 'rolecolors') {          } elsif ($action eq 'rolecolors') {
             $output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal);              $output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal);
         } elsif ($action eq 'coursedefaults') {  
             $output .= &print_coursedefaults('top',$dom,$settings,\$rowtotal);  
         }          }
         $output .= '          $output .= '
            </table>             </table>
Line 530  sub print_config_box { Line 691  sub print_config_box {
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col1'}).'</td>';                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col1'}).'</td>
         $output .= '  
               <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col2'}).'</td>                <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col2'}).'</td>
              </tr>';               </tr>';
             $rowtotal ++;              $rowtotal ++;
         if ($action eq 'autoupdate') {          if (($action eq 'autoupdate') || ($action eq 'usercreation') ||
             $output .= &print_autoupdate('middle',$dom,$settings,\$rowtotal).'              ($action eq 'selfcreation') || ($action eq 'selfenrollment') ||
               ($action eq 'usersessions') || ($action eq 'coursecategories')) {
               if ($action eq 'coursecategories') {
                   $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);
                   $colspan = ' colspan="2"';
               } else {
                   $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);
               }
               $output .= '
            </table>             </table>
           </td>            </td>
          </tr>           </tr>
Line 545  sub print_config_box { Line 713  sub print_config_box {
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>      </tr>'.                <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
             &print_autoupdate('bottom',$dom,$settings,\$rowtotal);               </tr>'."\n";
               if ($action eq 'coursecategories') {
                   $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
               } else {
                   $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
               }
             $rowtotal ++;              $rowtotal ++;
         } elsif ($action eq 'usercreation') {          } elsif (($action eq 'usermodification') || ($action eq 'defaults')) {
             $output .= &print_usercreation('middle',$dom,$settings,\$rowtotal).'              $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
           } elsif ($action eq 'login') {
               if ($numheaders == 3) {
                   $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'
            </table>             </table>
           </td>            </td>
          </tr>           </tr>
Line 558  sub print_config_box { Line 734  sub print_config_box {
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>             </tr>'.                <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td></tr>'.
             &print_usercreation('bottom',$dom,$settings,\$rowtotal);                         &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);
                   $rowtotal ++;
               } else {
                   $output .= &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);
               }
           } elsif ($action eq 'requestcourses') {
               $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);
             $rowtotal ++;              $rowtotal ++;
         } elsif ($action eq 'usermodification') {              $output .= &print_studentcode($settings,\$rowtotal).'
             $output .= &print_usermodification('middle',$dom,$settings,\$rowtotal).'  
            </table>             </table>
           </td>            </td>
          </tr>           </tr>
Line 571  sub print_config_box { Line 752  sub print_config_box {
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>      </tr>'.                <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td> </tr>'.
                        &print_usermodification('bottom',$dom,$settings,\$rowtotal);                         &textbookcourses_javascript($settings).
                          &print_textbookcourses($dom,'textbooks',$settings,\$rowtotal).'
               </table>
              </td>
             </tr>
            <tr>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
                 <td class="LC_right_item">'.&mt($item->{'header'}->[3]->{'col2'}).'</td> </tr>'.
                          &print_textbookcourses($dom,'templates',$settings,\$rowtotal).'
               </table>
              </td>
             </tr>
             <tr>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.' valign="top">'.&mt($item->{'header'}->[4]->{'col1'}).'</td>
                 <td class="LC_right_item" valign="top">'.&mt($item->{'header'}->[4]->{'col2'}).'</td>
                </tr>'.
               &print_validation_rows('requestcourses',$dom,$settings,\$rowtotal);
           } elsif ($action eq 'requestauthor') {
               $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);
             $rowtotal ++;              $rowtotal ++;
         } elsif ($action eq 'coursecategories') {  
             $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);  
         } elsif ($action eq 'login') {  
             $output .= &print_login('bottom',$dom,$confname,$phase,$settings,\$rowtotal);  
         } elsif ($action eq 'requestcourses') {  
             $output .= &print_courserequestmail($dom,$settings,\$rowtotal);  
         } elsif ($action eq 'helpsettings') {  
             $output .= &print_helpsettings('bottom',$dom,$confname,$settings,\$rowtotal);  
         } elsif ($action eq 'usersessions') {  
             $output .= &print_usersessions('bottom',$dom,$settings,\$rowtotal);  
         } elsif ($action eq 'coursedefaults') {  
             $output .= &print_coursedefaults('bottom',$dom,$settings,\$rowtotal);  
         } elsif ($action eq 'rolecolors') {          } elsif ($action eq 'rolecolors') {
             $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'              $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'
            </table>             </table>
Line 644  sub print_config_box { Line 837  sub print_config_box {
         }          }
         $output .= '</td>';          $output .= '</td>';
         if ($item->{'header'}->[0]->{'col3'}) {          if ($item->{'header'}->[0]->{'col3'}) {
             $output .= '<td class="LC_right_item" valign="top">'.              if (defined($item->{'header'}->[0]->{'col4'})) {
                        &mt($item->{'header'}->[0]->{'col3'});                  $output .= '<td class="LC_left_item" valign="top">'.
                               &mt($item->{'header'}->[0]->{'col3'});
               } else {
                   $output .= '<td class="LC_right_item" valign="top">'.
                              &mt($item->{'header'}->[0]->{'col3'});
               }
             if ($action eq 'serverstatuses') {              if ($action eq 'serverstatuses') {
                 $output .= '<br />(<tt>'.&mt('IP1,IP2 etc.').'</tt>)';                  $output .= '<br />(<tt>'.&mt('IP1,IP2 etc.').'</tt>)';
             }              }
             $output .= '</td>';              $output .= '</td>';
         }          }
           if ($item->{'header'}->[0]->{'col4'}) {
               $output .= '<td class="LC_right_item" valign="top">'.
                          &mt($item->{'header'}->[0]->{'col4'});
           }
         $output .= '</tr>';          $output .= '</tr>';
         $rowtotal ++;          $rowtotal ++;
         if ($action eq 'login') {          if ($action eq 'quotas') {
             $output .= &print_login('bottom',$dom,$confname,$phase,$settings,  
                                     \$rowtotal);  
         } elsif ($action eq 'quotas') {  
             $output .= &print_quotas($dom,$settings,\$rowtotal,$action);              $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
         } elsif ($action eq 'autoenroll') {          } elsif (($action eq 'autoenroll') || ($action eq 'autocreate') || ($action eq 'directorysrch') ||
             $output .= &print_autoenroll($dom,$settings,\$rowtotal);                   ($action eq 'contacts') || ($action eq 'serverstatuses') || ($action eq 'loadbalancing')) {
         } elsif ($action eq 'autocreate') {              $output .= $item->{'print'}->($dom,$settings,\$rowtotal);
             $output .= &print_autocreate($dom,$settings,\$rowtotal);  
         } elsif ($action eq 'directorysrch') {  
             $output .= &print_directorysrch($dom,$settings,\$rowtotal);  
         } elsif ($action eq 'contacts') {  
             $output .= &print_contacts($dom,$settings,\$rowtotal);  
         } elsif ($action eq 'defaults') {  
             $output .= &print_defaults($dom,\$rowtotal);  
         } elsif ($action eq 'scantron') {          } elsif ($action eq 'scantron') {
             $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);              $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);
         } elsif ($action eq 'serverstatuses') {  
             $output .= &print_serverstatuses($dom,$settings,\$rowtotal);  
         } elsif ($action eq 'helpsettings') {          } elsif ($action eq 'helpsettings') {
             $output .= &print_helpsettings('top',$dom,$confname,$settings,\$rowtotal);              $output .= &print_helpsettings($dom,$confname,$settings,\$rowtotal);
           } elsif ($action eq 'coursedefaults') {
               $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
         }          }
     }      }
     $output .= '      $output .= '
Line 685  sub print_config_box { Line 877  sub print_config_box {
 }  }
   
 sub print_login {  sub print_login {
     my ($position,$dom,$confname,$phase,$settings,$rowtotal) = @_;      my ($caller,$dom,$confname,$phase,$settings,$rowtotal) = @_;
     my ($css_class,$datatable);      my ($css_class,$datatable);
     my %choices = &login_choices();      my %choices = &login_choices();
   
     if ($position eq 'top') {      if ($caller eq 'service') {
         my %servers = &dom_servers($dom);          my %servers = &Apache::lonnet::internet_dom_servers($dom);
         my $choice = $choices{'disallowlogin'};          my $choice = $choices{'disallowlogin'};
         $css_class = ' class="LC_odd_row"';          $css_class = ' class="LC_odd_row"';
         $datatable .= '<tr'.$css_class.'><td>'.$choice.'</td>'.          $datatable .= '<tr'.$css_class.'><td>'.$choice.'</td>'.
Line 716  sub print_login { Line 908  sub print_login {
                           '<td><select name="'.$lonhost.'_server">'.                            '<td><select name="'.$lonhost.'_server">'.
                           '<option value=""'.$direct.'>'.$choices{'directlogin'}.                            '<option value=""'.$direct.'>'.$choices{'directlogin'}.
                           '</option>';                            '</option>';
             foreach my $hostid (keys(%servers)) {              foreach my $hostid (sort(keys(%servers))) {
                 next if ($servers{$hostid} eq $servers{$lonhost});                  next if ($servers{$hostid} eq $servers{$lonhost});
                 my $selected = '';                  my $selected = '';
                 if (ref($disallowed{$lonhost}) eq 'HASH') {                  if (ref($disallowed{$lonhost}) eq 'HASH') {
Line 756  sub print_login { Line 948  sub print_login {
         }          }
         $datatable .= '</table></td></tr>';          $datatable .= '</table></td></tr>';
         return $datatable;          return $datatable;
     }      } elsif ($caller eq 'page') {
           my %defaultchecked = ( 
     my %defaultchecked = (                                  'coursecatalog' => 'on',
                            'coursecatalog' => 'on',                                 'helpdesk'      => 'on',
                            'adminmail'     => 'off',                                 'adminmail'     => 'off',
                            'newuser'       => 'off',                                 'newuser'       => 'off',
                          );                               );
     my @toggles = ('coursecatalog','adminmail','newuser');          my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');
     my (%checkedon,%checkedoff);          my (%checkedon,%checkedoff);
     foreach my $item (@toggles) {  
         if ($defaultchecked{$item} eq 'on') {   
             $checkedon{$item} = ' checked="checked" ';  
             $checkedoff{$item} = ' ';  
         } elsif ($defaultchecked{$item} eq 'off') {  
             $checkedoff{$item} = ' checked="checked" ';  
             $checkedon{$item} = ' ';  
         }  
     }  
     my @images = ('img','logo','domlogo','login');  
     my @logintext = ('textcol','bgcol');  
     my @bgs = ('pgbg','mainbg','sidebg');  
     my @links = ('link','alink','vlink');  
     my %designhash = &Apache::loncommon::get_domainconf($dom);  
     my %defaultdesign = %Apache::loncommon::defaultdesign;  
     my (%is_custom,%designs);  
     my %defaults = (  
                    font => $defaultdesign{'login.font'},  
                    );  
     foreach my $item (@images) {  
         $defaults{$item} = $defaultdesign{'login.'.$item};  
         $defaults{'showlogo'}{$item} = 1;  
     }  
     foreach my $item (@bgs) {  
         $defaults{'bgs'}{$item} = $defaultdesign{'login.'.$item};  
     }  
     foreach my $item (@logintext) {  
         $defaults{'logintext'}{$item} = $defaultdesign{'login.'.$item};  
     }  
     foreach my $item (@links) {  
         $defaults{'links'}{$item} = $defaultdesign{'login.'.$item};  
     }  
     if (ref($settings) eq 'HASH') {  
         foreach my $item (@toggles) {          foreach my $item (@toggles) {
             if ($settings->{$item} eq '1') {              if ($defaultchecked{$item} eq 'on') { 
                 $checkedon{$item} =  ' checked="checked" ';                  $checkedon{$item} = ' checked="checked" ';
                 $checkedoff{$item} = ' ';                  $checkedoff{$item} = ' ';
             } elsif ($settings->{$item} eq '0') {              } elsif ($defaultchecked{$item} eq 'off') {
                 $checkedoff{$item} =  ' checked="checked" ';                  $checkedoff{$item} = ' checked="checked" ';
                 $checkedon{$item} = ' ';                  $checkedon{$item} = ' ';
             }              }
         }          }
           my @images = ('img','logo','domlogo','login');
           my @logintext = ('textcol','bgcol');
           my @bgs = ('pgbg','mainbg','sidebg');
           my @links = ('link','alink','vlink');
           my %designhash = &Apache::loncommon::get_domainconf($dom);
           my %defaultdesign = %Apache::loncommon::defaultdesign;
           my (%is_custom,%designs);
           my %defaults = (
                          font => $defaultdesign{'login.font'},
                          );
         foreach my $item (@images) {          foreach my $item (@images) {
             if (defined($settings->{$item})) {              $defaults{$item} = $defaultdesign{'login.'.$item};
                 $designs{$item} = $settings->{$item};              $defaults{'showlogo'}{$item} = 1;
                 $is_custom{$item} = 1;          }
             }          foreach my $item (@bgs) {
             if (defined($settings->{'showlogo'}{$item})) {              $defaults{'bgs'}{$item} = $defaultdesign{'login.'.$item};
                 $designs{'showlogo'}{$item} = $settings->{'showlogo'}{$item};  
             }  
         }          }
         foreach my $item (@logintext) {          foreach my $item (@logintext) {
             if ($settings->{$item} ne '') {              $defaults{'logintext'}{$item} = $defaultdesign{'login.'.$item};
                 $designs{'logintext'}{$item} = $settings->{$item};  
                 $is_custom{$item} = 1;  
             }  
         }          }
         if ($settings->{'font'} ne '') {          foreach my $item (@links) {
             $designs{'font'} = $settings->{'font'};              $defaults{'links'}{$item} = $defaultdesign{'login.'.$item};
             $is_custom{'font'} = 1;  
         }          }
         foreach my $item (@bgs) {          if (ref($settings) eq 'HASH') {
             if ($settings->{$item} ne '') {              foreach my $item (@toggles) {
                 $designs{'bgs'}{$item} = $settings->{$item};                  if ($settings->{$item} eq '1') {
                 $is_custom{$item} = 1;                      $checkedon{$item} =  ' checked="checked" ';
                       $checkedoff{$item} = ' ';
                   } elsif ($settings->{$item} eq '0') {
                       $checkedoff{$item} =  ' checked="checked" ';
                       $checkedon{$item} = ' ';
                   }
             }              }
         }              foreach my $item (@images) {
         foreach my $item (@links) {                  if (defined($settings->{$item})) {
             if ($settings->{$item} ne '') {                      $designs{$item} = $settings->{$item};
                 $designs{'links'}{$item} = $settings->{$item};                      $is_custom{$item} = 1;
                 $is_custom{$item} = 1;                  }
                   if (defined($settings->{'showlogo'}{$item})) {
                       $designs{'showlogo'}{$item} = $settings->{'showlogo'}{$item};
                   }
             }              }
         }              foreach my $item (@logintext) {
     } else {                  if ($settings->{$item} ne '') {
         if ($designhash{$dom.'.login.font'} ne '') {                      $designs{'logintext'}{$item} = $settings->{$item};
             $designs{'font'} = $designhash{$dom.'.login.font'};                      $is_custom{$item} = 1;
             $is_custom{'font'} = 1;                  }
         }              }
         foreach my $item (@images) {              if ($settings->{'font'} ne '') {
             if ($designhash{$dom.'.login.'.$item} ne '') {                  $designs{'font'} = $settings->{'font'};
                 $designs{$item} = $designhash{$dom.'.login.'.$item};                  $is_custom{'font'} = 1;
                 $is_custom{$item} = 1;              }
               foreach my $item (@bgs) {
                   if ($settings->{$item} ne '') {
                       $designs{'bgs'}{$item} = $settings->{$item};
                       $is_custom{$item} = 1;
                   }
               }
               foreach my $item (@links) {
                   if ($settings->{$item} ne '') {
                       $designs{'links'}{$item} = $settings->{$item};
                       $is_custom{$item} = 1;
                   }
               }
           } else {
               if ($designhash{$dom.'.login.font'} ne '') {
                   $designs{'font'} = $designhash{$dom.'.login.font'};
                   $is_custom{'font'} = 1;
               }
               foreach my $item (@images) {
                   if ($designhash{$dom.'.login.'.$item} ne '') {
                       $designs{$item} = $designhash{$dom.'.login.'.$item};
                       $is_custom{$item} = 1;
                   }
               }
               foreach my $item (@bgs) {
                   if ($designhash{$dom.'.login.'.$item} ne '') {
                       $designs{'bgs'}{$item} = $designhash{$dom.'.login.'.$item};
                       $is_custom{$item} = 1;
                   }
               }
               foreach my $item (@links) {
                   if ($designhash{$dom.'.login.'.$item} ne '') {
                       $designs{'links'}{$item} = $designhash{$dom.'.login.'.$item};
                       $is_custom{$item} = 1;
                   }
             }              }
         }          }
         foreach my $item (@bgs) {          my %alt_text = &Apache::lonlocal::texthash  ( img => 'Log-in banner',
             if ($designhash{$dom.'.login.'.$item} ne '') {                                                        logo => 'Institution Logo',
                 $designs{'bgs'}{$item} = $designhash{$dom.'.login.'.$item};                                                        domlogo => 'Domain Logo',
                 $is_custom{$item} = 1;                                                        login => 'Login box');
           my $itemcount = 1;
           foreach my $item (@toggles) {
               $css_class = $itemcount%2?' class="LC_odd_row"':'';
               $datatable .=  
                   '<tr'.$css_class.'><td colspan="2">'.$choices{$item}.
                   '</td><td>'.
                   '<span class="LC_nobreak"><label><input type="radio" name="'.
                   $item.'"'.$checkedon{$item}.' value="1" />'.&mt('Yes').
                   '</label>&nbsp;<label><input type="radio" name="'.$item.'"'.
                   $checkedoff{$item}.' value="0" />'.&mt('No').'</label></span></td>'.
                   '</tr>';
               $itemcount ++;
           }
           $datatable .= &display_color_options($dom,$confname,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal,\@logintext);
           $datatable .= '</tr></table></td></tr>';
       } elsif ($caller eq 'help') {
           my ($defaulturl,$defaulttype,%url,%type,%lt,%langchoices);
           my $switchserver = &check_switchserver($dom,$confname);
           my $itemcount = 1;
           $defaulturl = '/adm/loginproblems.html';
           $defaulttype = 'default';
           %lt = &Apache::lonlocal::texthash (
                        del     => 'Delete?',
                        rep     => 'Replace:',
                        upl     => 'Upload:',
                        default => 'Default',
                        custom  => 'Custom',
                                                );
           %langchoices = &Apache::lonlocal::texthash(&get_languages_hash());
           my @currlangs;
           if (ref($settings) eq 'HASH') {
               if (ref($settings->{'helpurl'}) eq 'HASH') {
                   foreach my $key (sort(keys(%{$settings->{'helpurl'}}))) {
                       next if ($settings->{'helpurl'}{$key} eq '');
                       $url{$key} = $settings->{'helpurl'}{$key}.'?inhibitmenu=yes';
                       $type{$key} = 'custom';
                       unless ($key eq 'nolang') {
                           push(@currlangs,$key);
                       }
                   }
               } elsif ($settings->{'helpurl'} ne '') {
                   $type{'nolang'} = 'custom';
                   $url{'nolang'} = $settings->{'helpurl'}.'?inhibitmenu=yes';
               }
           }
           foreach my $lang ('nolang',sort(@currlangs)) {
               $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
               $datatable .= '<tr'.$css_class.'>';
               if ($url{$lang} eq '') {
                   $url{$lang} = $defaulturl;
               }
               if ($type{$lang} eq '') {
                   $type{$lang} = $defaulttype;
               }
               $datatable .= '<td colspan="2"><span class="LC_nobreak">';
               if ($lang eq 'nolang') {
                   $datatable .= &mt('Log-in help page if no specific language file: [_1]',
                                     &Apache::loncommon::modal_link($url{$lang},$lt{$type{$lang}},600,500));
               } else {
                   $datatable .= &mt('Log-in help page for language: [_1] is [_2]',
                                     $langchoices{$lang},
                                     &Apache::loncommon::modal_link($url{$lang},$lt{$type{$lang}},600,500));
               }
               $datatable .= '</span></td>'."\n".
                             '<td class="LC_left_item">';
               if ($type{$lang} eq 'custom') {
                   $datatable .= '<span class="LC_nobreak"><label>'.
                                 '<input type="checkbox" name="loginhelpurl_del" value="'.$lang.'" />'.
                                 $lt{'del'}.'</label>&nbsp;'.$lt{'rep'}.'</span>';
               } else {
                   $datatable .= $lt{'upl'};
             }              }
               $datatable .='<br />';
               if ($switchserver) {
                   $datatable .= &mt('Upload to library server: [_1]',$switchserver);
               } else {
                   $datatable .= '<input type="file" name="loginhelpurl_'.$lang.'" />';
               }
               $datatable .= '</td></tr>';
               $itemcount ++;
         }          }
         foreach my $item (@links) {          my @addlangs;
             if ($designhash{$dom.'.login.'.$item} ne '') {          foreach my $lang (sort(keys(%langchoices))) {
                 $designs{'links'}{$item} = $designhash{$dom.'.login.'.$item};              next if ((grep(/^\Q$lang\E$/,@currlangs)) || ($lang eq 'x_chef'));
                 $is_custom{$item} = 1;              push(@addlangs,$lang);
           }
           if (@addlangs > 0) {
               my %toadd;
               map { $toadd{$_} = $langchoices{$_} ; } @addlangs;
               $toadd{''} = &mt('Select');
               $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
               $datatable .= '<tr'.$css_class.'><td class="LC_left_item" colspan="2">'.
                             &mt('Add log-in help page for a specific language:').'&nbsp;'.
                             &Apache::loncommon::select_form('','loginhelpurl_add_lang',\%toadd).
                             '</td><td class="LC_left_item">'.$lt{'upl'}.'<br />';
               if ($switchserver) {
                   $datatable .= &mt('Upload to library server: [_1]',$switchserver);
               } else {
                   $datatable .= '<input type="file" name="loginhelpurl_add_file" />';
             }              }
               $datatable .= '</td></tr>';
               $itemcount ++;
         }          }
           $datatable .= &captcha_choice('login',$settings,$itemcount);
     }      }
     my %alt_text = &Apache::lonlocal::texthash  ( img => 'Log-in banner',  
                                                   logo => 'Institution Logo',  
                                                   domlogo => 'Domain Logo',  
                                                   login => 'Login box');  
     my $itemcount = 1;  
     my ($css_class,$datatable);  
     foreach my $item (@toggles) {  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .=    
             '<tr'.$css_class.'><td colspan="2">'.$choices{$item}.  
             '</td><td>'.  
             '<span class="LC_nobreak"><label><input type="radio" name="'.  
             $item.'"'.$checkedon{$item}.' value="1" />'.&mt('Yes').  
             '</label>&nbsp;<label><input type="radio" name="'.$item.'"'.  
             $checkedoff{$item}.' value="0" />'.&mt('No').'</label></span></td>'.  
             '</tr>';  
         $itemcount ++;  
     }  
     $datatable .= &display_color_options($dom,$confname,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal,\@logintext);  
     $datatable .= '</tr></table></td></tr>';  
     return $datatable;      return $datatable;
 }  }
   
Line 890  sub login_choices { Line 1171  sub login_choices {
         &Apache::lonlocal::texthash (          &Apache::lonlocal::texthash (
             coursecatalog => 'Display Course/Community Catalog link?',              coursecatalog => 'Display Course/Community Catalog link?',
             adminmail     => "Display Administrator's E-mail Address?",              adminmail     => "Display Administrator's E-mail Address?",
               helpdesk      => 'Display "Contact Helpdesk" link',
             disallowlogin => "Login page requests redirected",              disallowlogin => "Login page requests redirected",
             hostid        => "Server",              hostid        => "Server",
             server        => "Redirect to:",              server        => "Redirect to:",
Line 927  sub print_rolecolors { Line 1209  sub print_rolecolors {
     my %designhash = &Apache::loncommon::get_domainconf($dom);      my %designhash = &Apache::loncommon::get_domainconf($dom);
     my %defaultdesign = %Apache::loncommon::defaultdesign;      my %defaultdesign = %Apache::loncommon::defaultdesign;
     my (%is_custom,%designs);      my (%is_custom,%designs);
     my %defaults = (      my %defaults = &role_defaults($role,\@bgs,\@links,\@images);
                    img => $defaultdesign{$role.'.img'},  
                    font => $defaultdesign{$role.'.font'},  
    fontmenu => $defaultdesign{$role.'.fontmenu'},  
                    );  
     foreach my $item (@bgs) {  
         $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item};  
     }  
     foreach my $item (@links) {  
         $defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item};  
     }  
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{$role}) eq 'HASH') {          if (ref($settings->{$role}) eq 'HASH') {
             if ($settings->{$role}->{'img'} ne '') {              if ($settings->{$role}->{'img'} ne '') {
Line 998  sub print_rolecolors { Line 1270  sub print_rolecolors {
     return $datatable;      return $datatable;
 }  }
   
   sub role_defaults {
       my ($role,$bgs,$links,$images,$logintext) = @_;
       my %defaults;
       unless ((ref($bgs) eq 'ARRAY') && (ref($links) eq 'ARRAY') && (ref($images) eq 'ARRAY')) {
           return %defaults;
       }
       my %defaultdesign = %Apache::loncommon::defaultdesign;
       if ($role eq 'login') {
           %defaults = (
                          font => $defaultdesign{$role.'.font'},
                       );
           if (ref($logintext) eq 'ARRAY') {
               foreach my $item (@{$logintext}) {
                   $defaults{'logintext'}{$item} = $defaultdesign{$role.'.'.$item};
               }
           }
           foreach my $item (@{$images}) {
               $defaults{'showlogo'}{$item} = 1;
           }
       } else {
           %defaults = (
                          img => $defaultdesign{$role.'.img'},
                          font => $defaultdesign{$role.'.font'},
                          fontmenu => $defaultdesign{$role.'.fontmenu'},
                       );
       }
       foreach my $item (@{$bgs}) {
           $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item};
       }
       foreach my $item (@{$links}) {
           $defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item};
       }
       foreach my $item (@{$images}) {
           $defaults{$item} = $defaultdesign{$role.'.'.$item};
       }
       return %defaults;
   }
   
 sub display_color_options {  sub display_color_options {
     my ($dom,$confname,$phase,$role,$itemcount,$choices,$is_custom,$defaults,$designs,      my ($dom,$confname,$phase,$role,$itemcount,$choices,$is_custom,$defaults,$designs,
         $images,$bgs,$links,$alt_text,$rowtotal,$logintext) = @_;          $images,$bgs,$links,$alt_text,$rowtotal,$logintext) = @_;
       my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
     my $css_class = $itemcount%2?' class="LC_odd_row"':'';      my $css_class = $itemcount%2?' class="LC_odd_row"':'';
     my $datatable = '<tr'.$css_class.'>'.      my $datatable = '<tr'.$css_class.'>'.
         '<td>'.$choices->{'font'}.'</td>';          '<td>'.$choices->{'font'}.'</td>';
Line 1009  sub display_color_options { Line 1320  sub display_color_options {
     } else {      } else {
         $datatable .= '<td>&nbsp;</td>';          $datatable .= '<td>&nbsp;</td>';
     }      }
     my $fontlink = &color_pick($phase,$role,'font',$choices->{'font'},$designs->{'font'});      my $current_color = $designs->{'font'} ? $designs->{'font'} : $defaults->{'font'};
   
     $datatable .= '<td><span class="LC_nobreak">'.      $datatable .= '<td><span class="LC_nobreak">'.
                   '<input type="text" size="10" name="'.$role.'_font"'.                    '<input type="text" class="colorchooser" size="10" name="'.$role.'_font"'.
                   ' value="'.$designs->{'font'}.'" />&nbsp;'.$fontlink.                    ' value="'.$current_color.'" />&nbsp;'.
                   '&nbsp;<span id="css_'.$role.'_font" style="background-color: '.                    '&nbsp;</td></tr>';
                   $designs->{'font'}.';">&nbsp;&nbsp;&nbsp;</span>'.  
                   '</span></td></tr>';  
     unless ($role eq 'login') {       unless ($role eq 'login') { 
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                       '<td>'.$choices->{'fontmenu'}.'</td>';                        '<td>'.$choices->{'fontmenu'}.'</td>';
Line 1024  sub display_color_options { Line 1334  sub display_color_options {
         } else {          } else {
             $datatable .= '<td>&nbsp;</td>';              $datatable .= '<td>&nbsp;</td>';
         }          }
         $fontlink = &color_pick($phase,$role,'fontmenu',$choices->{'fontmenu'},$designs->{'fontmenu'});   $current_color = $designs->{'fontmenu'} ?
       $designs->{'fontmenu'} : $defaults->{'fontmenu'};
         $datatable .= '<td><span class="LC_nobreak">'.          $datatable .= '<td><span class="LC_nobreak">'.
                       '<input type="text" size="10" name="'.$role.'_fontmenu"'.                        '<input class="colorchooser" type="text" size="10" name="'
                       ' value="'.$designs->{'fontmenu'}.'" />&nbsp;'.$fontlink.        .$role.'_fontmenu"'.
                       '&nbsp;<span id="css_'.$role.'_fontmenu" style="background-color: '.                        ' value="'.$current_color.'" />&nbsp;'.
                       $designs->{'fontmenu'}.';">&nbsp;&nbsp;&nbsp;</span>'.                        '&nbsp;</td></tr>';
                       '</span></td></tr>';  
     }      }
     my $switchserver = &check_switchserver($dom,$confname);      my $switchserver = &check_switchserver($dom,$confname);
     foreach my $img (@{$images}) {      foreach my $img (@{$images}) {
Line 1045  sub display_color_options { Line 1355  sub display_color_options {
                     &login_header_options($img,$role,$defaults,$is_custom,$choices);                      &login_header_options($img,$role,$defaults,$is_custom,$choices);
                 $logincolors =                  $logincolors =
                     &login_text_colors($img,$role,$logintext,$phase,$choices,                      &login_text_colors($img,$role,$logintext,$phase,$choices,
                                             $designs);                                         $designs,$defaults);
             } elsif ($img ne 'domlogo') {              } elsif ($img ne 'domlogo') {
                 $datatable.= &logo_display_options($img,$defaults,$designs);                  $datatable.= &logo_display_options($img,$defaults,$designs);
             }              }
Line 1078  sub display_color_options { Line 1388  sub display_color_options {
                 $showfile = $imgfile;                  $showfile = $imgfile;
                 my $imgdir = $1;                  my $imgdir = $1;
                 my $filename = $2;                  my $filename = $2;
                 if (-e "/home/httpd/html/$imgdir/tn-".$filename) {                  if (-e "$londocroot/$imgdir/tn-".$filename) {
                     $showfile = "/$imgdir/tn-".$filename;                      $showfile = "/$imgdir/tn-".$filename;
                 } else {                  } else {
                     my $input = "/home/httpd/html".$imgfile;                      my $input = $londocroot.$imgfile;
                     my $output = '/home/httpd/html/'.$imgdir.'/tn-'.$filename;                      my $output = "$londocroot/$imgdir/tn-".$filename;
                     if (!-e $output) {                      if (!-e $output) {
                         my ($width,$height) = &thumb_dimensions();                          my ($width,$height) = &thumb_dimensions();
                         my ($fullwidth,$fullheight) = &check_dimensions($input);                          my ($fullwidth,$fullheight) = &check_dimensions($input);
Line 1090  sub display_color_options { Line 1400  sub display_color_options {
                             if ($fullwidth > $width && $fullheight > $height) {                               if ($fullwidth > $width && $fullheight > $height) { 
                                 my $size = $width.'x'.$height;                                  my $size = $width.'x'.$height;
                                 system("convert -sample $size $input $output");                                  system("convert -sample $size $input $output");
                                 $showfile = '/'.$imgdir.'/tn-'.$filename;                                  $showfile = "/$imgdir/tn-".$filename;
                             }                              }
                         }                          }
                     }                      }
Line 1124  sub display_color_options { Line 1434  sub display_color_options {
                 $datatable .= &image_changes($is_custom->{$img},$alt_text->{$img},$img_import,                  $datatable .= &image_changes($is_custom->{$img},$alt_text->{$img},$img_import,
                                              $showfile,$fullsize,$role,$img,$imgfile,$logincolors);                                               $showfile,$fullsize,$role,$img,$imgfile,$logincolors);
             } else {              } else {
                 $datatable .= '<td colspan="2" class="LC_right_item"><br />'.                  $datatable .= '<td>&nbsp;</td><td class="LC_left_item">'.
                               &mt('Upload:');                                &mt('Upload:').'<br />';
             }              }
         } else {          } else {
             $datatable .= '<td colspan="2" class="LC_right_item"><br />'.              $datatable .= '<td>&nbsp;</td><td class="LC_left_item">'.
                           &mt('Upload:');                            &mt('Upload:').'<br />';
         }          }
         if ($switchserver) {          if ($switchserver) {
             $datatable .= &mt('Upload to library server: [_1]',$switchserver);              $datatable .= &mt('Upload to library server: [_1]',$switchserver);
Line 1157  sub display_color_options { Line 1467  sub display_color_options {
     }      }
     $datatable .= '<td class="LC_right_item">'.      $datatable .= '<td class="LC_right_item">'.
                   '<table border="0"><tr>';                    '<table border="0"><tr>';
   
     foreach my $item (@{$bgs}) {      foreach my $item (@{$bgs}) {
         my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'bgs'}{$item});          $datatable .= '<td align="center">'.$choices->{$item};
         $datatable .= '<td align="center">'.$link;   my $color = $designs->{'bgs'}{$item} ? $designs->{'bgs'}{$item} : $defaults->{'bgs'}{$item};
         if ($designs->{'bgs'}{$item}) {          if ($designs->{'bgs'}{$item}) {
             $datatable .= '&nbsp;<span id="css_'.$role.'_'.$item.'" style="background-color: '.$designs->{'bgs'}{$item}.';">&nbsp;&nbsp;&nbsp;</span>';              $datatable .= '&nbsp;';
         }          }
         $datatable .= '<br /><input type="text" size="8" name="'.$role.'_'.$item.'" value="'.$designs->{'bgs'}{$item}.          $datatable .= '<br /><input type="text" class="colorchooser" size="8" name="'.$role.'_'.$item.'" value="'.$color.
                       '" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>';                        '" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>';
     }      }
     $datatable .= '</tr></table></td></tr>';      $datatable .= '</tr></table></td></tr>';
Line 1185  sub display_color_options { Line 1496  sub display_color_options {
     $datatable .= '<td class="LC_right_item">'.      $datatable .= '<td class="LC_right_item">'.
                   '<table border="0"><tr>';                    '<table border="0"><tr>';
     foreach my $item (@{$links}) {      foreach my $item (@{$links}) {
         $datatable .= '<td align="center">'."\n".   my $color = $designs->{'links'}{$item} ? $designs->{'links'}{$item} : $defaults->{'links'}{$item};
                       &color_pick($phase,$role,$item,$choices->{$item},          $datatable .= '<td align="center">'.$choices->{$item}."\n";
                                   $designs->{'links'}{$item});  
         if ($designs->{'links'}{$item}) {          if ($designs->{'links'}{$item}) {
             $datatable.='&nbsp;<span id="css_'.$role.'_'.$item.'" style="background-color: '.$designs->{'links'}{$item}.';">&nbsp;&nbsp;&nbsp;</span>';              $datatable.='&nbsp;';
         }          }
         $datatable .= '<br /><input type="text" size="8" name="'.$role.'_'.$item.'" value="'.$designs->{'links'}{$item}.          $datatable .= '<br /><input type="text" size="8" class="colorchooser" name="'.$role.'_'.$item.'" value="'.$color.
                       '" /></td>';                        '" /></td>';
     }      }
     $$rowtotal += $itemcount;      $$rowtotal += $itemcount;
Line 1245  sub login_header_options  { Line 1555  sub login_header_options  {
 }  }
   
 sub login_text_colors {  sub login_text_colors {
     my ($img,$role,$logintext,$phase,$choices,$designs) = @_;      my ($img,$role,$logintext,$phase,$choices,$designs,$defaults) = @_;
     my $color_menu = '<table border="0"><tr>';      my $color_menu = '<table border="0"><tr>';
     foreach my $item (@{$logintext}) {      foreach my $item (@{$logintext}) {
         my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'logintext'}{$item});          $color_menu .= '<td align="center">'.$choices->{$item};
         $color_menu .= '<td align="center">'.$link;          my $color = $designs->{'logintext'}{$item} ? $designs->{'logintext'}{$item} : $defaults->{'logintext'}{$item};
         if ($designs->{'logintext'}{$item}) {          $color_menu .= '<br /><input type="text" class="colorchooser" size="8" name="'.$role.'_'.$item.'" value="'.$color.
             $color_menu .= '&nbsp;<span id="css_'.$role.'_'.$item.'" style="background-color: '.$designs->{'logintext'}{$item}.';">&nbsp;&nbsp;&nbsp;</span>';                        '" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>';
         }  
         $color_menu .= '<br /><input type="text" size="8" name="'.$role.'_'.$item.'" value="'.  
                        $designs->{'logintext'}{$item}.'" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>'.  
                        '<td>&nbsp;</td>';  
     }      }
     $color_menu .= '</tr></table><br />';      $color_menu .= '</tr></table><br />';
     return $color_menu;      return $color_menu;
Line 1287  sub image_changes { Line 1593  sub image_changes {
                        $role.'_del_'.$img.'" value="1" />'.&mt('Delete?').                         $role.'_del_'.$img.'" value="1" />'.&mt('Delete?').
                        '</label>&nbsp;'.&mt('Replace:').'</span><br />';                         '</label>&nbsp;'.&mt('Replace:').'</span><br />';
         } else {          } else {
             $output .= '<td valign="bottom">'.$logincolors.&mt('Upload:').'<br />';              $output .= '<td valign="middle">'.$logincolors.&mt('Upload:').'<br />';
         }          }
     }      }
     return $output;      return $output;
 }  }
   
 sub color_pick {  
     my ($phase,$role,$item,$desc,$curcol) = @_;  
     my $link = '<a href="javascript:pjump('."'color_custom','".$desc.  
                "','".$curcol."','".$role.'_'.$item."','parmform.pres','psub'".  
                ');">'.$desc.'</a>';  
     return $link;  
 }  
   
 sub print_quotas {  sub print_quotas {
     my ($dom,$settings,$rowtotal,$action) = @_;      my ($dom,$settings,$rowtotal,$action) = @_;
     my $context;      my $context;
Line 1309  sub print_quotas { Line 1607  sub print_quotas {
     } else {      } else {
         $context = $action;          $context = $action;
     }      }
     my ($datatable,$defaultquota,@usertools,@options,%validations);      my ($datatable,$defaultquota,$authorquota,@usertools,@options,%validations);
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);      my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
     my $typecount = 0;      my $typecount = 0;
     my ($css_class,%titles);      my ($css_class,%titles);
     if ($context eq 'requestcourses') {      if ($context eq 'requestcourses') {
         @usertools = ('official','unofficial','community');          @usertools = ('official','unofficial','community','textbook');
         @options =('norequest','approval','validate','autolimit');          @options =('norequest','approval','validate','autolimit');
         %validations = &Apache::lonnet::auto_courserequest_checks($dom);          %validations = &Apache::lonnet::auto_courserequest_checks($dom);
         %titles = &courserequest_titles();          %titles = &courserequest_titles();
       } elsif ($context eq 'requestauthor') {
           @usertools = ('author');
           @options = ('norequest','approval','automatic');
           %titles = &authorrequest_titles();
     } else {      } else {
         @usertools = ('aboutme','blog','portfolio');          @usertools = ('aboutme','blog','webdav','portfolio');
         %titles = &tool_titles();          %titles = &tool_titles();
     }      }
     if (ref($types) eq 'ARRAY') {      if (ref($types) eq 'ARRAY') {
         foreach my $type (@{$types}) {          foreach my $type (@{$types}) {
             my $currdefquota;              my ($currdefquota,$currauthorquota);
             unless ($context eq 'requestcourses') {              unless (($context eq 'requestcourses') ||
                       ($context eq 'requestauthor')) {
                 if (ref($settings) eq 'HASH') {                  if (ref($settings) eq 'HASH') {
                     if (ref($settings->{defaultquota}) eq 'HASH') {                      if (ref($settings->{defaultquota}) eq 'HASH') {
                         $currdefquota = $settings->{defaultquota}->{$type};                           $currdefquota = $settings->{defaultquota}->{$type};
                     } else {                      } else {
                         $currdefquota = $settings->{$type};                          $currdefquota = $settings->{$type};
                     }                      }
                       if (ref($settings->{authorquota}) eq 'HASH') {
                           $currauthorquota = $settings->{authorquota}->{$type};
                       }
                 }                  }
             }              }
             if (defined($usertypes->{$type})) {              if (defined($usertypes->{$type})) {
Line 1395  sub print_quotas { Line 1701  sub print_quotas {
                                 $cell{$item} .= $titles{'unlimited'};                                  $cell{$item} .= $titles{'unlimited'};
                             }                              }
                         }                          }
                       } elsif ($context eq 'requestauthor') {
                           my $curroption;
                           if (ref($settings) eq 'HASH') {
                               $curroption = $settings->{$type};
                           }
                           if (!$curroption) {
                               $curroption = 'norequest';
                           }
                           foreach my $option (@options) {
                               my $val = $option;
                               if ($option eq 'norequest') {
                                   $val = 0;
                               }
                               my $checked = '';
                               if ($option eq $curroption) {
                                   $checked = ' checked="checked"';
                               }
                               $datatable .= '<span class="LC_nobreak"><label>'.
                                     '<input type="radio" name="authorreq_'.$type.
                                     '" value="'.$val.'"'.$checked.' />'.
                                     $titles{$option}.'</label></span>&nbsp; ';
                           }
                     } else {                      } else {
                         my $checked = 'checked="checked" ';                          my $checked = 'checked="checked" ';
                         if (ref($settings) eq 'HASH') {                          if (ref($settings) eq 'HASH') {
Line 1420  sub print_quotas { Line 1748  sub print_quotas {
                     $datatable .= '</tr></table>';                      $datatable .= '</tr></table>';
                 }                  }
                 $datatable .= '</td>';                  $datatable .= '</td>';
                 unless ($context eq 'requestcourses') {                  unless (($context eq 'requestcourses') ||
                           ($context eq 'requestauthor')) {
                     $datatable .=                       $datatable .= 
                               '<td class="LC_right_item"><span class="LC_nobreak">'.                                '<td class="LC_right_item">'.
                                 '<span class="LC_nobreak">'.&mt('Portfolio').':&nbsp;'.
                               '<input type="text" name="quota_'.$type.                                '<input type="text" name="quota_'.$type.
                               '" value="'.$currdefquota.                                '" value="'.$currdefquota.
                               '" size="5" /> Mb</span></td>';                                '" size="5" /></span>'.('&nbsp;' x 2).
                                 '<span class="LC_nobreak">'.&mt('Authoring').':&nbsp;'.
                                 '<input type="text" name="authorquota_'.$type.
                                 '" value="'.$currauthorquota.
                                 '" size="5" /></span></td>';
                 }                  }
                 $datatable .= '</tr>';                  $datatable .= '</tr>';
             }              }
         }          }
     }      }
     unless ($context eq 'requestcourses') {      unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
         $defaultquota = '20';          $defaultquota = '20';
           $authorquota = '500';
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if (ref($settings->{'defaultquota'}) eq 'HASH') {              if (ref($settings->{'defaultquota'}) eq 'HASH') {
                 $defaultquota = $settings->{'defaultquota'}->{'default'};                  $defaultquota = $settings->{'defaultquota'}->{'default'};
             } elsif (defined($settings->{'default'})) {              } elsif (defined($settings->{'default'})) {
                 $defaultquota = $settings->{'default'};                  $defaultquota = $settings->{'default'};
             }              }
               if (ref($settings->{'authorquota'}) eq 'HASH') {
                   $authorquota = $settings->{'authorquota'}->{'default'};
               }
         }          }
     }      }
     $typecount ++;      $typecount ++;
Line 1501  sub print_quotas { Line 1839  sub print_quotas {
                     $defcell{$item} .= $titles{'unlimited'};                      $defcell{$item} .= $titles{'unlimited'};
                 }                  }
             }              }
           } elsif ($context eq 'requestauthor') {
               my $curroption;
               if (ref($settings) eq 'HASH') {
                   $curroption = $settings->{'default'};
               }
               if (!$curroption) {
                   $curroption = 'norequest';
               }
               foreach my $option (@options) {
                   my $val = $option;
                   if ($option eq 'norequest') {
                       $val = 0;
                   }
                   my $checked = '';
                   if ($option eq $curroption) {
                       $checked = ' checked="checked"';
                   }
                   $datatable .= '<span class="LC_nobreak"><label>'.
                                 '<input type="radio" name="authorreq_default"'.
                                 ' value="'.$val.'"'.$checked.' />'.
                                 $titles{$option}.'</label></span>&nbsp; ';
               }
         } else {          } else {
             my $checked = 'checked="checked" ';              my $checked = 'checked="checked" ';
             if (ref($settings) eq 'HASH') {              if (ref($settings) eq 'HASH') {
Line 1526  sub print_quotas { Line 1886  sub print_quotas {
         $datatable .= '</tr></table>';          $datatable .= '</tr></table>';
     }      }
     $datatable .= '</td>';      $datatable .= '</td>';
     unless ($context eq 'requestcourses') {      unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
         $datatable .= '<td class="LC_right_item"><span class="LC_nobreak">'.          $datatable .= '<td class="LC_right_item">'.
                         '<span class="LC_nobreak">'.&mt('Portfolio').':&nbsp;'.
                       '<input type="text" name="defaultquota" value="'.                        '<input type="text" name="defaultquota" value="'.
                       $defaultquota.'" size="5" /> Mb</span></td>';                        $defaultquota.'" size="5" /></span>'.('&nbsp;' x2).
                         '<span class="LC_nobreak">'.&mt('Authoring').':&nbsp;'.
                         '<input type="text" name="authorquota" value="'.
                         $authorquota.'" size="5" /></span></td>';
     }      }
     $datatable .= '</tr>';      $datatable .= '</tr>';
     $typecount ++;      $typecount ++;
     $css_class = $typecount%2?' class="LC_odd_row"':'';      $css_class = $typecount%2?' class="LC_odd_row"':'';
     $datatable .= '<tr'.$css_class.'>'.      $datatable .= '<tr'.$css_class.'>'.
                   '<td>'.&mt('LON-CAPA Advanced Users').' ';                    '<td>'.&mt('LON-CAPA Advanced Users').'<br />';
     if ($context eq 'requestcourses') {      if ($context eq 'requestcourses') {
         $datatable .= &mt('(overrides affiliation, if set)').          $datatable .= &mt('(overrides affiliation, if set)').
                       '</td>'.                        '</td>'.
Line 1604  sub print_quotas { Line 1968  sub print_quotas {
                     $advcell{$item} .= $titles{'unlimited'};                      $advcell{$item} .= $titles{'unlimited'};
                 }                  }
             }              }
           } elsif ($context eq 'requestauthor') {
               my $curroption;
               if (ref($settings) eq 'HASH') {
                   $curroption = $settings->{'_LC_adv'};
               }
               my $checked = '';
               if ($curroption eq '') {
                   $checked = ' checked="checked"';
               }
               $datatable .= '<span class="LC_nobreak"><label>'.
                             '<input type="radio" name="authorreq__LC_adv"'.
                             ' value=""'.$checked.' />'.
                             &mt('No override set').'</label></span>&nbsp; ';
               foreach my $option (@options) {
                   my $val = $option;
                   if ($option eq 'norequest') {
                       $val = 0;
                   }
                   my $checked = '';
                   if ($val eq $curroption) {
                       $checked = ' checked="checked"';
                   }
                   $datatable .= '<span class="LC_nobreak"><label>'.
                                 '<input type="radio" name="authorreq__LC_adv"'.
                                 ' value="'.$val.'"'.$checked.' />'.
                                 $titles{$option}.'</label></span>&nbsp; ';
               }
         } else {          } else {
             my $checked = 'checked="checked" ';              my $checked = 'checked="checked" ';
             if (ref($settings) eq 'HASH') {              if (ref($settings) eq 'HASH') {
Line 1633  sub print_quotas { Line 2024  sub print_quotas {
     return $datatable;      return $datatable;
 }  }
   
 sub print_courserequestmail {  sub print_requestmail {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$action,$settings,$rowtotal) = @_;
     my ($now,$datatable,%dompersonnel,@domcoord,@currapproval,$rows);      my ($now,$datatable,%currapp);
     $now = time;      $now = time;
     $rows = 0;      if (ref($settings) eq 'HASH') {
     %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc'],$now,$now);          if (ref($settings->{'notify'}) eq 'HASH') {
     foreach my $server (keys(%dompersonnel)) {              if ($settings->{'notify'}{'approval'} ne '') {
         foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {                  map {$currapp{$_}=1;} split(/,/,$settings->{'notify'}{'approval'});
             my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user);  
             if (!grep(/^$uname:$udom$/,@domcoord)) {  
                 push(@domcoord,$uname.':'.$udom);  
             }              }
         }          }
     }      }
       my $numinrow = 2;
       my $css_class;
       $css_class = ($$rowtotal%2? ' class="LC_odd_row"':'');
       my $text;
       if ($action eq 'requestcourses') {
           $text = &mt('Receive notification of course requests requiring approval');
       } elsif ($action eq 'requestauthor') {
           $text = &mt('Receive notification of Authoring Space requests requiring approval');
       } else {
          $text = &mt('Receive notification of queued requests for self-created user accounts requiring approval');
       }
       $datatable = '<tr'.$css_class.'>'.
                    ' <td>'.$text.'</td>'.
                    ' <td class="LC_left_item">';
       my ($numdc,$table,$rows) = &active_dc_picker($dom,$numinrow,'checkbox',
                                                    $action.'notifyapproval',%currapp);
       if ($numdc > 0) {
           $datatable .= $table;
       } else {
           $datatable .= &mt('There are no active Domain Coordinators');
       }
       $datatable .='</td></tr>';
       return $datatable;
   }
   
   sub print_studentcode {
       my ($settings,$rowtotal) = @_;
       my $rownum = 0; 
       my ($output,%current);
       my @crstypes = ('official','unofficial','community','textbook');
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{'notify'}) eq 'HASH') {          if (ref($settings->{'uniquecode'}) eq 'HASH') {
             if ($settings->{'notify'}{'approval'} ne '') {              foreach my $type (@crstypes) {
                @currapproval = split(',',$settings->{'notify'}{'approval'});                  $current{$type} = $settings->{'uniquecode'}{$type};
             }              }
         }          }
     }      }
     if (@currapproval) {      $output .= '<tr>'.
         foreach my $dc (@currapproval) {                 '<td class="LC_left_item">'.&mt('Generate unique six character code as course identifier?').'</td>'.
             unless (grep(/^\Q$dc\E$/,@domcoord)) {                 '<td class="LC_left_item">';
                 push(@domcoord,$dc);      foreach my $type (@crstypes) {
           my $check = ' ';
           if ($current{$type}) {
               $check = ' checked="checked" ';
           }
           $output .= '<span class="LC_nobreak"><label>'.
                      '<input type="checkbox" name="uniquecode" value="'.$type.'"'.$check.'/>'.
                      &mt($type).'</label></span>'.('&nbsp;'x2).' ';
       }
       $output .= '</td></tr>';
       $$rowtotal ++;
       return $output;
   }
   
   sub print_textbookcourses {
       my ($dom,$type,$settings,$rowtotal) = @_;
       my $rownum = 0;
       my $css_class;
       my $itemcount = 1;
       my $maxnum = 0;
       my $bookshash;
       if (ref($settings) eq 'HASH') {
           $bookshash = $settings->{$type};
       }
       my %ordered;
       if (ref($bookshash) eq 'HASH') {
           foreach my $item (keys(%{$bookshash})) {
               if (ref($bookshash->{$item}) eq 'HASH') {
                   my $num = $bookshash->{$item}{'order'};
                   $ordered{$num} = $item;
             }              }
         }          }
     }      }
     @domcoord = sort(@domcoord);      my $confname = $dom.'-domainconfig';
     my $numinrow = 4;      my $switchserver = &check_switchserver($dom,$confname);
     my $numdc = @domcoord;      my $maxnum = scalar(keys(%ordered));
     my $css_class = 'class="LC_odd_row"';      my $datatable;
     $datatable = '<tr'.$css_class.'>'.      if (keys(%ordered)) {
                  ' <td>'.&mt('Receive notification of course requests requiring approval.').          my @items = sort { $a <=> $b } keys(%ordered);
                  ' </td>'.          for (my $i=0; $i<@items; $i++) {
                  ' <td class="LC_left_item">';              $css_class = $itemcount%2?' class="LC_odd_row"':'';
     if (@domcoord > 0) {              my $key = $ordered{$items[$i]};
         $datatable .= '<table>';              my %coursehash=&Apache::lonnet::coursedescription($key);
         for (my $i=0; $i<$numdc; $i++) {              my $coursetitle = $coursehash{'description'};
             my $rem = $i%($numinrow);              my ($subject,$title,$author,$publisher,$image,$imgsrc,$cdom,$cnum);
             if ($rem == 0) {              if (ref($bookshash->{$key}) eq 'HASH') {
                 if ($i > 0) {                  $subject = $bookshash->{$key}->{'subject'};
                     $datatable .= '</tr>';                  $title = $bookshash->{$key}->{'title'};
                   if ($type eq 'textbooks') {
                       $publisher = $bookshash->{$key}->{'publisher'};
                       $author = $bookshash->{$key}->{'author'};
                       $image = $bookshash->{$key}->{'image'};
                       if ($image ne '') {
                           my ($path,$imagefile) = ($image =~ m{^(.+)/([^/]+)$});
                           my $imagethumb = "$path/tn-".$imagefile;
                           $imgsrc = '<img src="'.$imagethumb.'" alt="'.&mt('Textbook image').'" />';
                       }
                 }                  }
                 $datatable .= '<tr>';  
                 $rows ++;  
             }  
             my $check = ' ';  
             if (grep(/^\Q$domcoord[$i]\E$/,@currapproval)) {  
                 $check = ' checked="checked" ';  
             }              }
             my ($uname,$udom) = split(':',$domcoord[$i]);              my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$type".'_'."$key','$type'".');"';
             my $fullname = &Apache::loncommon::plainname($uname,$udom);              $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
             if ($i == $numdc-1) {                           .'<select name="'.$type.'_'.$key.'"'.$chgstr.'>';
                 my $colsleft = $numinrow-$rem;              for (my $k=0; $k<=$maxnum; $k++) {
                 if ($colsleft > 1) {                  my $vpos = $k+1;
                     $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">';                  my $selstr;
                   if ($k == $i) {
                       $selstr = ' selected="selected" ';
                   }
                   $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
               }
               $datatable .= '</select>'.('&nbsp;'x2).
                   '<label><input type="checkbox" name="'.$type.'_del" value="'.$key.'" />'.
                   &mt('Delete?').'</label></span></td>'.
                   '<td colspan="2">'.
                   '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_subject_'.$i.'" value="'.$subject.'" /></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="'.$type.'_title_'.$i.'" value="'.$title.'" /></span> ';
               if ($type eq 'textbooks') {
                   $datatable .= ('&nbsp;'x2).
                                 '<span class="LC_nobreak">'.&mt('Publisher:').'<input type="text" size="10" name="'.$type.'_publisher_'.$i.'" value="'.$publisher.'" /></span> '.
                                 ('&nbsp;'x2).
                                 '<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="'.$type.'_author_'.$i.'" value="'.$author.'" /></span> '.
                                 ('&nbsp;'x2).
                                 '<span class="LC_nobreak">'.&mt('Thumbnail:');
                   if ($image) {
                       $datatable .= '<span class="LC_nobreak">'.
                                     $imgsrc.
                                     '<label><input type="checkbox" name="'.$type.'_image_del"'.
                                     ' value="'.$key.'" />'.&mt('Delete?').'</label></span> '.
                                     '<span class="LC_nobreak">&nbsp;'.&mt('Replace:').'&nbsp;';
                   }
                   if ($switchserver) {
                       $datatable .= &mt('Upload to library server: [_1]',$switchserver);
                 } else {                  } else {
                     $datatable .= '<td class="LC_left_item">';                      $datatable .= '<input type="file" name="'.$type.'_image_'.$i.'" value="" />';
                 }                  }
             } else {  
                 $datatable .= '<td class="LC_left_item">';  
             }              }
             $datatable .= '<span class="LC_nobreak"><label>'.              $datatable .= '<input type="hidden" name="'.$type.'_id_'.$i.'" value="'.$type.'_'.$key.'" /></span> '.
                           '<input type="checkbox" name="reqapprovalnotify" '.                            '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.
                           'value="'.$domcoord[$i].'"'.$check.'/>'.                            $coursetitle.'</span></td></tr>'."\n";
                           $fullname.'</label></span></td>';              $itemcount ++;
         }          }
         $datatable .= '</tr></table>';  
     } else {  
         $datatable .= &mt('There are no active Domain Coordinators');  
         $rows ++;  
     }      }
     $datatable .='</td></tr>';      $css_class = $itemcount%2?' class="LC_odd_row"':'';
     $$rowtotal += $rows;      my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$type"."_addbook_pos','$type'".');"';
       $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
                     '<input type="hidden" name="'.$type.'_maxnum" value="'.$maxnum.'" />'."\n".
                     '<select name="'.$type.'_addbook_pos"'.$chgstr.'>';
       for (my $k=0; $k<$maxnum+1; $k++) {
           my $vpos = $k+1;
           my $selstr;
           if ($k == $maxnum) {
               $selstr = ' selected="selected" ';
           }
           $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
       }
       $datatable .= '</select>&nbsp;'."\n".
                     '<input type="checkbox" name="'.$type.'_addbook" value="1" />'.&mt('Add').'</td>'."\n".
                     '<td colspan="2">'.
                     '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_addbook_subject" value="" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="'.$type.'_addbook_title" value="" /></span> '."\n".
                     ('&nbsp;'x2);
       if ($type eq 'textbooks') {
           $datatable .= '<span class="LC_nobreak">'.&mt('Publisher:').'<input type="text" size="10" name="'.$type.'_addbook_publisher" value="" /></span> '."\n".
                         ('&nbsp;'x2).
                         '<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="'.$type.'_addbook_author" value="" /></span> '."\n".
                         ('&nbsp;'x2).
                         '<span class="LC_nobreak">'.&mt('Image:').'&nbsp;';
           if ($switchserver) {
               $datatable .= &mt('Upload to library server: [_1]',$switchserver);
           } else {
               $datatable .= '<input type="file" name="'.$type.'_addbook_image" value="" />';
           }
       }
       $datatable .= '</span>'."\n".
                     '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.
                     &Apache::loncommon::select_dom_form($env{'request.role.domain'},$type.'_addbook_cdom').
                     '<input type="text" size="25" name="'.$type.'_addbook_cnum" value="" />'.
                     &Apache::loncommon::selectcourse_link
                         ('display',$type.'_addbook_cnum',$type.'_addbook_cdom',undef,undef,undef,'Course');
                     '</span></td>'."\n".
                     '</tr>'."\n";
       $itemcount ++;
     return $datatable;      return $datatable;
 }  }
   
   sub textbookcourses_javascript {
       my ($settings) = @_;
       return unless(ref($settings) eq 'HASH');
       my (%ordered,%total,%jstext);
       foreach my $type ('textbooks','templates') {
           $total{$type} = 0;
           if (ref($settings->{$type}) eq 'HASH') {
               foreach my $item (keys(%{$settings->{$type}})) {
                   if (ref($settings->{$type}->{$item}) eq 'HASH') {
                       my $num = $settings->{$type}->{$item}{'order'};
                       $ordered{$type}{$num} = $item;
                   }
               }
               $total{$type} = scalar(keys(%{$settings->{$type}}));
           }
           my @jsarray = ();
           foreach my $item (sort {$a <=> $b } (keys(%{$ordered{$type}}))) {
               push(@jsarray,$ordered{$type}{$item});
           }
           $jstext{$type} = '    var '.$type.' = Array('."'".join("','",@jsarray)."'".');'."\n";
       }
       return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   function reorderBooks(form,item,caller) {
       var changedVal;
   $jstext{'textbooks'};
   $jstext{'templates'};
       var newpos;
       var maxh;
       if (caller == 'textbooks') {  
           newpos = 'textbooks_addbook_pos';
           maxh = 1 + $total{'textbooks'};
       } else {
           newpos = 'templates_addbook_pos';
           maxh = 1 + $total{'templates'};
       }
       var current = new Array;
       var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
       if (item == newpos) {
           changedVal = newitemVal;
       } else {
           changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
           current[newitemVal] = newpos;
       }
       if (caller == 'textbooks') {
           for (var i=0; i<textbooks.length; i++) {
               var elementName = 'textbooks_'+textbooks[i];
               if (elementName != item) {
                   if (form.elements[elementName]) {
                       var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
                       current[currVal] = elementName;
                   }
               }
           }
       }
       if (caller == 'templates') {
           for (var i=0; i<templates.length; i++) {
               var elementName = 'templates_'+templates[i];
               if (elementName != item) {
                   if (form.elements[elementName]) {
                       var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
                       current[currVal] = elementName;
                   }
               }
           }
       }
       var oldVal;
       for (var j=0; j<maxh; j++) {
           if (current[j] == undefined) {
               oldVal = j;
           }
       }
       if (oldVal < changedVal) {
           for (var k=oldVal+1; k<=changedVal ; k++) {
              var elementName = current[k];
              form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
           }
       } else {
           for (var k=changedVal; k<oldVal; k++) {
               var elementName = current[k];
               form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   ENDSCRIPT
   }
   
 sub print_autoenroll {  sub print_autoenroll {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my $autorun = &Apache::lonnet::auto_run(undef,$dom),      my $autorun = &Apache::lonnet::auto_run(undef,$dom),
Line 1859  sub print_autoupdate { Line 2463  sub print_autoupdate {
   
 sub print_autocreate {  sub print_autocreate {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my (%createon,%createoff);      my (%createon,%createoff,%currhash);
     my $curr_dc;  
     my @types = ('xml','req');      my @types = ('xml','req');
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         foreach my $item (@types) {          foreach my $item (@types) {
Line 1873  sub print_autocreate { Line 2476  sub print_autocreate {
                 }                  }
             }              }
         }          }
         $curr_dc = $settings->{'xmldc'};          if ($settings->{'xmldc'} ne '') {
               $currhash{$settings->{'xmldc'}} = 1;
           }
     } else {      } else {
         foreach my $item (@types) {          foreach my $item (@types) {
             $createoff{$item} = ' checked="checked" ';              $createoff{$item} = ' checked="checked" ';
Line 1881  sub print_autocreate { Line 2486  sub print_autocreate {
         }          }
     }      }
     $$rowtotal += 2;      $$rowtotal += 2;
       my $numinrow = 2;
     my $datatable='<tr class="LC_odd_row">'.      my $datatable='<tr class="LC_odd_row">'.
                   '<td>'.&mt('Create pending official courses from XML files').'</td>'.                    '<td>'.&mt('Create pending official courses from XML files').'</td>'.
                   '<td class="LC_right_item"><span class="LC_nobreak"><label>'.                    '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                   '<input type="radio" name="autocreate_xml"'.                    '<input type="radio" name="autocreate_xml"'.
                   $createon{'xml'}.' value="1" />'.&mt('Yes').'</label>&nbsp;'.                    $createon{'xml'}.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                   '<label><input type="radio" name="autocreate_xml"'.                    '<label><input type="radio" name="autocreate_xml"'.
                   $createoff{'xml'}.' value="0" />'.&mt('No').'</label></span>';                    $createoff{'xml'}.' value="0" />'.&mt('No').'</label></span>'.
     my ($numdc,$dctable) = &active_dc_picker($dom,$curr_dc);                    '</td></tr><tr>'.
     if ($numdc > 1) {                    '<td>'.&mt('Create pending requests for official courses (if validated)').'</td>'.
         $datatable .= '</td><tr><td>'.  
                       &mt('XML files processed as: (choose Dom. Coord.)').   
                       '</td><td class="LC_left_item">'.$dctable.'</td></tr>'.  
                       '<tr class="LC_odd_row">';  
         $$rowtotal ++ ;  
     } else {  
         $datatable .= '</td></tr><tr>';  
     }  
     $datatable .= '<td>'.&mt('Create pending requests for official courses (if validated)').'</td>'.  
                   '<td class="LC_right_item"><span class="LC_nobreak"><label>'.                    '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                   '<input type="radio" name="autocreate_req"'.                    '<input type="radio" name="autocreate_req"'.
                   $createon{'req'}.' value="1" />'.&mt('Yes').'</label>&nbsp;'.                    $createon{'req'}.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                   '<label><input type="radio" name="autocreate_req"'.                    '<label><input type="radio" name="autocreate_req"'.
                   $createoff{'req'}.' value="0" />'.&mt('No').'</label></span></td>'.                    $createoff{'req'}.' value="0" />'.&mt('No').'</label></span>';
                   '</tr>';      my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',
                                                      'autocreate_xmldc',%currhash);
       $datatable .= '</td></tr><tr class="LC_odd_row"><td>';
       if ($numdc > 1) {
           $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)').
                         '</td><td class="LC_left_item">';
       } else {
           $datatable .= &mt('Course creation processed as:').
                         '</td><td class="LC_right_item">';
       }
       $datatable .= $dctable.'</td></tr>';
       $$rowtotal += $rows;
     return $datatable;      return $datatable;
 }  }
   
Line 2027  sub print_contacts { Line 2635  sub print_contacts {
     my @contacts = ('adminemail','supportemail');      my @contacts = ('adminemail','supportemail');
     my (%checked,%to,%otheremails,%bccemails);      my (%checked,%to,%otheremails,%bccemails);
     my @mailings = ('errormail','packagesmail','lonstatusmail','helpdeskmail',      my @mailings = ('errormail','packagesmail','lonstatusmail','helpdeskmail',
                     'requestsmail');                      'requestsmail','updatesmail','idconflictsmail');
     foreach my $type (@mailings) {      foreach my $type (@mailings) {
         $otheremails{$type} = '';          $otheremails{$type} = '';
     }      }
Line 2063  sub print_contacts { Line 2671  sub print_contacts {
         $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';          $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';
         $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';           $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" '; 
         $checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';          $checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';
           $checked{'updatesmail'}{'adminemail'} = ' checked="checked" ';
           $checked{'idconflictsmail'}{'adminemail'} = ' checked="checked" ';
     }      }
     my ($titles,$short_titles) = &contact_titles();      my ($titles,$short_titles) = &contact_titles();
     my $rownum = 0;      my $rownum = 0;
     my $css_class;      my $css_class;
     foreach my $item (@contacts) {      foreach my $item (@contacts) {
         $rownum ++;  
         $css_class = $rownum%2?' class="LC_odd_row"':'';          $css_class = $rownum%2?' class="LC_odd_row"':'';
         $datatable .= '<tr'.$css_class.'>'.           $datatable .= '<tr'.$css_class.'>'. 
                   '<td><span class="LC_nobreak">'.$titles->{$item}.                    '<td><span class="LC_nobreak">'.$titles->{$item}.
                   '</span></td><td class="LC_right_item">'.                    '</span></td><td class="LC_right_item">'.
                   '<input type="text" name="'.$item.'" value="'.                    '<input type="text" name="'.$item.'" value="'.
                   $to{$item}.'" /></td></tr>';                    $to{$item}.'" /></td></tr>';
           $rownum ++;
     }      }
     foreach my $type (@mailings) {      foreach my $type (@mailings) {
         $rownum ++;  
         $css_class = $rownum%2?' class="LC_odd_row"':'';          $css_class = $rownum%2?' class="LC_odd_row"':'';
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                       '<td><span class="LC_nobreak">'.                        '<td><span class="LC_nobreak">'.
Line 2100  sub print_contacts { Line 2709  sub print_contacts {
                           'value="'.$bccemails{$type}.'"  />';                            'value="'.$bccemails{$type}.'"  />';
         }          }
         $datatable .= '</td></tr>'."\n";          $datatable .= '</td></tr>'."\n";
           $rownum ++;
     }      }
       my %choices;
       $choices{'reporterrors'} = &mt('E-mail error reports to [_1]',
                                      &Apache::loncommon::modal_link('http://loncapa.org/core.html',
                                      &mt('LON-CAPA core group - MSU'),600,500));
       $choices{'reportupdates'} = &mt('E-mail record of completed LON-CAPA updates to [_1]',
                                       &Apache::loncommon::modal_link('http://loncapa.org/core.html',
                                       &mt('LON-CAPA core group - MSU'),600,500));
       my @toggles = ('reporterrors','reportupdates');
       my %defaultchecked = ('reporterrors'  => 'on',
                             'reportupdates' => 'on');
       (my $reports,$rownum) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
                                                  \%choices,$rownum);
       $datatable .= $reports;
     $$rowtotal += $rownum;      $$rowtotal += $rownum;
     return $datatable;      return $datatable;
 }  }
   
 sub print_helpsettings {  sub print_helpsettings {
       my ($dom,$confname,$settings,$rowtotal) = @_;
       my ($datatable,$itemcount);
       $itemcount = 1;
       my (%choices,%defaultchecked,@toggles);
       $choices{'submitbugs'} = &mt('Display link to: [_1]?',
                                    &Apache::loncommon::modal_link('http://bugs.loncapa.org',
                                    &mt('LON-CAPA bug tracker'),600,500));
       %defaultchecked = ('submitbugs' => 'on');
       @toggles = ('submitbugs',);
   
  my ($position,$dom,$confname,$settings,$rowtotal) = @_;      ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
  my ($css_class,$datatable);                                                   \%choices,$itemcount);
       return $datatable;
  my $switchserver = &check_switchserver($dom,$confname);  
   
  my $itemcount = 1;  
   
  if ($position eq 'top') {  
   
  my (%checkedon,%checkedoff,%choices,%defaultchecked,@toggles);  
   
  %choices =  
  &Apache::lonlocal::texthash (  
  submitbugs => 'Display &quot;Submit a bug&quot; link?',  
  );  
   
  %defaultchecked = ('submitbugs' => 'on');  
   
  @toggles = ('submitbugs',);  
   
  foreach my $item (@toggles) {  
  if ($defaultchecked{$item} eq 'on') {   
  $checkedon{$item} = ' checked="checked" ';  
  $checkedoff{$item} = ' ';  
  } elsif ($defaultchecked{$item} eq 'off') {  
  $checkedoff{$item} = ' checked="checked" ';  
  $checkedon{$item} = ' ';  
  }  
  }  
   
  if (ref($settings) eq 'HASH') {  
  foreach my $item (@toggles) {  
  if ($settings->{$item} eq '1') {  
  $checkedon{$item} =  ' checked="checked" ';  
  $checkedoff{$item} = ' ';  
  } elsif ($settings->{$item} eq '0') {  
  $checkedoff{$item} =  ' checked="checked" ';  
  $checkedon{$item} = ' ';  
  }  
  }  
  }  
   
  foreach my $item (@toggles) {  
  $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';  
  $datatable .=    
  '<tr'.$css_class.'>  
  <td><span class="LC_nobreak">'.$choices{$item}.'</span></td>  
  <td><span class="LC_nobreak">&nbsp;</span></td>  
  <td class="LC_right_item"><span class="LC_nobreak">  
  <label><input type="radio" name="'.$item.'" '.$checkedon{$item}.' value="1" />'.&mt('Yes').'</label>&nbsp;  
  <label><input type="radio" name="'.$item.'" '.$checkedoff{$item}.' value="0" />'.&mt('No').'</label>'.  
  '</span></td>'.  
  '</tr>';  
  $itemcount ++;  
  }  
        
      } else {  
        
       $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';  
        
       $datatable .= '<tr'.$css_class.'>';  
        
       if (ref($settings) eq 'HASH') {  
  if ($settings->{'loginhelpurl'} ne '') {  
  my($directory, $filename) = $settings->{'loginhelpurl'} =~ m/(.*\/)(.*)$/;  
  $datatable .= '<td width="33%"><span class="LC_left_item"><label><a href="'.$settings->{'loginhelpurl'}.'" target="_blank">'.&mt('Custom Login Page Help File In Use').'</a></label></span></td>';  
  $datatable .= '<td width="33%"><span class="LC_right_item"><label><input type="checkbox" name="loginhelpurl_del" value="1" />'.&mt('Delete?').'</label></span></td>'  
  } else {  
  $datatable .= '<td width="33%"><span class="LC_left_item"><label>'.&mt('Default Login Page Help File In Use').'</label></span></td>';  
  $datatable .= '<td width="33%"><span class="LC_right_item">&nbsp;</span></td>';  
  }  
  } else {  
  $datatable .= '<td><span class="LC_left_item">&nbsp;</span></td>';  
  $datatable .= '<td><span class="LC_right_item">&nbsp;</span></td>';  
  }  
      
       $datatable .= '<td width="33%"><span class="LC_right_item">';  
       if ($switchserver) {  
             $datatable .= &mt('Upload to library server: [_1]',$switchserver);  
         } else {  
         $datatable .= &mt('Upload Custom Login Page Help File:');  
             $datatable .='<input type="file" name="loginhelpurl" />';  
         }  
         $datatable .= '</span></td></tr>';  
           
      }  
        
      return $datatable;  
   
 }  }
   
   
 sub radiobutton_prefs {  sub radiobutton_prefs {
     my ($settings,$toggles,$defaultchecked,$choices,$itemcount) = @_;      my ($settings,$toggles,$defaultchecked,$choices,$itemcount,$onclick,
           $additional) = @_;
     return unless ((ref($toggles) eq 'ARRAY') && (ref($defaultchecked) eq 'HASH') &&      return unless ((ref($toggles) eq 'ARRAY') && (ref($defaultchecked) eq 'HASH') &&
                    (ref($choices) eq 'HASH'));                     (ref($choices) eq 'HASH'));
   
Line 2226  sub radiobutton_prefs { Line 2772  sub radiobutton_prefs {
             }              }
         }          }
     }      }
       if ($onclick) {
           $onclick = ' onclick="'.$onclick.'"';
       }
     foreach my $item (@{$toggles}) {      foreach my $item (@{$toggles}) {
         $css_class = $itemcount%2?' class="LC_odd_row"':'';          $css_class = $itemcount%2?' class="LC_odd_row"':'';
         $datatable .=          $datatable .=
             '<tr'.$css_class.'><td><span class="LC_nobreak">'.$choices->{$item}.              '<tr'.$css_class.'><td valign="top">'.
               '<span class="LC_nobreak">'.$choices->{$item}.
             '</span></td>'.              '</span></td>'.
             '<td class="LC_right_item"><span class="LC_nobreak">'.              '<td class="LC_right_item"><span class="LC_nobreak">'.
             '<label><input type="radio" name="'.              '<label><input type="radio" name="'.
             $item.'" '.$checkedon{$item}.' value="1" />'.&mt('Yes').              $item.'" '.$checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').
             '</label>&nbsp;<label><input type="radio" name="'.$item.'" '.              '</label>&nbsp;<label><input type="radio" name="'.$item.'" '.
             $checkedoff{$item}.' value="0" />'.&mt('No').'</label>'.              $checkedoff{$item}.' value="0"'.$onclick.' />'.&mt('No').'</label>'.
             '</span></td>'.              '</span>'.$additional.
               '</td>'.
             '</tr>';              '</tr>';
         $itemcount ++;          $itemcount ++;
     }      }
Line 2245  sub radiobutton_prefs { Line 2796  sub radiobutton_prefs {
   
 sub print_coursedefaults {  sub print_coursedefaults {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable);      my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles);
     my $itemcount = 1;      my $itemcount = 1;
       my %choices =  &Apache::lonlocal::texthash (
           canuse_pdfforms      => 'Course/Community users can create/upload PDF forms',
           uploadquota          => 'Default quota for files uploaded directly to course/community using Course Editor (MB)',
           anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',
           coursecredits        => 'Credits can be specified for courses',
       );
       my %staticdefaults = (
                              anonsurvey_threshold => 10,
                              uploadquota          => 500,
                            );
     if ($position eq 'top') {      if ($position eq 'top') {
         my (%checkedon,%checkedoff,%choices,%defaultchecked,@toggles);  
         %choices =  
             &Apache::lonlocal::texthash (  
                 canuse_pdfforms => 'Course/Community users can create/upload PDF forms',  
         );  
         %defaultchecked = ('canuse_pdfforms' => 'off');          %defaultchecked = ('canuse_pdfforms' => 'off');
         @toggles = ('canuse_pdfforms',);          @toggles = ('canuse_pdfforms');
         ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,          ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
                                                  \%choices,$itemcount);                                                   \%choices,$itemcount);
         $$rowtotal += $itemcount;  
     } else {      } else {
         $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';          $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
         my %choices =          my ($currdefresponder,$def_official_credits,$def_unofficial_credits,$def_textbook_credits,
             &Apache::lonlocal::texthash (              %curruploadquota);
                 anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',          my $currusecredits = 0;
         );          my @types = ('official','unofficial','community','textbook');
         my $currdefresponder;  
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             $currdefresponder = $settings->{'anonsurvey_threshold'};              $currdefresponder = $settings->{'anonsurvey_threshold'};
               if (ref($settings->{'uploadquota'}) eq 'HASH') {
                   foreach my $type (keys(%{$settings->{'uploadquota'}})) {
                       $curruploadquota{$type} = $settings->{'uploadquota'}{$type};
                   }
               }
               if (ref($settings->{'coursecredits'}) eq 'HASH') {
                   $def_official_credits = $settings->{'coursecredits'}->{'official'};
                   $def_unofficial_credits = $settings->{'coursecredits'}->{'unofficial'};
                   $def_textbook_credits = $settings->{'coursecredits'}->{'textbook'};
                   if (($def_official_credits ne '') || ($def_unofficial_credits ne '') ||
                       ($def_textbook_credits ne '')) {
                       $currusecredits = 1;
                   }
               }
         }          }
         if (!$currdefresponder) {          if (!$currdefresponder) {
             $currdefresponder = 10;              $currdefresponder = $staticdefaults{'anonsurvey_threshold'};
         } elsif ($currdefresponder < 1) {          } elsif ($currdefresponder < 1) {
             $currdefresponder = 1;              $currdefresponder = 1;
         }          }
           foreach my $type (@types) {
               if ($curruploadquota{$type} eq '') {
                   $curruploadquota{$type} = $staticdefaults{'uploadquota'};
               }
           }
         $datatable .=          $datatable .=
                '<tr'.$css_class.'><td><span class="LC_nobreak">'.$choices{'anonsurvey_threshold'}.                  '<tr'.$css_class.'><td><span class="LC_nobreak">'.
                   $choices{'anonsurvey_threshold'}.
                 '</span></td>'.                  '</span></td>'.
                 '<td class="LC_right_item"><span class="LC_nobreak">'.                  '<td class="LC_right_item"><span class="LC_nobreak">'.
                 '<input type="text" name="anonsurvey_threshold"'.                  '<input type="text" name="anonsurvey_threshold"'.
                 ' value="'.$currdefresponder.'" size="5" /></span>'.                  ' value="'.$currdefresponder.'" size="5" /></span>'.
                 '</td></tr>';                  '</td></tr>'."\n";
           $itemcount ++;
           $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
           $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
                         $choices{'uploadquota'}.
                         '</span></td>'.
                         '<td align="right" class="LC_right_item">'.
                         '<table><tr>';
           foreach my $type (@types) {
               $datatable .= '<td align="center">'.&mt($type).'<br />'.
                              '<input type="text" name="uploadquota_'.$type.'"'.
                              ' value="'.$curruploadquota{$type}.'" size="5" /></td>';
           }
           $datatable .= '</tr></table></td></tr>'."\n";
           $itemcount ++;
           my $onclick = "toggleDisplay(this.form,'credits');";
           my $display = 'none';
           if ($currusecredits) {
               $display = 'block';
           }
           my $additional = '<div id="credits" style="display: '.$display.'">'.
                            '<span class="LC_nobreak">'.
                            &mt('Default credits for official courses [_1]',
                            '<input type="text" name="official_credits" value="'.
                            $def_official_credits.'" size="3" />').
                            '</span><br />'.
                            '<span class="LC_nobreak">'.
                            &mt('Default credits for unofficial courses [_1]',
                            '<input type="text" name="unofficial_credits" value="'.
                            $def_unofficial_credits.'" size="3" />').
                            '</span><br />'.
                            '<span class="LC_nobreak">'.
                            &mt('Default credits for textbook courses [_1]',
                            '<input type="text" name="textbook_credits" value="'.
                            $def_textbook_credits.'" size="3" />').
                            '</span></div>'."\n";
           %defaultchecked = ('coursecredits' => 'off');
           @toggles = ('coursecredits');
           my $current = {
                           'coursecredits' => $currusecredits,
                         };
           (my $table,$itemcount) =
               &radiobutton_prefs($current,\@toggles,\%defaultchecked,
                                  \%choices,$itemcount,$onclick,$additional);
           $datatable .= $table;
           $itemcount ++;
     }      }
       $$rowtotal += $itemcount;
     return $datatable;      return $datatable;
 }  }
   
 sub print_usersessions {  sub print_selfenrollment {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable,%checked,%choices);      my ($css_class,$datatable);
     my %lt = &usersession_titles();  
     my $itemcount = 1;      my $itemcount = 1;
     my $numinrow = 6;      my @types = ('official','unofficial','community','textbook');
     my $prefix;      if (($position eq 'top') || ($position eq 'middle')) {
     my @types;          my ($rowsref,$titlesref) = &Apache::lonuserutils::get_selfenroll_titles();
     if ($position eq 'top') {          my %descs = &Apache::lonuserutils::selfenroll_default_descs();
         $prefix = 'hosted';          my @rows;
         @types = ('excludedomain','includedomain');          my $key;
     } else {          if ($position eq 'top') {
         $prefix = 'remote';              $key = 'admin'; 
         @types = ('version','excludedomain','includedomain');              if (ref($rowsref) eq 'ARRAY') {
                   @rows = @{$rowsref};
               }
           } elsif ($position eq 'middle') {
               $key = 'default';
               @rows = ('types','registered','approval','limit');
           }
           foreach my $row (@rows) {
               if (defined($titlesref->{$row})) {
                   $itemcount ++;
                   $css_class = $itemcount%2?' class="LC_odd_row"':'';
                   $datatable .= '<tr'.$css_class.'>'.
                                 '<td>'.$titlesref->{$row}.'</td>'.
                                 '<td class="LC_left_item">'.
                                 '<table><tr>';
                   my (%current,%currentcap);
                   if (ref($settings) eq 'HASH') {
                       if (ref($settings->{$key}) eq 'HASH') {
                           foreach my $type (@types) {
                               if (ref($settings->{$key}->{$type}) eq 'HASH') {
                                   $current{$type} = $settings->{$key}->{$type}->{$row};
                               }
                               if (($row eq 'limit') && ($key eq 'default')) {
                                   if (ref($settings->{$key}->{$type}) eq 'HASH') {
                                       $currentcap{$type} = $settings->{$key}->{$type}->{'cap'};
                                   }
                               }
                           }
                       }
                   }
                   my %roles = (
                                '0' => &Apache::lonnet::plaintext('dc'),
                               ); 
               
                   foreach my $type (@types) {
                       unless (($row eq 'registered') && ($key eq 'default')) {
                           $datatable .= '<th>'.&mt($type).'</th>';
                       }
                   }
                   unless (($row eq 'registered') && ($key eq 'default')) {
                       $datatable .= '</tr><tr>';
                   }
                   foreach my $type (@types) {
                       if ($type eq 'community') {
                           $roles{'1'} = &mt('Community personnel');
                       } else {
                           $roles{'1'} = &mt('Course personnel');
                       }
                       $datatable .= '<td style="vertical-align: top">';
                       if ($position eq 'top') {
                           my %checked;
                           if ($current{$type} eq '0') {
                               $checked{'0'} = ' checked="checked"';
                           } else {
                               $checked{'1'} = ' checked="checked"';
                           }
                           foreach my $role ('1','0') {
                               $datatable .= '<span class="LC_nobreak"><label>'.
                                             '<input type="radio" name="selfenrolladmin_'.$row.'_'.$type.'" '.
                                             'value="'.$role.'"'.$checked{$role}.' />'.
                                             $roles{$role}.'</label></span> ';
                           }
                       } else {
                           if ($row eq 'types') {
                               my %checked;
                               if ($current{$type} =~ /^(all|dom)$/) {
                                   $checked{$1} = ' checked="checked"';
                               } else {
                                   $checked{''} = ' checked="checked"';
                               }
                               foreach my $val ('','dom','all') {
                                   $datatable .= '<span class="LC_nobreak"><label>'.
                                                 '<input type ="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.
                                                 'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';
                               }
                           } elsif ($row eq 'registered') {
                               my %checked;
                               if ($current{$type} eq '1') {
                                   $checked{'1'} = ' checked="checked"';
                               } else {
                                   $checked{'0'} = ' checked="checked"';
                               }
                               foreach my $val ('0','1') {
                                   $datatable .= '<span class="LC_nobreak"><label>'.
                                                 '<input type ="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.
                                                 'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';
                               }
                           } elsif ($row eq 'approval') {
                               my %checked;
                               if ($current{$type} =~ /^([12])$/) {
                                   $checked{$1} = ' checked="checked"';
                               } else {
                                   $checked{'0'} = ' checked="checked"';
                               }
                               for my $val (0..2) {
                                   $datatable .= '<span class="LC_nobreak"><label>'.
                                                 '<input type="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.
                                                 'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';
                               }
                           } elsif ($row eq 'limit') {
                               my %checked;
                               if ($current{$type} =~ /^(allstudents|selfenrolled)$/) {
                                   $checked{$1} = ' checked="checked"';
                               } else {
                                   $checked{'none'} = ' checked="checked"';
                               }
                               my $cap;
                               if ($currentcap{$type} =~ /^\d+$/) {
                                   $cap = $currentcap{$type};
                               }
                               foreach my $val ('none','allstudents','selfenrolled') {
                                   $datatable .= '<span class="LC_nobreak"><label>'.
                                                 '<input type="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.
                                                 'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';
                               }
                               $datatable .= '<br />'.
                                             '<span class="LC_nobreak">'.&mt('Maximum allowed: ').
                                             '<input type="text" name="selfenrolldefault_cap_'.$type.'" size = "5" value="'.$cap.'" />'.
                                             '</span>'; 
                           }
                       }
                       $datatable .= '</td>';
                   }
                   $datatable .= '</tr>';
               }
               $datatable .= '</table></td></tr>';
           }
       } elsif ($position eq 'bottom') {
           $datatable .= &print_validation_rows('selfenroll',$dom,$settings,\$itemcount);
     }      }
     my (%current,%checkedon,%checkedoff);      $$rowtotal += $itemcount;
     my @lcversions = &Apache::lonnet::all_loncaparevs();      return $datatable;
     my (%by_ip,%by_location,@intdoms);  }
     &build_location_hashes(\@intdoms,\%by_ip,\%by_location);  
     my @locations = sort(keys(%by_location));  sub print_validation_rows {
     foreach my $type (@types) {      my ($caller,$dom,$settings,$rowtotal) = @_;
         $checkedon{$type} = '';      my ($itemsref,$namesref,$fieldsref);
         $checkedoff{$type} = ' checked="checked"';      if ($caller eq 'selfenroll') { 
           ($itemsref,$namesref,$fieldsref) = &Apache::lonuserutils::selfenroll_validation_types();
       } elsif ($caller eq 'requestcourses') {
           ($itemsref,$namesref,$fieldsref) = &Apache::loncoursequeueadmin::requestcourses_validation_types();
     }      }
       my %currvalidation;
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{$prefix}) eq 'HASH') {          if (ref($settings->{'validation'}) eq 'HASH') {
             foreach my $key (keys(%{$settings->{$prefix}})) {              %currvalidation = %{$settings->{'validation'}};
                 $current{$key} = $settings->{$prefix}{$key};          }
                 if ($key eq 'version') {      }
                     if ($current{$key} ne '') {      my $datatable;
                         $checkedon{$key} = ' checked="checked"';      my $itemcount = 0;
                         $checkedoff{$key} = '';      foreach my $item (@{$itemsref}) {
                     }          my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
                 } elsif (ref($current{$key}) eq 'ARRAY') {          $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
                     $checkedon{$key} = ' checked="checked"';                        $namesref->{$item}.
                     $checkedoff{$key} = '';                        '</span></td>'.
                         '<td class="LC_left_item">';
           if (($item eq 'url') || ($item eq 'button')) {
               $datatable .= '<span class="LC_nobreak">'.
                             '<input type="text" name="'.$caller.'_validation_'.$item.'"'.
                             ' value="'.$currvalidation{$item}.'" size="50" /></span>';
           } elsif ($item eq 'fields') {
               my @currfields;
               if (ref($currvalidation{$item}) eq 'ARRAY') {
                   @currfields = @{$currvalidation{$item}};
               }
               foreach my $field (@{$fieldsref}) {
                   my $check = '';
                   if (grep(/^\Q$field\E$/,@currfields)) {
                       $check = ' checked="checked"';
                 }                  }
             }                  $datatable .= '<span class="LC_nobreak"><label>'.
                                 '<input type="checkbox" name="'.$caller.'_validation_fields"'.
                                 ' value="'.$field.'"'.$check.' />'.$field.
                                 '</label></span> ';
               }
           } elsif ($item eq 'markup') {
               $datatable .= '<textarea name="'.$caller.'_validation_markup" cols="50" rows="5" wrap="soft">'.
                              $currvalidation{$item}.
                                 '</textarea>';
           }
           $datatable .= '</td></tr>'."\n";
           if (ref($rowtotal)) {
               $itemcount ++;
         }          }
     }      }
     foreach my $type (@types) {      if ($caller eq 'requestcourses') {
         $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';          my %currhash;
         $datatable .= '<tr'.$css_class.'>          if (ref($settings) eq 'HASH') {
                        <td><span class="LC_nobreak">'.$lt{$type}.'</span><br />              if (ref($settings->{'validation'}) eq 'HASH') {
                            <span class="LC_nobreak">&nbsp;                  if ($settings->{'validation'}{'dc'} ne '') {
                            <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>&nbsp;                      $currhash{$settings->{'validation'}{'dc'}} = 1;
                            <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';  
         if ($type eq 'version') {  
             my $selector = '<select name="'.$prefix.'_version">';  
             foreach my $version (@lcversions) {  
                 my $selected = '';  
                 if ($current{'version'} eq $version) {  
                     $selected = ' selected="selected"';  
                 }                  }
                 $selector .= ' <option value="'.$version.'"'.  
                              $selected.'>'.$version.'</option>';  
             }              }
             $selector .= '</select> ';          }
             $datatable .= &mt('remote server must be version: [_1] or later',$selector);          my $numinrow = 2;
           my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',
                                                          'validationdc',%currhash);
           my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
           $datatable .= '</td></tr><tr'.$css_class.'><td>';
           if ($numdc > 1) {
               $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)');
         } else {          } else {
             $datatable.= '<div><input type="button" value="'.&mt('check all').'" '.              $datatable .=  &mt('Course creation processed as: ');
                          'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.          }
                          ' />'.('&nbsp;'x2).          $datatable .= '</td><td class="LC_left_item">'.$dctable.'</td></tr>';
                          '<input type="button" value="'.&mt('uncheck all').'" '.          $itemcount ++;
                          'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.      }
                          "\n".      if (ref($rowtotal)) {
                          '</div><div><table>';          $$rowtotal += $itemcount;
             my $rem;      }
             for (my $i=0; $i<@locations; $i++) {      return $datatable;
                 my ($showloc,$value,$checkedtype);  }
                 if (ref($by_location{$locations[$i]}) eq 'ARRAY') {  
                     my $ip = $by_location{$locations[$i]}->[0];  sub print_usersessions {
                     if (ref($by_ip{$ip}) eq 'ARRAY') {      my ($position,$dom,$settings,$rowtotal) = @_;
                         $value = join(':',@{$by_ip{$ip}});      my ($css_class,$datatable,%checked,%choices);
                         $showloc = join(', ',@{$by_ip{$ip}});      my (%by_ip,%by_location,@intdoms);
                         if (ref($current{$type}) eq 'ARRAY') {      &build_location_hashes(\@intdoms,\%by_ip,\%by_location);
                             foreach my $loc (@{$by_ip{$ip}}) {    
                                 if (grep(/^\Q$loc\E$/,@{$current{$type}})) {      my @alldoms = &Apache::lonnet::all_domains();
                                     $checkedtype = ' checked="checked"';      my %serverhomes = %Apache::lonnet::serverhomeIDs;
                                     last;      my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my %altids = &id_for_thisdom(%servers);
       my $itemcount = 1;
       if ($position eq 'top') {
           if (keys(%serverhomes) > 1) {
               my %spareid = &current_offloads_to($dom,$settings,\%servers);
               $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$rowtotal);
           } else {
               $datatable .= '<tr'.$css_class.'><td colspan="2">'.
                             &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.');
           }
       } else {
           if (keys(%by_location) == 0) {
               $datatable .= '<tr'.$css_class.'><td colspan="2">'.
                             &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.');
           } else {
               my %lt = &usersession_titles();
               my $numinrow = 5;
               my $prefix;
               my @types;
               if ($position eq 'bottom') {
                   $prefix = 'remote';
                   @types = ('version','excludedomain','includedomain');
               } else {
                   $prefix = 'hosted';
                   @types = ('excludedomain','includedomain');
               }
               my (%current,%checkedon,%checkedoff);
               my @lcversions = &Apache::lonnet::all_loncaparevs();
               my @locations = sort(keys(%by_location));
               foreach my $type (@types) {
                   $checkedon{$type} = '';
                   $checkedoff{$type} = ' checked="checked"';
               }
               if (ref($settings) eq 'HASH') {
                   if (ref($settings->{$prefix}) eq 'HASH') {
                       foreach my $key (keys(%{$settings->{$prefix}})) {
                           $current{$key} = $settings->{$prefix}{$key};
                           if ($key eq 'version') {
                               if ($current{$key} ne '') {
                                   $checkedon{$key} = ' checked="checked"';
                                   $checkedoff{$key} = '';
                               }
                           } elsif (ref($current{$key}) eq 'ARRAY') {
                               $checkedon{$key} = ' checked="checked"';
                               $checkedoff{$key} = '';
                           }
                       }
                   }
               }
               foreach my $type (@types) {
                   next if ($type ne 'version' && !@locations);
                   $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
                   $datatable .= '<tr'.$css_class.'>
                                  <td><span class="LC_nobreak">'.$lt{$type}.'</span><br />
                                  <span class="LC_nobreak">&nbsp;
                                  <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>&nbsp;
                                  <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';
                   if ($type eq 'version') {
                       my $selector = '<select name="'.$prefix.'_version">';
                       foreach my $version (@lcversions) {
                           my $selected = '';
                           if ($current{'version'} eq $version) {
                               $selected = ' selected="selected"';
                           }
                           $selector .= ' <option value="'.$version.'"'.
                                        $selected.'>'.$version.'</option>';
                       }
                       $selector .= '</select> ';
                       $datatable .= &mt('remote server must be version: [_1] or later',$selector);
                   } else {
                       $datatable.= '<div><input type="button" value="'.&mt('check all').'" '.
                                    'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.
                                    ' />'.('&nbsp;'x2).
                                    '<input type="button" value="'.&mt('uncheck all').'" '.
                                    'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.
                                    "\n".
                                    '</div><div><table>';
                       my $rem;
                       for (my $i=0; $i<@locations; $i++) {
                           my ($showloc,$value,$checkedtype);
                           if (ref($by_location{$locations[$i]}) eq 'ARRAY') {
                               my $ip = $by_location{$locations[$i]}->[0];
                               if (ref($by_ip{$ip}) eq 'ARRAY') {
                                    $value = join(':',@{$by_ip{$ip}});
                                   $showloc = join(', ',@{$by_ip{$ip}});
                                   if (ref($current{$type}) eq 'ARRAY') {
                                       foreach my $loc (@{$by_ip{$ip}}) {  
                                           if (grep(/^\Q$loc\E$/,@{$current{$type}})) {
                                               $checkedtype = ' checked="checked"';
                                               last;
                                           }
                                       }
                                 }                                  }
                             }                              }
                         }                          }
                           $rem = $i%($numinrow);
                           if ($rem == 0) {
                               if ($i > 0) {
                                   $datatable .= '</tr>';
                               }
                               $datatable .= '<tr>';
                           }
                           $datatable .= '<td class="LC_left_item">'.
                                         '<span class="LC_nobreak"><label>'.
                                         '<input type="checkbox" name="'.$prefix.'_'.$type.
                                         '" value="'.$value.'"'.$checkedtype.' />'.$showloc.
                                         '</label></span></td>';
                     }                      }
                 }                      $rem = @locations%($numinrow);
                 $rem = $i%($numinrow);                      my $colsleft = $numinrow - $rem;
                 if ($rem == 0) {                      if ($colsleft > 1 ) {
                     if ($i > 0) {                          $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                         $datatable .= '</tr>';                                        '&nbsp;</td>';
                       } elsif ($colsleft == 1) {
                           $datatable .= '<td class="LC_left_item">&nbsp;</td>';
                     }                      }
                     $datatable .= '<tr>';                      $datatable .= '</tr></table>';
                 }                  }
                 $datatable .= '<td class="LC_left_item">'.                  $datatable .= '</td></tr>';
                               '<span class="LC_nobreak"><label>'.                  $itemcount ++;
                               '<input type="checkbox" name="'.$prefix.'_'.$type.  
                               '" value="'.$value.'"'.$checkedtype.' />'.$showloc.  
                               '</label></span></td>';  
             }  
             $rem = @locations%($numinrow);  
             my $colsleft = $numinrow - $rem;  
             if ($colsleft > 1 ) {  
                 $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.  
                               '&nbsp;</td>';  
             } elsif ($colsleft == 1) {  
                 $datatable .= '<td class="LC_left_item">&nbsp;</td>';  
             }              }
             $datatable .= '</tr></table>';  
         }          }
         $datatable .= '</td></tr>';  
         $itemcount ++;  
     }      }
     $$rowtotal += $itemcount;      $$rowtotal += $itemcount;
     return $datatable;      return $datatable;
Line 2447  sub build_location_hashes { Line 3313  sub build_location_hashes {
     return;      return;
 }  }
   
   sub current_offloads_to {
       my ($dom,$settings,$servers) = @_;
       my (%spareid,%otherdomconfigs);
       if (ref($servers) eq 'HASH') {
           foreach my $lonhost (sort(keys(%{$servers}))) {
               my $gotspares;
               if (ref($settings) eq 'HASH') {
                   if (ref($settings->{'spares'}) eq 'HASH') {
                       if (ref($settings->{'spares'}{$lonhost}) eq 'HASH') {
                           $spareid{$lonhost}{'primary'} = $settings->{'spares'}{$lonhost}{'primary'};
                           $spareid{$lonhost}{'default'} = $settings->{'spares'}{$lonhost}{'default'};
                           $gotspares = 1;
                       }
                   }
               }
               unless ($gotspares) {
                   my $gotspares;
                   my $serverhomeID =
                       &Apache::lonnet::get_server_homeID($servers->{$lonhost});
                   my $serverhomedom =
                       &Apache::lonnet::host_domain($serverhomeID);
                   if ($serverhomedom ne $dom) {
                       if (ref($otherdomconfigs{$serverhomedom} eq 'HASH')) {
                           if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}) eq 'HASH') {
                               if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}) eq 'HASH') {
                                   $spareid{$lonhost}{'primary'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'primary'};
                                   $spareid{$lonhost}{'default'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'default'};
                                   $gotspares = 1;
                               }
                           }
                       } else {
                           $otherdomconfigs{$serverhomedom} =
                               &Apache::lonnet::get_dom('configuration',['usersessions'],$serverhomedom);
                           if (ref($otherdomconfigs{$serverhomedom}) eq 'HASH') {
                               if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}) eq 'HASH') {
                                   if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}) eq 'HASH') {
                                       if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{$lonhost}) eq 'HASH') {
                                           $spareid{$lonhost}{'primary'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'primary'};
                                           $spareid{$lonhost}{'default'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'default'};
                                           $gotspares = 1;
                                       }
                                   }
                               }
                           }
                       }
                   }
               }
               unless ($gotspares) {
                   if ($lonhost eq $Apache::lonnet::perlvar{'lonHostID'}) {
                       $spareid{$lonhost}{'primary'} = $Apache::lonnet::spareid{'primary'};
                       $spareid{$lonhost}{'default'} = $Apache::lonnet::spareid{'default'};
                  } else {
                       my $server_hostname = &Apache::lonnet::hostname($lonhost);
                       my $server_homeID = &Apache::lonnet::get_server_homeID($server_hostname);
                       if ($server_homeID eq $Apache::lonnet::perlvar{'lonHostID'}) {
                           $spareid{$lonhost}{'primary'} = $Apache::lonnet::spareid{'primary'};
                           $spareid{$lonhost}{'default'} = $Apache::lonnet::spareid{'default'};
                       } else {
                           my %what = (
                                spareid => 1,
                           );
                           my ($result,$returnhash) = 
                               &Apache::lonnet::get_remote_globals($lonhost,\%what);
                           if ($result eq 'ok') { 
                               if (ref($returnhash) eq 'HASH') {
                                   if (ref($returnhash->{'spareid'}) eq 'HASH') {
                                       $spareid{$lonhost}{'primary'} = $returnhash->{'spareid'}->{'primary'};
                                       $spareid{$lonhost}{'default'} = $returnhash->{'spareid'}->{'default'};
                                   }
                               }
                           }
                       }
                   }
               }
           }
       }
       return %spareid;
   }
   
   sub spares_row {
       my ($dom,$servers,$spareid,$serverhomes,$altids,$rowtotal) = @_;
       my $css_class;
       my $numinrow = 4;
       my $itemcount = 1;
       my $datatable;
       my %typetitles = &sparestype_titles();
       if ((ref($servers) eq 'HASH') && (ref($spareid) eq 'HASH') && (ref($altids) eq 'HASH')) {
           foreach my $server (sort(keys(%{$servers}))) {
               my $serverhome = &Apache::lonnet::get_server_homeID($servers->{$server});
               my ($othercontrol,$serverdom);
               if ($serverhome ne $server) {
                   $serverdom = &Apache::lonnet::host_domain($serverhome);
                   $othercontrol = &mt('Session offloading controlled by domain: [_1]','<b>'.$serverdom.'</b>');
               } else {
                   $serverdom = &Apache::lonnet::host_domain($server);
                   if ($serverdom ne $dom) {
                       $othercontrol = &mt('Session offloading controlled by domain: [_1]','<b>'.$serverdom.'</b>');
                   }
               }
               next unless (ref($spareid->{$server}) eq 'HASH');
               $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
               $datatable .= '<tr'.$css_class.'>
                              <td rowspan="2">
                               <span class="LC_nobreak">'.
                             &mt('[_1] when busy, offloads to:'
                                 ,'<b>'.$server.'</b>').
                             "\n";
               my (%current,%canselect);
               my @choices = 
                   &possible_newspares($server,$spareid->{$server},$serverhomes,$altids);
               foreach my $type ('primary','default') {
                   if (ref($spareid->{$server}) eq 'HASH') {
                       if (ref($spareid->{$server}{$type}) eq 'ARRAY') {
                           my @spares = @{$spareid->{$server}{$type}};
                           if (@spares > 0) {
                               if ($othercontrol) {
                                   $current{$type} = join(', ',@spares);
                               } else {
                                   $current{$type} .= '<table>';
                                   my $numspares = scalar(@spares);
                                   for (my $i=0;  $i<@spares; $i++) {
                                       my $rem = $i%($numinrow);
                                       if ($rem == 0) {
                                           if ($i > 0) {
                                               $current{$type} .= '</tr>';
                                           }
                                           $current{$type} .= '<tr>';
                                       }
                                       $current{$type} .= '<td><label><input type="checkbox" name="spare_'.$type.'_'.$server.'" id="spare_'.$type.'_'.$server.'_'.$i.'" checked="checked" value="'.$spareid->{$server}{$type}[$i].'" onclick="updateNewSpares(this.form,'."'$server'".');" />&nbsp;'.
                                                          $spareid->{$server}{$type}[$i].
                                                          '</label></td>'."\n";
                                   }
                                   my $rem = @spares%($numinrow);
                                   my $colsleft = $numinrow - $rem;
                                   if ($colsleft > 1 ) {
                                       $current{$type} .= '<td colspan="'.$colsleft.
                                                          '" class="LC_left_item">'.
                                                          '&nbsp;</td>';
                                   } elsif ($colsleft == 1) {
                                       $current{$type} .= '<td class="LC_left_item">&nbsp;</td>'."\n";
                                   }
                                   $current{$type} .= '</tr></table>';
                               }
                           }
                       }
                       if ($current{$type} eq '') {
                           $current{$type} = &mt('None specified');
                       }
                       if ($othercontrol) {
                           if ($type eq 'primary') {
                               $canselect{$type} = $othercontrol;
                           }
                       } else {
                           $canselect{$type} = 
                               &mt('Add new [_1]'.$type.'[_2]:','<i>','</i>').'&nbsp;'.
                               '<select name="newspare_'.$type.'_'.$server.'" '.
                               'id="newspare_'.$type.'_'.$server.'" onchange="checkNewSpares('."'$server','$type'".');">'."\n".
                               '<option value="" selected ="selected">'.&mt('Select').'</option>'."\n";
                           if (@choices > 0) {
                               foreach my $lonhost (@choices) {
                                   $canselect{$type} .= '<option value="'.$lonhost.'">'.$lonhost.'</option>'."\n";
                               }
                           }
                           $canselect{$type} .= '</select>'."\n";
                       }
                   } else {
                       $current{$type} = &mt('Could not be determined');
                       if ($type eq 'primary') {
                           $canselect{$type} =  $othercontrol;
                       }
                   }
                   if ($type eq 'default') {
                       $datatable .= '<tr'.$css_class.'>';
                   }
                   $datatable .= '<td><i>'.$typetitles{$type}.'</i></td>'."\n".
                                 '<td>'.$current{$type}.'</td>'."\n".
                                 '<td>'.$canselect{$type}.'</td></tr>'."\n";
               }
               $itemcount ++;
           }
       }
       $$rowtotal += $itemcount;
       return $datatable;
   }
   
   sub possible_newspares {
       my ($server,$currspares,$serverhomes,$altids) = @_;
       my $serverhostname = &Apache::lonnet::hostname($server);
       my %excluded;
       if ($serverhostname ne '') {
           %excluded = (
                          $serverhostname => 1,
                       );
       }
       if (ref($currspares) eq 'HASH') {
           foreach my $type (keys(%{$currspares})) {
               if (ref($currspares->{$type}) eq 'ARRAY') {
                   if (@{$currspares->{$type}} > 0) {
                       foreach my $curr (@{$currspares->{$type}}) {
                           my $hostname = &Apache::lonnet::hostname($curr);
                           $excluded{$hostname} = 1;
                       }
                   }
               }
           }
       }
       my @choices;
       if ((ref($serverhomes) eq 'HASH') && (ref($altids) eq 'HASH')) {
           if (keys(%{$serverhomes}) > 1) {
               foreach my $name (sort(keys(%{$serverhomes}))) {
                   unless ($excluded{$name}) {
                       if (exists($altids->{$serverhomes->{$name}})) {
                           push(@choices,$altids->{$serverhomes->{$name}});
                       } else {
                           push(@choices,$serverhomes->{$name});
                       }
                   }
               }
           }
       }
       return sort(@choices);
   }
   
   sub print_loadbalancing {
       my ($dom,$settings,$rowtotal) = @_;
       my $primary_id = &Apache::lonnet::domain($dom,'primary');
       my $intdom = &Apache::lonnet::internet_dom($primary_id);
       my $numinrow = 1;
       my $datatable;
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my (%currbalancer,%currtargets,%currrules,%existing);
       if (ref($settings) eq 'HASH') {
           %existing = %{$settings};
       }
       if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
           &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
                                     \%currtargets,\%currrules);
       } else {
           return;
       }
       my ($othertitle,$usertypes,$types) =
           &Apache::loncommon::sorted_inst_types($dom);
       my $rownum = 8;
       if (ref($types) eq 'ARRAY') {
           $rownum += scalar(@{$types});
       }
       my @css_class = ('LC_odd_row','LC_even_row');
       my $balnum = 0;
       my $islast;
       my (@toshow,$disabledtext);
       if (keys(%currbalancer) > 0) {
           @toshow = sort(keys(%currbalancer));
           if (scalar(@toshow) < scalar(keys(%servers)) + 1) {
               push(@toshow,'');
           }
       } else {
           @toshow = ('');
           $disabledtext = &mt('No existing load balancer');
       }
       foreach my $lonhost (@toshow) {
           if ($balnum == scalar(@toshow)-1) {
               $islast = 1;
           } else {
               $islast = 0;
           }
           my $cssidx = $balnum%2;
           my $targets_div_style = 'display: none';
           my $disabled_div_style = 'display: block';
           my $homedom_div_style = 'display: none';
           $datatable .= '<tr class="'.$css_class[$cssidx].'">'.
                         '<td rowspan="'.$rownum.'" valign="top">'.
                         '<p>';
           if ($lonhost eq '') {
               $datatable .= '<span class="LC_nobreak">';
               if (keys(%currbalancer) > 0) {
                   $datatable .= &mt('Add balancer:');
               } else {
                   $datatable .= &mt('Enable balancer:');
               }
               $datatable .= '&nbsp;'.
                             '<select name="loadbalancing_lonhost_'.$balnum.'"'.
                             ' id="loadbalancing_lonhost_'.$balnum.'"'.
                             ' onchange="toggleTargets('."'$balnum'".');">'."\n".
                             '<option value="" selected="selected">'.&mt('None').
                             '</option>'."\n";
               foreach my $server (sort(keys(%servers))) {
                   next if ($currbalancer{$server});
                   $datatable .= '<option value="'.$server.'">'.$server.'</option>'."\n";
               }
               $datatable .=
                   '</select>'."\n".
                   '<input type="hidden" name="loadbalancing_prevlonhost_'.$balnum.'" id="loadbalancing_prevlonhost_'.$balnum.'" value="" />&nbsp;</span>'."\n";
           } else {
               $datatable .= '<i>'.$lonhost.'</i><br /><span class="LC_nobreak">'.
                             '<label><input type="checkbox" name="loadbalancing_delete" value="'.$balnum.'" id="loadbalancing_delete_'.$balnum.'" onclick="javascript:balancerDeleteChange('."'$balnum'".');" />&nbsp;'.
                              &mt('Stop balancing').'</label>'.
                              '<input type="hidden" name="loadbalancing_lonhost_'.$balnum.'" value="'.$lonhost.'" id="loadbalancing_lonhost_'.$balnum.'" /></span>';
               $targets_div_style = 'display: block';
               $disabled_div_style = 'display: none';
               if ($dom eq &Apache::lonnet::host_domain($lonhost)) {
                   $homedom_div_style = 'display: block';
               }
           }
           $datatable .= '</p></td><td rowspan="'.$rownum.'" valign="top">'.
                     '<div id="loadbalancing_disabled_'.$balnum.'" style="'.
                     $disabled_div_style.'">'.$disabledtext.'</div>'."\n".
                     '<div id="loadbalancing_targets_'.$balnum.'" style="'.$targets_div_style.'">'.&mt('Offloads to:').'<br />';
           my ($numspares,@spares) = &count_servers($lonhost,%servers);
           my @sparestypes = ('primary','default');
           my %typetitles = &sparestype_titles();
           foreach my $sparetype (@sparestypes) {
               my $targettable;
               for (my $i=0; $i<$numspares; $i++) {
                   my $checked;
                   if (ref($currtargets{$lonhost}) eq 'HASH') {
                       if (ref($currtargets{$lonhost}{$sparetype}) eq 'ARRAY') {
                           if (grep(/^\Q$spares[$i]\E$/,@{$currtargets{$lonhost}{$sparetype}})) {
                               $checked = ' checked="checked"';
                           }
                       }
                   }
                   my ($chkboxval,$disabled);
                   if (($lonhost ne '') && (exists($servers{$lonhost}))) {
                       $chkboxval = $spares[$i];
                   }
                   if (exists($currbalancer{$spares[$i]})) {
                       $disabled = ' disabled="disabled"';
                   }
                   $targettable .=
                       '<td><label><input type="checkbox" name="loadbalancing_target_'.$balnum.'_'.$sparetype.'"'.
                       $checked.$disabled.' value="'.$chkboxval.'" id="loadbalancing_target_'.$balnum.'_'.$sparetype.'_'.$i.'" onclick="checkOffloads('."this,'$balnum','$sparetype'".');" /><span id="loadbalancing_targettxt_'.$balnum.'_'.$sparetype.'_'.$i.'">&nbsp;'.$chkboxval.
                       '</span></label></td>';
                   my $rem = $i%($numinrow);
                   if ($rem == 0) {
                       if (($i > 0) && ($i < $numspares-1)) {
                           $targettable .= '</tr>';
                       }
                       if ($i < $numspares-1) {
                           $targettable .= '<tr>';
                       }
                   }
               }
               if ($targettable ne '') {
                   my $rem = $numspares%($numinrow);
                   my $colsleft = $numinrow - $rem;
                   if ($colsleft > 1 ) {
                       $targettable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                                       '&nbsp;</td>';
                   } elsif ($colsleft == 1) {
                       $targettable .= '<td class="LC_left_item">&nbsp;</td>';
                   }
                   $datatable .=  '<i>'.$typetitles{$sparetype}.'</i><br />'.
                                  '<table><tr>'.$targettable.'</tr></table><br />';
               }
           }
           $datatable .= '</div></td></tr>'.
                         &loadbalancing_rules($dom,$intdom,$currrules{$lonhost},
                                              $othertitle,$usertypes,$types,\%servers,
                                              \%currbalancer,$lonhost,
                                              $targets_div_style,$homedom_div_style,
                                              $css_class[$cssidx],$balnum,$islast);
           $$rowtotal += $rownum;
           $balnum ++;
       }
       $datatable .= '<input type="hidden" name="loadbalancing_total" id="loadbalancing_total" value="'.$balnum.'" />';
       return $datatable;
   }
   
   sub get_loadbalancers_config {
       my ($servers,$existing,$currbalancer,$currtargets,$currrules) = @_;
       return unless ((ref($servers) eq 'HASH') &&
                      (ref($existing) eq 'HASH') && (ref($currbalancer) eq 'HASH') &&
                      (ref($currtargets) eq 'HASH') && (ref($currrules) eq 'HASH'));
       if (keys(%{$existing}) > 0) {
           my $oldlonhost;
           foreach my $key (sort(keys(%{$existing}))) {
               if ($key eq 'lonhost') {
                   $oldlonhost = $existing->{'lonhost'};
                   $currbalancer->{$oldlonhost} = 1;
               } elsif ($key eq 'targets') {
                   if ($oldlonhost) {
                       $currtargets->{$oldlonhost} = $existing->{'targets'};
                   }
               } elsif ($key eq 'rules') {
                   if ($oldlonhost) {
                       $currrules->{$oldlonhost} = $existing->{'rules'};
                   }
               } elsif (ref($existing->{$key}) eq 'HASH') {
                   $currbalancer->{$key} = 1;
                   $currtargets->{$key} = $existing->{$key}{'targets'};
                   $currrules->{$key} = $existing->{$key}{'rules'};
               }
           }
       } else {
           my ($balancerref,$targetsref) =
                   &Apache::lonnet::get_lonbalancer_config($servers);
           if ((ref($balancerref) eq 'HASH') && (ref($targetsref) eq 'HASH')) {
               foreach my $server (sort(keys(%{$balancerref}))) {
                   $currbalancer->{$server} = 1;
                   $currtargets->{$server} = $targetsref->{$server};
               }
           }
       }
       return;
   }
   
   sub loadbalancing_rules {
       my ($dom,$intdom,$currrules,$othertitle,$usertypes,$types,$servers,
           $currbalancer,$lonhost,$targets_div_style,$homedom_div_style,
           $css_class,$balnum,$islast) = @_;
       my $output;
       my $num = 0;
       my ($alltypes,$othertypes,$titles) =
           &loadbalancing_titles($dom,$intdom,$usertypes,$types);
       if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH'))  {
           foreach my $type (@{$alltypes}) {
               $num ++;
               my $current;
               if (ref($currrules) eq 'HASH') {
                   $current = $currrules->{$type};
               }
               if (($type eq '_LC_external') || ($type eq '_LC_internetdom') || ($type eq '_LC_ipchange')) {
                   if ($dom ne &Apache::lonnet::host_domain($lonhost)) {
                       $current = '';
                   }
               }
               $output .= &loadbalance_rule_row($type,$titles->{$type},$current,
                                                $servers,$currbalancer,$lonhost,$dom,
                                                $targets_div_style,$homedom_div_style,
                                                $css_class,$balnum,$num,$islast);
           }
       }
       return $output;
   }
   
   sub loadbalancing_titles {
       my ($dom,$intdom,$usertypes,$types) = @_;
       my %othertypes = (
              '_LC_adv'         => &mt('Advanced users from [_1]',$dom),
              '_LC_author'      => &mt('Users from [_1] with author role',$dom),
              '_LC_internetdom' => &mt('Users not from [_1], but from [_2]',$dom,$intdom),
              '_LC_external'    => &mt('Users not from [_1]',$intdom),
              '_LC_ipchangesso' => &mt('SSO users from [_1], with IP mismatch',$dom),
              '_LC_ipchange'    => &mt('Non-SSO users with IP mismatch'),
                        );
       my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external','_LC_ipchangesso','_LC_ipchange');
       if (ref($types) eq 'ARRAY') {
           unshift(@alltypes,@{$types},'default');
       }
       my %titles;
       foreach my $type (@alltypes) {
           if ($type =~ /^_LC_/) {
               $titles{$type} = $othertypes{$type};
           } elsif ($type eq 'default') {
               $titles{$type} = &mt('All users from [_1]',$dom);
               if (ref($types) eq 'ARRAY') {
                   if (@{$types} > 0) {
                       $titles{$type} = &mt('Other users from [_1]',$dom);
                   }
               }
           } elsif (ref($usertypes) eq 'HASH') {
               $titles{$type} = $usertypes->{$type};
           }
       }
       return (\@alltypes,\%othertypes,\%titles);
   }
   
   sub loadbalance_rule_row {
       my ($type,$title,$current,$servers,$currbalancer,$lonhost,$dom,
           $targets_div_style,$homedom_div_style,$css_class,$balnum,$num,$islast) = @_;
       my @rulenames;
       my %ruletitles = &offloadtype_text();
       if (($type eq '_LC_ipchangesso') || ($type eq '_LC_ipchange')) {
           @rulenames = ('balancer','offloadedto');
       } else {
           @rulenames = ('default','homeserver');
           if ($type eq '_LC_external') {
               push(@rulenames,'externalbalancer');
           } else {
               push(@rulenames,'specific');
           }
           push(@rulenames,'none');
       }
       my $style = $targets_div_style;
       if (($type eq '_LC_external') || ($type eq '_LC_internetdom') || ($type eq '_LC_ipchange')) {
           $style = $homedom_div_style;
       }
       my $space;
       if ($islast && $num == 1) {
           $space = '<div display="inline-block">&nbsp;</div>';
       }
       my $output =
           '<tr class="'.$css_class.'" id="balanceruletr_'.$balnum.'_'.$num.'"><td valign="top">'.$space.
           '<div id="balanceruletitle_'.$balnum.'_'.$type.'" style="'.$style.'">'.$title.'</div></td>'."\n".
           '<td valaign="top">'.$space.
           '<div id="balancerule_'.$balnum.'_'.$type.'" style="'.$style.'">'."\n";
       for (my $i=0; $i<@rulenames; $i++) {
           my $rule = $rulenames[$i];
           my ($checked,$extra);
           if ($rulenames[$i] eq 'default') {
               $rule = '';
           }
           if ($rulenames[$i] eq 'specific') {
               if (ref($servers) eq 'HASH') {
                   my $default;
                   if (($current ne '') && (exists($servers->{$current}))) {
                       $checked = ' checked="checked"';
                   }
                   unless ($checked) {
                       $default = ' selected="selected"';
                   }
                   $extra =
                       ':&nbsp;<select name="loadbalancing_singleserver_'.$balnum.'_'.$type.
                       '" id="loadbalancing_singleserver_'.$balnum.'_'.$type.
                       '" onchange="singleServerToggle('."'$balnum','$type'".')">'."\n".
                       '<option value=""'.$default.'></option>'."\n";
                   foreach my $server (sort(keys(%{$servers}))) {
                       if (ref($currbalancer) eq 'HASH') {
                           next if (exists($currbalancer->{$server}));
                       }
                       my $selected;
                       if ($server eq $current) {
                           $selected = ' selected="selected"';
                       }
                       $extra .= '<option value="'.$server.'"'.$selected.'>'.$server.'</option>';
                   }
                   $extra .= '</select>';
               }
           } elsif ($rule eq $current) {
               $checked = ' checked="checked"';
           }
           $output .= '<span class="LC_nobreak"><label>'.
                      '<input type="radio" name="loadbalancing_rules_'.$balnum.'_'.$type.
                      '" id="loadbalancing_rules_'.$balnum.'_'.$type.'_'.$i.'" value="'.
                      $rule.'" onclick="balanceruleChange('."this.form,'$balnum','$type'".
                      ')"'.$checked.' />&nbsp;'.$ruletitles{$rulenames[$i]}.
                      '</label>'.$extra.'</span><br />'."\n";
       }
       $output .= '</div></td></tr>'."\n";
       return $output;
   }
   
   sub offloadtype_text {
       my %ruletitles = &Apache::lonlocal::texthash (
              'default'          => 'Offloads to default destinations',
              'homeserver'       => "Offloads to user's home server",
              'externalbalancer' => "Offloads to Load Balancer in user's domain",
              'specific'         => 'Offloads to specific server',
              'none'             => 'No offload',
              'balancer'         => 'Session hosted on Load Balancer, after re-authentication',
              'offloadedto'      => 'Session hosted on offload server, after re-authentication',
       );
       return %ruletitles;
   }
   
   sub sparestype_titles {
       my %typestitles = &Apache::lonlocal::texthash (
                             'primary' => 'primary',
                             'default' => 'default',
                         );
       return %typestitles;
   }
   
 sub contact_titles {  sub contact_titles {
     my %titles = &Apache::lonlocal::texthash (      my %titles = &Apache::lonlocal::texthash (
                    'supportemail' => 'Support E-mail address',                     'supportemail' => 'Support E-mail address',
Line 2456  sub contact_titles { Line 3885  sub contact_titles {
                    'helpdeskmail' => 'Helpdesk requests to be e-mailed to',                     'helpdeskmail' => 'Helpdesk requests to be e-mailed to',
                    'lonstatusmail' => 'E-mail from nightly status check (warnings/errors)',                     'lonstatusmail' => 'E-mail from nightly status check (warnings/errors)',
                    'requestsmail' => 'E-mail from course requests requiring approval',                     'requestsmail' => 'E-mail from course requests requiring approval',
                      'updatesmail'  => 'E-mail from nightly check of LON-CAPA module integrity/updates',
                      'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID',
                  );                   );
     my %short_titles = &Apache::lonlocal::texthash (      my %short_titles = &Apache::lonlocal::texthash (
                            adminemail   => 'Admin E-mail address',                             adminemail   => 'Admin E-mail address',
Line 2466  sub contact_titles { Line 3897  sub contact_titles {
   
 sub tool_titles {  sub tool_titles {
     my %titles = &Apache::lonlocal::texthash (      my %titles = &Apache::lonlocal::texthash (
                      aboutme    => 'Personal Information Page',                       aboutme    => 'Personal web page',
                      blog       => 'Blog',                       blog       => 'Blog',
                        webdav     => 'WebDAV',
                      portfolio  => 'Portfolio',                       portfolio  => 'Portfolio',
                      official   => 'Official courses (with institutional codes)',                       official   => 'Official courses (with institutional codes)',
                      unofficial => 'Unofficial courses',                       unofficial => 'Unofficial courses',
                      community  => 'Communities',                       community  => 'Communities',
                        textbook   => 'Textbook courses',
                  );                   );
     return %titles;      return %titles;
 }  }
Line 2481  sub courserequest_titles { Line 3914  sub courserequest_titles {
                                    official   => 'Official',                                     official   => 'Official',
                                    unofficial => 'Unofficial',                                     unofficial => 'Unofficial',
                                    community  => 'Communities',                                     community  => 'Communities',
                                      textbook   => 'Textbook',
                                    norequest  => 'Not allowed',                                     norequest  => 'Not allowed',
                                    approval   => 'Approval by Dom. Coord.',                                     approval   => 'Approval by Dom. Coord.',
                                    validate   => 'With validation',                                     validate   => 'With validation',
Line 2490  sub courserequest_titles { Line 3924  sub courserequest_titles {
     return %titles;      return %titles;
 }  }
   
   sub authorrequest_titles {
       my %titles = &Apache::lonlocal::texthash (
                                      norequest  => 'Not allowed',
                                      approval   => 'Approval by Dom. Coord.',
                                      automatic  => 'Automatic approval',
                    );
       return %titles;
   }
   
 sub courserequest_conditions {  sub courserequest_conditions {
     my %conditions = &Apache::lonlocal::texthash (      my %conditions = &Apache::lonlocal::texthash (
        approval    => '(Processing of request subject to approval by Domain Coordinator).',         approval    => '(Processing of request subject to approval by Domain Coordinator).',
        validate   => '(Processing of request subject to instittutional validation).',         validate   => '(Processing of request subject to institutional validation).',
                  );                   );
     return %conditions;      return %conditions;
 }  }
Line 2524  sub print_usercreation { Line 3967  sub print_usercreation {
                 $rowcount ++;                  $rowcount ++;
             }              }
         }          }
         my ($emailrules,$emailruleorder) =   
             &Apache::lonnet::inst_userrules($dom,'email');  
         if (ref($emailrules) eq 'HASH') {  
             if (keys(%{$emailrules}) > 0) {  
                 $datatable .= &user_formats_row('email',$settings,$emailrules,  
                                                 $emailruleorder,$numinrow,$rowcount);  
                 $$rowtotal ++;  
                 $rowcount ++;  
             }  
         }  
         if ($rowcount == 0) {          if ($rowcount == 0) {
             $datatable .= '<tr><td colspan="2">'.&mt('No format rules have been defined for usernames or IDs in this domain.').'</td></tr>';                $datatable .= '<tr><td colspan="2">'.&mt('No format rules have been defined for usernames or IDs in this domain.').'</td></tr>';  
             $$rowtotal ++;              $$rowtotal ++;
             $rowcount ++;              $rowcount ++;
         }          }
     } elsif ($position eq 'middle') {      } elsif ($position eq 'middle') {
         my @creators = ('author','course','requestcrs','selfcreate');          my @creators = ('author','course','requestcrs');
         my ($rules,$ruleorder) =          my ($rules,$ruleorder) =
             &Apache::lonnet::inst_userrules($dom,'username');              &Apache::lonnet::inst_userrules($dom,'username');
         my %lt = &usercreation_types();          my %lt = &usercreation_types();
         my %checked;          my %checked;
         my @selfcreate;   
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if (ref($settings->{'cancreate'}) eq 'HASH') {              if (ref($settings->{'cancreate'}) eq 'HASH') {
                 foreach my $item (@creators) {                  foreach my $item (@creators) {
                     $checked{$item} = $settings->{'cancreate'}{$item};                      $checked{$item} = $settings->{'cancreate'}{$item};
                 }                  }
                 if (ref($settings->{'cancreate'}{'selfcreate'}) eq 'ARRAY') {  
                     @selfcreate = @{$settings->{'cancreate'}{'selfcreate'}};  
                 } elsif ($settings->{'cancreate'}{'selfcreate'} ne '') {  
                     if ($settings->{'cancreate'}{'selfcreate'} eq 'any') {  
                         @selfcreate = ('email','login','sso');  
                     } elsif ($settings->{'cancreate'}{'selfcreate'} ne 'none') {  
                         @selfcreate = ($settings->{'cancreate'}{'selfcreate'});  
                     }  
                 }  
             } elsif (ref($settings->{'cancreate'}) eq 'ARRAY') {              } elsif (ref($settings->{'cancreate'}) eq 'ARRAY') {
                 foreach my $item (@creators) {                  foreach my $item (@creators) {
                     if (grep(/^\Q$item\E$/,@{$settings->{'cancreate'}})) {                      if (grep(/^\Q$item\E$/,@{$settings->{'cancreate'}})) {
Line 2571  sub print_usercreation { Line 3994  sub print_usercreation {
         my $rownum = 0;          my $rownum = 0;
         foreach my $item (@creators) {          foreach my $item (@creators) {
             $rownum ++;              $rownum ++;
             if ($item ne 'selfcreate') {                if ($checked{$item} eq '') {
                 if ($checked{$item} eq '') {                  $checked{$item} = 'any';
                     $checked{$item} = 'any';  
                 }  
             }              }
             my $css_class;              my $css_class;
             if ($rownum%2) {              if ($rownum%2) {
Line 2585  sub print_usercreation { Line 4006  sub print_usercreation {
             $datatable .= '<tr'.$css_class.'>'.              $datatable .= '<tr'.$css_class.'>'.
                          '<td><span class="LC_nobreak">'.$lt{$item}.                           '<td><span class="LC_nobreak">'.$lt{$item}.
                          '</span></td><td align="right">';                           '</span></td><td align="right">';
             my @options;              my @options = ('any');
             if ($item eq 'selfcreate') {              if (ref($rules) eq 'HASH') {
                 push(@options,('email','login','sso'));                  if (keys(%{$rules}) > 0) {
             } else {                      push(@options,('official','unofficial'));
                 @options = ('any');  
                 if (ref($rules) eq 'HASH') {  
                     if (keys(%{$rules}) > 0) {  
                         push(@options,('official','unofficial'));  
                     }  
                 }                  }
                 push(@options,'none');  
             }              }
               push(@options,'none');
             foreach my $option (@options) {              foreach my $option (@options) {
                 my $type = 'radio';                  my $type = 'radio';
                 my $check = ' ';                  my $check = ' ';
                 if ($item eq 'selfcreate') {                  if ($checked{$item} eq $option) {
                     $type = 'checkbox';                      $check = ' checked="checked" ';
                     if (grep(/^\Q$option\E$/,@selfcreate)) {  
                         $check = ' checked="checked" ';  
                     }  
                 } else {  
                     if ($checked{$item} eq $option) {  
                         $check = ' checked="checked" ';  
                     }  
                 }                   } 
                 $datatable .= '<span class="LC_nobreak"><label>'.                  $datatable .= '<span class="LC_nobreak"><label>'.
                               '<input type="'.$type.'" name="can_createuser_'.                                '<input type="'.$type.'" name="can_createuser_'.
Line 2617  sub print_usercreation { Line 4026  sub print_usercreation {
             }              }
             $datatable .= '</td></tr>';              $datatable .= '</td></tr>';
         }          }
         my ($othertitle,$usertypes,$types) =  
             &Apache::loncommon::sorted_inst_types($dom);  
         if (ref($usertypes) eq 'HASH') {  
             if (keys(%{$usertypes}) > 0) {  
                 my $createsettings;  
                 if (ref($settings) eq 'HASH') {  
                     $createsettings = $settings->{cancreate};  
                 }  
                 $datatable .= &insttypes_row($createsettings,$types,$usertypes,  
                                              $dom,$numinrow,$othertitle,  
                                              'statustocreate');  
                 $$rowtotal ++;  
             }  
         }  
     } else {      } else {
         my @contexts = ('author','course','domain');          my @contexts = ('author','course','domain');
         my @authtypes = ('int','krb4','krb5','loc');          my @authtypes = ('int','krb4','krb5','loc');
Line 2682  sub print_usercreation { Line 4077  sub print_usercreation {
     return $datatable;      return $datatable;
 }  }
   
   sub print_selfcreation {
       my ($position,$dom,$settings,$rowtotal) = @_;
       my (@selfcreate,$createsettings,$processing,$datatable);
       if (ref($settings) eq 'HASH') {
           if (ref($settings->{'cancreate'}) eq 'HASH') {
               $createsettings = $settings->{'cancreate'};
               if (ref($createsettings) eq 'HASH') {
                   if (ref($createsettings->{'selfcreate'}) eq 'ARRAY') {
                       @selfcreate = @{$createsettings->{'selfcreate'}};
                   } elsif ($createsettings->{'selfcreate'} ne '') {
                       if ($settings->{'cancreate'}{'selfcreate'} eq 'any') {
                           @selfcreate = ('email','login','sso');
                       } elsif ($createsettings->{'selfcreate'} ne 'none') {
                           @selfcreate = ($createsettings->{'selfcreate'});
                       }
                   }
                   if (ref($createsettings->{'selfcreateprocessing'}) eq 'HASH') {
                       $processing = $createsettings->{'selfcreateprocessing'};
                   }
               }
           }
       }
       my %radiohash;
       my $numinrow = 4;
       map { $radiohash{'cancreate_'.$_} = 1; } @selfcreate;
       if ($position eq 'top') {
           my %choices = &Apache::lonlocal::texthash (
                                                         cancreate_login      => 'Institutional Login',
                                                         cancreate_sso        => 'Institutional Single Sign On',
                                                     );
           my @toggles = sort(keys(%choices));
           my %defaultchecked = (
                                  'cancreate_login' => 'off',
                                  'cancreate_sso'   => 'off',
                                );
           my ($onclick,$itemcount);
           ($datatable,$itemcount) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,
                                                        \%choices,$itemcount,$onclick);
           $$rowtotal += $itemcount;
           
           my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
   
           if (ref($usertypes) eq 'HASH') {
               if (keys(%{$usertypes}) > 0) {
                   $datatable .= &insttypes_row($createsettings,$types,$usertypes,
                                                $dom,$numinrow,$othertitle,
                                                'statustocreate',$$rowtotal);
                   $$rowtotal ++;
               }
           }
           my @fields = ('lastname','firstname','middlename','permanentemail','id','inststatus');
           my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
           $fieldtitles{'inststatus'} = &mt('Institutional status');
           my $rem;
           my $numperrow = 2;
           my $css_class = $$rowtotal%2?' class="LC_odd_row"':'';
           $datatable .= '<tr'.$css_class.'>'.
                        '<td class="LC_left_item">'.&mt('Mapping of Shibboleth environment variable names to user data fields (SSO auth)').'</td>'.
                        '<td class="LC_left_item">'."\n".
                        '<table><tr><td>'."\n";
           for (my $i=0; $i<@fields; $i++) {
               $rem = $i%($numperrow);
               if ($rem == 0) {
                   if ($i > 0) {
                       $datatable .= '</tr>';
                   }
                   $datatable .= '<tr>';
               }
               my $currval;
               if (ref($createsettings) eq 'HASH') {
                   if (ref($createsettings->{'shibenv'}) eq 'HASH') {
                       $currval = $createsettings->{'shibenv'}{$fields[$i]};
                   }
               }
               $datatable .= '<td class="LC_left_item">'.
                             '<span class="LC_nobreak">'.
                             '<input type="text" name="shibenv_'.$fields[$i].'" '.
                             'value="'.$currval.'" size="10" />&nbsp;'.
                             $fieldtitles{$fields[$i]}.'</span></td>';
           }
           my $colsleft = $numperrow - $rem;
           if ($colsleft > 1 ) {
               $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                            '&nbsp;</td>';
           } elsif ($colsleft == 1) {
               $datatable .= '<td class="LC_left_item">&nbsp;</td>';
           }
           $datatable .= '</tr></table></td></tr>';
           $$rowtotal ++;
       } elsif ($position eq 'middle') {
           my %domconf = &Apache::lonnet::get_dom('configuration',['usermodification'],$dom);
           my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
           $usertypes->{'default'} = $othertitle;
           if (ref($types) eq 'ARRAY') {
               push(@{$types},'default');
               $usertypes->{'default'} = $othertitle;
               foreach my $status (@{$types}) {
                   $datatable .= &modifiable_userdata_row('selfcreate',$status,$domconf{'usermodification'},
                                                          $numinrow,$$rowtotal,$usertypes);
                   $$rowtotal ++;
               }
           }
       } else {
           my %choices = &Apache::lonlocal::texthash (
                                                         cancreate_email => 'E-mail address as username',
                                                     );
           my @toggles = sort(keys(%choices));
           my %defaultchecked = (
                                  'cancreate_email' => 'off',
                                );
           my $itemcount = 0;
           my $display = 'none';
           if (grep(/^\Qemail\E$/,@selfcreate)) {
               $display = 'block';
           }
           my $onclick = "toggleDisplay(this.form,'emailoptions');";
           my $additional = '<div id="emailoptions" style="display: '.$display.'">';
           my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
           my $usertypes = {};
           my $order = [];
           if ((ref($domdefaults{'inststatustypes'}) eq 'HASH') && (ref($domdefaults{'inststatusguest'}) eq 'ARRAY')) {
               $usertypes = $domdefaults{'inststatustypes'};
               $order = $domdefaults{'inststatusguest'};
           }
           if (ref($order) eq 'ARRAY') {
               push(@{$order},'default');
               if (@{$order} > 1) {
                   $usertypes->{'default'} = &mt('Other users');
                   $additional .= '<table><tr>';
                   foreach my $status (@{$order}) {
                       $additional .= '<th>'.$usertypes->{$status}.'</th>';
                   }
                   $additional .= '</tr><tr>';
                   foreach my $status (@{$order}) {
                       $additional .= '<td>'.&email_as_username($rowtotal,$processing,$status).'</td>';
                   }
                   $additional .= '</tr></table>';
               } else {
                   $usertypes->{'default'} = &mt('All users');
                   $additional .= &email_as_username($rowtotal,$processing);
               }
           }
           $additional .= '</div>'."\n";
   
           ($datatable,$itemcount) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,
                                                        \%choices,$$rowtotal,$onclick,$additional);
           $$rowtotal ++;
           $datatable .= &print_requestmail($dom,'selfcreation',$createsettings,$rowtotal);
           $$rowtotal ++;
           my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();
           $numinrow = 1;
           if (ref($order) eq 'ARRAY') {
               foreach my $status (@{$order}) {
                   $datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,
                                                          $numinrow,$$rowtotal,$usertypes,$infofields,$infotitles);
                   $$rowtotal ++;
               }
           }
           my ($emailrules,$emailruleorder) =
               &Apache::lonnet::inst_userrules($dom,'email');
           if (ref($emailrules) eq 'HASH') {
               if (keys(%{$emailrules}) > 0) {
                   $datatable .= &user_formats_row('email',$settings,$emailrules,
                                                   $emailruleorder,$numinrow,$$rowtotal);
                   $$rowtotal ++;
               }
           }
           $datatable .= &captcha_choice('cancreate',$createsettings,$$rowtotal);
       }
       return $datatable;
   }
   
   sub email_as_username {
       my ($rowtotal,$processing,$type) = @_;
       my %choices =
           &Apache::lonlocal::texthash (
                                         automatic => 'Automatic approval',
                                         approval  => 'Queued for approval',
                                       );
       my $output;
       foreach my $option ('automatic','approval') {
           my $checked;
           if (ref($processing) eq 'HASH') {
               if ($type eq '') {   
                   if (!exists($processing->{'default'})) {
                       if ($option eq 'automatic') {
                           $checked = ' checked="checked"';
                       }
                   } else {
                       if ($processing->{'default'} eq $option) {
                           $checked = ' checked="checked"';
                       }
                   }
               } else {
                   if (!exists($processing->{$type})) {
                       if ($option eq 'automatic') {
                           $checked = ' checked="checked"';
                       }
                   } else {
                       if ($processing->{$type} eq $option) {
                           $checked = ' checked="checked"';
                       }
                   }
               }
           } elsif ($option eq 'automatic') {
               $checked = ' checked="checked"'; 
           }
           my $name = 'cancreate_emailprocess';
           if (($type ne '') && ($type ne 'default')) {
               $name .= '_'.$type;
           }
           $output .= '<span class="LC_nobreak"><label>'.
                      '<input type="radio" name="'.$name.'"'.
                      $checked.' value="'.$option.'" />'.
                      $choices{$option}.'</label></span>';
           if ($type eq '') {
               $output .= '&nbsp;';
           } else {
               $output .= '<br />';
           }
       }
       $$rowtotal ++;
       return $output;
   }
   
   sub captcha_choice {
       my ($context,$settings,$itemcount) = @_;
       my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext);
       my %lt = &captcha_phrases();
       $keyentry = 'hidden';
       if ($context eq 'cancreate') {
           $rowname = &mt('CAPTCHA validation');
       } elsif ($context eq 'login') {
           $rowname =  &mt('"Contact helpdesk" CAPTCHA validation');
       }
       if (ref($settings) eq 'HASH') {
           if ($settings->{'captcha'}) {
               $checked{$settings->{'captcha'}} = ' checked="checked"';
           } else {
               $checked{'original'} = ' checked="checked"';
           }
           if ($settings->{'captcha'} eq 'recaptcha') {
               $pubtext = $lt{'pub'};
               $privtext = $lt{'priv'};
               $keyentry = 'text';
           }
           if (ref($settings->{'recaptchakeys'}) eq 'HASH') {
               $currpub = $settings->{'recaptchakeys'}{'public'};
               $currpriv = $settings->{'recaptchakeys'}{'private'};
           }
       } else {
           $checked{'original'} = ' checked="checked"';
       }
       my $css_class = $itemcount%2?' class="LC_odd_row"':'';
       my $output = '<tr'.$css_class.'>'.
                    '<td class="LC_left_item">'.$rowname.'</td><td class="LC_left_item" colspan="2">'."\n".
                    '<table><tr><td>'."\n";
       foreach my $option ('original','recaptcha','notused') {
           $output .= '<span class="LC_nobreak"><label><input type="radio" name="'.$context.'_captcha" value="'.
                      $option.'" '.$checked{$option}.' onchange="javascript:updateCaptcha('."this,'$context'".');" />'.
                      $lt{$option}.'</label></span>';
           unless ($option eq 'notused') {
               $output .= ('&nbsp;'x2)."\n";
           }
       }
   #
   # Note: If reCAPTCHA is to be used for LON-CAPA servers in a domain, a domain coordinator should visit:
   # https://www.google.com/recaptcha and generate a Public and Private key. For domains with multiple
   # servers a single key pair will be used for all servers, so the internet domain (e.g., yourcollege.edu)
   # specified for use with the key should be broad enough to accommodate all servers in the LON-CAPA domain.
   #
       $output .= '</td></tr>'."\n".
                  '<tr><td>'."\n".
                  '<span class="LC_nobreak"><span id="'.$context.'_recaptchapubtxt">'.$pubtext.'</span>&nbsp;'."\n".
                  '<input type="'.$keyentry.'" id="'.$context.'_recaptchapub" name="'.$context.'_recaptchapub" value="'.
                  $currpub.'" size="40" /></span><br />'."\n".
                  '<span class="LC_nobreak"><span id="'.$context.'_recaptchaprivtxt">'.$privtext.'</span>&nbsp;'."\n".
                  '<input type="'.$keyentry.'" id="'.$context.'_recaptchapriv" name="'.$context.'_recaptchapriv" value="'.
                  $currpriv.'" size="40" /></span></td></tr></table>'."\n".
                  '</td></tr>';
       return $output;
   }
   
 sub user_formats_row {  sub user_formats_row {
     my ($type,$settings,$rules,$ruleorder,$numinrow,$rowcount) = @_;      my ($type,$settings,$rules,$ruleorder,$numinrow,$rowcount) = @_;
     my $output;      my $output;
Line 2744  sub usercreation_types { Line 4422  sub usercreation_types {
                     author     => 'When adding a co-author',                      author     => 'When adding a co-author',
                     course     => 'When adding a user to a course',                      course     => 'When adding a user to a course',
                     requestcrs => 'When requesting a course',                      requestcrs => 'When requesting a course',
                     selfcreate => 'User creates own account',   
                     any        => 'Any',                      any        => 'Any',
                     official   => 'Institutional only ',                      official   => 'Institutional only ',
                     unofficial => 'Non-institutional only',                      unofficial => 'Non-institutional only',
                     email      => 'E-mail address',  
                     login      => 'Institutional Login',  
                     sso        => 'SSO',   
                     none       => 'None',                      none       => 'None',
     );      );
     return %lt;      return %lt;
 }  }
   
   sub selfcreation_types {
       my %lt = &Apache::lonlocal::texthash (
                       selfcreate => 'User creates own account',
                       any        => 'Any',
                       official   => 'Institutional only ',
                       unofficial => 'Non-institutional only',
                       email      => 'E-mail address',
                       login      => 'Institutional Login',
                       sso        => 'SSO',
                );
   }
   
 sub authtype_names {  sub authtype_names {
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
                       int    => 'Internal',                        int    => 'Internal',
Line 2788  sub print_usermodification { Line 4474  sub print_usermodification {
             $$rowtotal ++;              $$rowtotal ++;
             $rowcount ++;              $rowcount ++;
         }          }
     } elsif ($position eq 'middle') {      } elsif ($position eq 'bottom') {
         $context = 'course';          $context = 'course';
         $rowcount = 0;          $rowcount = 0;
         foreach my $role ('st','ep','ta','in','cr') {          foreach my $role ('st','ep','ta','in','cr') {
Line 2797  sub print_usermodification { Line 4483  sub print_usermodification {
             $$rowtotal ++;              $$rowtotal ++;
             $rowcount ++;              $rowcount ++;
         }          }
     } elsif ($position eq 'bottom') {  
         $context = 'selfcreate';  
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
         $usertypes->{'default'} = $othertitle;  
         if (ref($types) eq 'ARRAY') {  
             push(@{$types},'default');  
             $usertypes->{'default'} = $othertitle;  
             foreach my $status (@{$types}) {  
                 $datatable .= &modifiable_userdata_row($context,$status,$settings,  
                                                        $numinrow,$rowcount,$usertypes);  
                 $$rowtotal ++;  
                 $rowcount ++;  
             }  
         }  
     }      }
     return $datatable;      return $datatable;
 }  }
   
 sub print_defaults {  sub print_defaults {
     my ($dom,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my @items = ('auth_def','auth_arg_def','lang_def','timezone_def',  
                  'datelocale_def');  
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);  
     my $titles = &defaults_titles();  
     my $rownum = 0;      my $rownum = 0;
     my ($datatable,$css_class);      my ($datatable,$css_class);
     foreach my $item (@items) {      if ($position eq 'top') {
         if ($rownum%2) {          my @items = ('auth_def','auth_arg_def','lang_def','timezone_def',
             $css_class = '';                       'datelocale_def','portal_def');
           my %defaults;
           if (ref($settings) eq 'HASH') {
               %defaults = %{$settings};
         } else {          } else {
             $css_class = ' class="LC_odd_row" ';              my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
               foreach my $item (@items) {
                   $defaults{$item} = $domdefaults{$item};
               }
         }          }
         $datatable .= '<tr'.$css_class.'>'.          my $titles = &defaults_titles($dom);
                   '<td><span class="LC_nobreak">'.$titles->{$item}.          foreach my $item (@items) {
                   '</span></td><td class="LC_right_item">';              if ($rownum%2) {
         if ($item eq 'auth_def') {                  $css_class = '';
             my @authtypes = ('internal','krb4','krb5','localauth');              } else {
             my %shortauth = (                  $css_class = ' class="LC_odd_row" ';
                              internal => 'int',              }
                              krb4 => 'krb4',              $datatable .= '<tr'.$css_class.'>'.
                              krb5 => 'krb5',                            '<td><span class="LC_nobreak">'.$titles->{$item}.
                              localauth  => 'loc'                            '</span></td><td class="LC_right_item" colspan="3">';
                            );              if ($item eq 'auth_def') {
             my %authnames = &authtype_names();                  my @authtypes = ('internal','krb4','krb5','localauth');
             foreach my $auth (@authtypes) {                  my %shortauth = (
                 my $checked = ' ';                                   internal => 'int',
                 if ($domdefaults{$item} eq $auth) {                                   krb4 => 'krb4',
                     $checked = ' checked="checked" ';                                   krb5 => 'krb5',
                 }                                   localauth  => 'loc'
                 $datatable .= '<label><input type="radio" name="'.$item.                                  );
                               '" value="'.$auth.'"'.$checked.'/>'.                  my %authnames = &authtype_names();
                               $authnames{$shortauth{$auth}}.'</label>&nbsp;&nbsp;';                  foreach my $auth (@authtypes) {
                       my $checked = ' ';
                       if ($defaults{$item} eq $auth) {
                           $checked = ' checked="checked" ';
                       }
                       $datatable .= '<label><input type="radio" name="'.$item.
                                     '" value="'.$auth.'"'.$checked.'/>'.
                                     $authnames{$shortauth{$auth}}.'</label>&nbsp;&nbsp;';
                   }
               } elsif ($item eq 'timezone_def') {
                   my $includeempty = 1;
                   $datatable .= &Apache::loncommon::select_timezone($item,$defaults{$item},undef,$includeempty);
               } elsif ($item eq 'datelocale_def') {
                   my $includeempty = 1;
                   $datatable .= &Apache::loncommon::select_datelocale($item,$defaults{$item},undef,$includeempty);
               } elsif ($item eq 'lang_def') {
                   my %langchoices = &get_languages_hash();
                   $langchoices{''} = 'No language preference';
                   %langchoices = &Apache::lonlocal::texthash(%langchoices);
                   $datatable .= &Apache::loncommon::select_form($defaults{$item},$item,
                                                                 \%langchoices);
               } else {
                   my $size;
                   if ($item eq 'portal_def') {
                       $size = ' size="25"';
                   }
                   $datatable .= '<input type="text" name="'.$item.'" value="'.
                                 $defaults{$item}.'"'.$size.' />';
               }
               $datatable .= '</td></tr>';
               $rownum ++;
           }
       } else {
           my (%defaults);
           if (ref($settings) eq 'HASH') {
               if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH') &&
                   (ref($settings->{'inststatusguest'}) eq 'ARRAY')) {
                   my $maxnum = @{$settings->{'inststatusorder'}};
                   for (my $i=0; $i<$maxnum; $i++) {
                       $css_class = $rownum%2?' class="LC_odd_row"':'';
                       my $item = $settings->{'inststatusorder'}->[$i];
                       my $title = $settings->{'inststatustypes'}->{$item};
                       my $guestok;
                       if (grep(/^\Q$item\E$/,@{$settings->{'inststatusguest'}})) {
                           $guestok = 1;
                       }
                       my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'$item'".');"';
                       $datatable .= '<tr'.$css_class.'>'.
                                     '<td><span class="LC_nobreak">'.
                                     '<select name="inststatus_pos_'.$item.'"'.$chgstr.'>';
                       for (my $k=0; $k<=$maxnum; $k++) {
                           my $vpos = $k+1;
                           my $selstr;
                           if ($k == $i) {
                               $selstr = ' selected="selected" ';
                           }
                           $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                       }
                       my ($checkedon,$checkedoff);
                       $checkedoff = ' checked="checked"';
                       if ($guestok) {
                           $checkedon = $checkedoff;
                           $checkedoff = ''; 
                       }
                       $datatable .= '</select>&nbsp;'.&mt('Internal ID:').'&nbsp;<b>'.$item.'</b>&nbsp;'.
                                     '<input type="checkbox" name="inststatus_delete" value="'.$item.'" />'.
                                     &mt('delete').'</span></td>'.
                                     '<td class="LC_left_item"><span class="LC_nobreak">'.&mt('Name displayed:').
                                     '<input type="text" size="20" name="inststatus_title_'.$item.'" value="'.$title.'" />'.
                                     '</span></td>'.
                                     '<td class="LC_right_item"><span class="LC_nobreak">'.
                                     '<label><input type="radio" value="1" name="inststatus_guest_'.$item.'"'.$checkedon.' />'.
                                     &mt('Yes').'</label>'.('&nbsp;'x2).
                                     '<label><input type="radio" value="0" name="inststatus_guest_'.$item.'"'.$checkedoff.' />'.
                                     &mt('No').'</label></span></td></tr>';
                   }
                   $css_class = $rownum%2?' class="LC_odd_row"':'';
                   my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'addinststatus_pos'".');"';
                   $datatable .= '<tr '.$css_class.'>'.
                                 '<td><span class="LC_nobreak"><select name="addinststatus_pos"'.$chgstr.'>';
                   for (my $k=0; $k<=$maxnum; $k++) {
                       my $vpos = $k+1;
                       my $selstr;
                       if ($k == $maxnum) {
                           $selstr = ' selected="selected" ';
                       }
                       $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                   }
                   $datatable .= '</select>&nbsp;'.&mt('Internal ID:').
                                 '<input type="text" size="10" name="addinststatus" value="" /></span>'.
                                 '&nbsp;'.&mt('(new)').
                                 '</span></td><td class="LC_left_item"><span class="LC_nobreak">'.
                                 &mt('Name displayed:').
                                 '<input type="text" size="20" name="addinststatus_title" value="" /></span></td>'.
                                 '<td class="LC_right_item"><span class="LC_nobreak">'.
                                 '<label><input type="radio" value="1" name="addinststatus_guest" />'.
                                 &mt('Yes').'</label>'.('&nbsp;'x2).
                                 '<label><input type="radio" value="0" name="addinststatus_guest" />'.
                                 &mt('No').'</label></span></td></tr>';
                                 '</tr>'."\n";
                   $rownum ++;
             }              }
         } elsif ($item eq 'timezone_def') {  
             my $includeempty = 1;  
             $datatable .= &Apache::loncommon::select_timezone($item,$domdefaults{$item},undef,$includeempty);  
         } elsif ($item eq 'datelocale_def') {  
             my $includeempty = 1;  
             $datatable .= &Apache::loncommon::select_datelocale($item,$domdefaults{$item},undef,$includeempty);  
         } else {  
             $datatable .= '<input type="text" name="'.$item.'" value="'.  
                           $domdefaults{$item}.'" />';  
         }          }
         $datatable .= '</td></tr>';  
         $rownum ++;  
     }      }
     $$rowtotal += $rownum;      $$rowtotal += $rownum;
     return $datatable;      return $datatable;
 }  }
   
   sub get_languages_hash {
       my %langchoices;
       foreach my $id (&Apache::loncommon::languageids()) {
           my $code = &Apache::loncommon::supportedlanguagecode($id);
           if ($code ne '') {
               $langchoices{$code} =  &Apache::loncommon::plainlanguagedescription($id);
           }
       }
       return %langchoices;
   }
   
 sub defaults_titles {  sub defaults_titles {
       my ($dom) = @_;
     my %titles = &Apache::lonlocal::texthash (      my %titles = &Apache::lonlocal::texthash (
                    'auth_def'      => 'Default authentication type',                     'auth_def'      => 'Default authentication type',
                    'auth_arg_def'  => 'Default authentication argument',                     'auth_arg_def'  => 'Default authentication argument',
                    'lang_def'      => 'Default language',                     'lang_def'      => 'Default language',
                    'timezone_def'  => 'Default timezone',                     'timezone_def'  => 'Default timezone',
                    'datelocale_def' => 'Default locale for dates',                     'datelocale_def' => 'Default locale for dates',
                      'portal_def'     => 'Portal/Default URL',
                  );                   );
       if ($dom) {
           my $uprimary_id = &Apache::lonnet::domain($dom,'primary');
           my $uint_dom = &Apache::lonnet::internet_dom($uprimary_id);
           my $protocol = $Apache::lonnet::protocol{$uprimary_id};
           $protocol = 'http' if ($protocol ne 'https');
           if ($uint_dom) {
               $titles{'portal_def'} .= ' '.&mt('(for example: [_1])',$protocol.'://loncapa.'.
                                            $uint_dom);
           }
       }
     return (\%titles);      return (\%titles);
 }  }
   
Line 2987  sub print_scantronformat { Line 4773  sub print_scantronformat {
         $datatable .= '<td>'.&mt('Default in use:').'<br />'.          $datatable .= '<td>'.&mt('Default in use:').'<br />'.
                       '<span class="LC_nobreak">';                        '<span class="LC_nobreak">';
         if ($scantronurl) {          if ($scantronurl) {
             $datatable .= '<a href="'.$scantronurl.'" target="_blank">'.              $datatable .= &Apache::loncommon::modal_link($scantronurl,&mt('Default bubblesheet format file'),600,500,
                           &mt('Default bubblesheet format file').'</a>';                                                           undef,undef,undef,undef,'background-color:#ffffff');
         } else {          } else {
             $datatable = &mt('File unavailable for display');              $datatable = &mt('File unavailable for display');
         }          }
Line 3013  sub print_scantronformat { Line 4799  sub print_scantronformat {
             }               } 
             $datatable .= '<td>'.$errorstr.'</td><td>&nbsp;';              $datatable .= '<td>'.$errorstr.'</td><td>&nbsp;';
         } elsif ($scantronurl) {          } elsif ($scantronurl) {
               my $link =  &Apache::loncommon::modal_link($scantronurl,&mt('Custom bubblesheet format file'),600,500,
                                                          undef,undef,undef,undef,'background-color:#ffffff');
             $datatable .= '<td><span class="LC_nobreak">'.              $datatable .= '<td><span class="LC_nobreak">'.
                           '<a href="'.$scantronurl.'" target="_blank">'.                            $link.
                           &mt('Custom bubblesheet format file').'</a><label>'.                            '<label><input type="checkbox" name="scantronformat_del"'.
                           '<input type="checkbox" name="scantronformat_del"'.                            ' value="1" />'.&mt('Delete?').'</label></span></td>'.
                           '" value="1" />'.&mt('Delete?').'</label></span></td>'.  
                           '<td><span class="LC_nobreak">&nbsp;'.                            '<td><span class="LC_nobreak">&nbsp;'.
                           &mt('Replace:').'</span><br />';                            &mt('Replace:').'</span><br />';
         }          }
Line 3054  sub print_coursecategories { Line 4841  sub print_coursecategories {
     my ($position,$dom,$hdritem,$settings,$rowtotal) = @_;      my ($position,$dom,$hdritem,$settings,$rowtotal) = @_;
     my $datatable;      my $datatable;
     if ($position eq 'top') {      if ($position eq 'top') {
           my (%checked);
           my @catitems = ('unauth','auth');
           my @cattypes = ('std','domonly','codesrch','none');
           $checked{'unauth'} = 'std';
           $checked{'auth'} = 'std';
           if (ref($settings) eq 'HASH') {
               foreach my $type (@cattypes) {
                   if ($type eq $settings->{'unauth'}) {
                       $checked{'unauth'} = $type;
                   }
                   if ($type eq $settings->{'auth'}) {
                       $checked{'auth'} = $type;
                   }
               }
           }
           my %lt = &Apache::lonlocal::texthash (
                                                  unauth   => 'Catalog type for unauthenticated users',
                                                  auth     => 'Catalog type for authenticated users',
                                                  none     => 'No catalog',
                                                  std      => 'Standard catalog',
                                                  domonly  => 'Domain-only catalog',
                                                  codesrch => "Code search form",
                                                );
          my $itemcount = 0;
          foreach my $item (@catitems) {
              my $css_class = $itemcount%2? ' class="LC_odd_row"':'';
              $datatable .= '<tr '.$css_class.'>'.
                            '<td>'.$lt{$item}.'</td>'.
                            '<td class="LC_right_item"><span class="LC_nobreak">';
              foreach my $type (@cattypes) {
                  my $ischecked;
                  if ($checked{$item} eq $type) {
                      $ischecked=' checked="checked"';
                  }
                  $datatable .= '<label>'.
                                '<input type="radio" name="coursecat_'.$item.'" value="'.$type.'"'.$ischecked.
                                ' />'.$lt{$type}.'</label>&nbsp;';
              }
              $datatable .= '</td></tr>';
              $itemcount ++;
           }
           $$rowtotal += $itemcount;
       } elsif ($position eq 'middle') {
         my $toggle_cats_crs = ' ';          my $toggle_cats_crs = ' ';
         my $toggle_cats_dom = ' checked="checked" ';          my $toggle_cats_dom = ' checked="checked" ';
         my $can_cat_crs = ' ';          my $can_cat_crs = ' ';
Line 3171  sub print_coursecategories { Line 5001  sub print_coursecategories {
                             }                              }
                             $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';                              $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                         }                          }
                         $datatable .= '</select></td><td>';                          $datatable .= '</select></span></td><td>';
                         if ($parent eq 'instcode' || $parent eq 'communities') {                          if ($parent eq 'instcode' || $parent eq 'communities') {
                             $datatable .=  '<span class="LC_nobreak">'                              $datatable .=  '<span class="LC_nobreak">'
                                            .$default_names{$parent}.'</span>';                                             .$default_names{$parent}.'</span>';
Line 3201  sub print_coursecategories { Line 5031  sub print_coursecategories {
                             $datatable .= '</td>';                              $datatable .= '</td>';
                         } else {                          } else {
                             $datatable .= $parent                              $datatable .= $parent
                                           .'&nbsp;<label><input type="checkbox" name="deletecategory" '                                            .'&nbsp;<span class="LC_nobreak"><label>'
                                             .'<input type="checkbox" name="deletecategory" '
                                           .'value="'.$item.'" />'.&mt('Delete').'</label></span></td>';                                            .'value="'.$item.'" />'.&mt('Delete').'</label></span></td>';
                         }                          }
                         my $depth = 1;                          my $depth = 1;
Line 3259  sub print_coursecategories { Line 5090  sub print_coursecategories {
                 $datatable .= &initialize_categories($itemcount);                  $datatable .= &initialize_categories($itemcount);
             }              }
         } else {          } else {
             $datatable .= '<td class="LC_right_item">'.$hdritem->{'header'}->[0]->{'col2'}.'</td>'              $datatable .= '<td class="LC_right_item">'.$hdritem->{'header'}->[1]->{'col2'}.'</td>'
                           .&initialize_categories($itemcount);                            .&initialize_categories($itemcount);
         }          }
         $$rowtotal += $itemcount;          $$rowtotal += $itemcount;
Line 3315  sub print_serverstatuses { Line 5146  sub print_serverstatuses {
   
 sub serverstatus_pages {  sub serverstatus_pages {
     return ('userstatus','lonstatus','loncron','server-status','codeversions',      return ('userstatus','lonstatus','loncron','server-status','codeversions',
             'clusterstatus','metadata_keywords','metadata_harvest',              'checksums','clusterstatus','metadata_keywords','metadata_harvest',
             'takeoffline','takeonline','showenv','toggledebug');              'takeoffline','takeonline','showenv','toggledebug','ping','domconf',
               'uniquecodes','diskusage');
   }
   
   sub defaults_javascript {
       my ($settings) = @_;
       return unless (ref($settings) eq 'HASH');
       if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {
           my $maxnum = scalar(@{$settings->{'inststatusorder'}});
           if ($maxnum eq '') {
               $maxnum = 0;
           }
           $maxnum ++;
           my $jstext = '    var inststatuses = Array('."'".join("','",@{$settings->{'inststatusorder'}})."'".');';  
           return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   function reorderTypes(form,caller) {
       var changedVal;
   $jstext 
       var newpos = 'addinststatus_pos';
       var current = new Array;
       var maxh = $maxnum;
       var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
       var oldVal;
       if (caller == newpos) {
           changedVal = newitemVal;
       } else {
           var curritem = 'inststatus_pos_'+caller;
           changedVal = form.elements[curritem].options[form.elements[curritem].selectedIndex].value;
           current[newitemVal] = newpos;
       }
       for (var i=0; i<inststatuses.length; i++) {
           if (inststatuses[i] != caller) {
               var elementName = 'inststatus_pos_'+inststatuses[i];
               if (form.elements[elementName]) {
                   var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
                   current[currVal] = elementName;
               }
           }
       }
       for (var j=0; j<maxh; j++) {
           if (current[j] == undefined) {
               oldVal = j;
           }
       }
       if (oldVal < changedVal) {
           for (var k=oldVal+1; k<=changedVal ; k++) {
              var elementName = current[k];
              form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
           }
       } else {
           for (var k=changedVal; k<oldVal; k++) {
               var elementName = current[k];
               form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   ENDSCRIPT
       }
 }  }
   
 sub coursecategories_javascript {  sub coursecategories_javascript {
Line 3341  sub coursecategories_javascript { Line 5236  sub coursecategories_javascript {
         $jstext  = '    var categories = Array(1);'."\n".          $jstext  = '    var categories = Array(1);'."\n".
                    '    categories[0] = Array("instcode_pos");'."\n";                      '    categories[0] = Array("instcode_pos");'."\n"; 
     }      }
     my $instcode_reserved = &mt('The name: "instcode" is a reserved category');      my $instcode_reserved = &mt('The name: [_1] is a reserved category.','"instcode"');
     my $communities_reserved = &mt('The name: "communities" is a reserved category');      my $communities_reserved = &mt('The name: [_1] is a reserved category.','"communities"');
     my $choose_again = '\\n'.&mt('Please use a different name for the new top level category');       my $choose_again = '\\n'.&mt('Please use a different name for the new top level category.'); 
     $output = <<"ENDSCRIPT";      $output = <<"ENDSCRIPT";
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
Line 3351  function reorderCats(form,parent,item,id Line 5246  function reorderCats(form,parent,item,id
     var changedVal;      var changedVal;
 $jstext  $jstext
     var newpos = 'addcategory_pos';      var newpos = 'addcategory_pos';
     var current = new Array;  
     if (parent == '') {      if (parent == '') {
         var has_instcode = 0;          var has_instcode = 0;
         var maxtop = categories[idx].length;          var maxtop = categories[idx].length;
Line 3473  sub build_category_rows { Line 5367  sub build_category_rows {
             if (ref($cats->[$depth]{$parent}) eq 'ARRAY') {              if (ref($cats->[$depth]{$parent}) eq 'ARRAY') {
                 my $numchildren = @{$cats->[$depth]{$parent}};                  my $numchildren = @{$cats->[$depth]{$parent}};
                 my $css_class = $itemcount%2?' class="LC_odd_row"':'';                  my $css_class = $itemcount%2?' class="LC_odd_row"':'';
                 $text .= '<td><table class="LC_datatable">';                  $text .= '<td><table class="LC_data_table">';
                 my ($idxnum,$parent_name,$parent_item);                  my ($idxnum,$parent_name,$parent_item);
                 my $higher = $depth - 1;                  my $higher = $depth - 1;
                 if ($higher == 0) {                  if ($higher == 0) {
Line 3547  sub build_category_rows { Line 5441  sub build_category_rows {
 }  }
   
 sub modifiable_userdata_row {  sub modifiable_userdata_row {
     my ($context,$role,$settings,$numinrow,$rowcount,$usertypes) = @_;      my ($context,$item,$settings,$numinrow,$rowcount,$usertypes,$fieldsref,$titlesref) = @_;
     my $rolename;      my ($role,$rolename,$statustype);
     if ($context eq 'selfcreate') {      $role = $item;
       if ($context eq 'cancreate') {
           if ($item =~ /^emailusername_(.+)$/) {
               $statustype = $1;
               $role = 'emailusername';
               if (ref($usertypes) eq 'HASH') {
                   if ($usertypes->{$statustype}) {
                       $rolename = &mt('Data provided by [_1]',$usertypes->{$statustype});
                   } else {
                       $rolename = &mt('Data provided by user');
                   }
               }
           }
       } elsif ($context eq 'selfcreate') {
         if (ref($usertypes) eq 'HASH') {          if (ref($usertypes) eq 'HASH') {
             $rolename = $usertypes->{$role};              $rolename = $usertypes->{$role};
         } else {          } else {
Line 3562  sub modifiable_userdata_row { Line 5469  sub modifiable_userdata_row {
             $rolename = &Apache::lonnet::plaintext($role);              $rolename = &Apache::lonnet::plaintext($role);
         }          }
     }      }
     my @fields = ('lastname','firstname','middlename','generation',      my (@fields,%fieldtitles);
                   'permanentemail','id');      if (ref($fieldsref) eq 'ARRAY') {
     my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();          @fields = @{$fieldsref};
       } else {
           @fields = ('lastname','firstname','middlename','generation',
                      'permanentemail','id');
       }
       if ((ref($titlesref) eq 'HASH')) {
           %fieldtitles = %{$titlesref};
       } else {
           %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
       }
     my $output;      my $output;
     my $css_class = $rowcount%2?' class="LC_odd_row"':'';      my $css_class = $rowcount%2?' class="LC_odd_row"':'';
     $output = '<tr '.$css_class.'>'.      $output = '<tr '.$css_class.'>'.
Line 3575  sub modifiable_userdata_row { Line 5491  sub modifiable_userdata_row {
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{$context}) eq 'HASH') {          if (ref($settings->{$context}) eq 'HASH') {
             if (ref($settings->{$context}->{$role}) eq 'HASH') {              if (ref($settings->{$context}->{$role}) eq 'HASH') {
                 foreach my $field (@fields) {                  my $hashref = $settings->{$context}->{$role};
                     if ($settings->{$context}->{$role}->{$field}) {                  if ($role eq 'emailusername') {
                         $checks{$field} = ' checked="checked" ';                      if ($statustype) {
                           if (ref($settings->{$context}->{$role}->{$statustype}) eq 'HASH') {
                               $hashref = $settings->{$context}->{$role}->{$statustype};
                               if (ref($hashref) eq 'HASH') { 
                                   foreach my $field (@fields) {
                                       if ($hashref->{$field}) {
                                           $checks{$field} = $hashref->{$field};
                                       }
                                   }
                               }
                           }
                       }
                   } else {
                       if (ref($hashref) eq 'HASH') {
                           foreach my $field (@fields) {
                               if ($hashref->{$field}) {
                                   $checks{$field} = ' checked="checked" ';
                               }
                           }
                     }                      }
                 }                  }
             }              }
         }          }
     }      }
        
     for (my $i=0; $i<@fields; $i++) {      for (my $i=0; $i<@fields; $i++) {
         my $rem = $i%($numinrow);          my $rem = $i%($numinrow);
         if ($rem == 0) {          if ($rem == 0) {
Line 3592  sub modifiable_userdata_row { Line 5527  sub modifiable_userdata_row {
             $output .= '<tr>';              $output .= '<tr>';
         }          }
         my $check = ' ';          my $check = ' ';
         if (exists($checks{$fields[$i]})) {          unless ($role eq 'emailusername') {
             $check = $checks{$fields[$i]}              if (exists($checks{$fields[$i]})) {
         } else {                  $check = $checks{$fields[$i]}
             if ($role eq 'st') {              } else {
                 if (ref($settings) ne 'HASH') {                  if ($role eq 'st') {
                     $check = ' checked="checked" ';                       if (ref($settings) ne 'HASH') {
                           $check = ' checked="checked" '; 
                       }
                 }                  }
             }              }
         }          }
         $output .= '<td class="LC_left_item">'.          $output .= '<td class="LC_left_item">'.
                    '<span class="LC_nobreak"><label>'.                     '<span class="LC_nobreak">';
                    '<input type="checkbox" name="canmodify_'.$role.'" '.          if ($role eq 'emailusername') {
                    'value="'.$fields[$i].'"'.$check.'/>'.$fieldtitles{$fields[$i]}.              unless ($checks{$fields[$i]} =~ /^(required|optional)$/) {
                    '</label></span></td>';                  $checks{$fields[$i]} = 'omit';
               }
               foreach my $option ('required','optional','omit') {
                   my $checked='';
                   if ($checks{$fields[$i]} eq $option) {
                       $checked='checked="checked" ';
                   }
                   $output .= '<label>'.
                              '<input type="radio" name="canmodify_'.$item.'_'.$fields[$i].'" value="'.$option.'" '.$checked.'/>'.
                              &mt($option).'</label>'.('&nbsp;' x2);
               }
               $output .= '<i>'.$fieldtitles{$fields[$i]}.'</i>';
           } else {
               $output .= '<label>'.
                          '<input type="checkbox" name="canmodify_'.$role.'" '.
                          'value="'.$fields[$i].'"'.$check.'/>'.$fieldtitles{$fields[$i]}.
                          '</label>';
           }
           $output .= '</span></td>';
         $rem = @fields%($numinrow);          $rem = @fields%($numinrow);
     }      }
     my $colsleft = $numinrow - $rem;      my $colsleft = $numinrow - $rem;
Line 3620  sub modifiable_userdata_row { Line 5575  sub modifiable_userdata_row {
 }  }
   
 sub insttypes_row {  sub insttypes_row {
     my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context) = @_;      my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context,$rownum) = @_;
     my %lt = &Apache::lonlocal::texthash (      my %lt = &Apache::lonlocal::texthash (
                       cansearch => 'Users allowed to search',                        cansearch => 'Users allowed to search',
                       statustocreate => 'Institutional affiliation(s) able to create own account (login/SSO)',                        statustocreate => 'Institutional affiliation(s) able to create own account (login/SSO)',
Line 3630  sub insttypes_row { Line 5585  sub insttypes_row {
     if ($context eq 'cansearch') {      if ($context eq 'cansearch') {
         $showdom = ' ('.$dom.')';          $showdom = ' ('.$dom.')';
     }      }
     my $output =  '<tr class="LC_odd_row">'.      my $class = 'LC_left_item';
                   '<td>'.$lt{$context}.$showdom.      if ($context eq 'statustocreate') {
                   '</td><td class="LC_left_item" colspan="2"><table>';          $class = 'LC_right_item';
       }
       my $css_class = ' class="LC_odd_row"';
       if ($rownum ne '') { 
           $css_class = ($rownum%2? ' class="LC_odd_row"':'');
       }
       my $output = '<tr'.$css_class.'>'.
                    '<td>'.$lt{$context}.$showdom.
                    '</td><td class="'.$class.'" colspan="2"><table>';
     my $rem;      my $rem;
     if (ref($types) eq 'ARRAY') {      if (ref($types) eq 'ARRAY') {
         for (my $i=0; $i<@{$types}; $i++) {          for (my $i=0; $i<@{$types}; $i++) {
Line 3761  sub usertype_update_row { Line 5724  sub usertype_update_row {
 }  }
   
 sub modify_login {  sub modify_login {
     my ($r,$dom,$confname,%domconfig) = @_;      my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
     my ($resulttext,$errors,$colchgtext,%changes,%colchanges);      my ($resulttext,$errors,$colchgtext,%changes,%colchanges,%newfile,%newurl,
     my %title = ( coursecatalog => 'Display course catalog',          %curr_loginvia,%loginhash,@currlangs,@newlangs,$addedfile,%title,@offon);
                   adminmail => 'Display administrator E-mail address',      %title = ( coursecatalog => 'Display course catalog',
                   newuser => 'Link for visitors to create a user account',                 adminmail => 'Display administrator E-mail address',
                   loginheader => 'Log-in box header');                 helpdesk  => 'Display "Contact Helpdesk" link',
     my @offon = ('off','on');                 newuser => 'Link for visitors to create a user account',
     my %curr_loginvia;                 loginheader => 'Log-in box header');
       @offon = ('off','on');
     if (ref($domconfig{login}) eq 'HASH') {      if (ref($domconfig{login}) eq 'HASH') {
         if (ref($domconfig{login}{loginvia}) eq 'HASH') {          if (ref($domconfig{login}{loginvia}) eq 'HASH') {
             foreach my $lonhost (keys(%{$domconfig{login}{loginvia}})) {              foreach my $lonhost (keys(%{$domconfig{login}{loginvia}})) {
Line 3776  sub modify_login { Line 5740  sub modify_login {
             }              }
         }          }
     }      }
     my %loginhash;  
     ($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'],      ($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'],
                                            \%domconfig,\%loginhash);                                             \%domconfig,\%loginhash);
     my @toggles = ('coursecatalog','adminmail','newuser');      my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');
     foreach my $item (@toggles) {      foreach my $item (@toggles) {
         $loginhash{login}{$item} = $env{'form.'.$item};          $loginhash{login}{$item} = $env{'form.'.$item};
     }      }
Line 3789  sub modify_login { Line 5752  sub modify_login {
                                          \%loginhash);                                           \%loginhash);
     }      }
   
     my %servers = &dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
     my @loginvia_attribs = ('serverpath','custompath','exempt');      my @loginvia_attribs = ('serverpath','custompath','exempt');
     if (keys(%servers) > 1) {      if (keys(%servers) > 1) {
         foreach my $lonhost (keys(%servers)) {          foreach my $lonhost (keys(%servers)) {
Line 3849  sub modify_login { Line 5812  sub modify_login {
                                 $new = '';                                   $new = ''; 
                             }                              }
                         }                          }
   
                         $loginhash{login}{loginvia}{$lonhost}{$item} = $new;                          $loginhash{login}{loginvia}{$lonhost}{$item} = $new;
                     }                      }
                 }                  }
Line 3875  sub modify_login { Line 5837  sub modify_login {
         }          }
     }      }
   
       my $servadm = $r->dir_config('lonAdmEMail');
       my %langchoices = &Apache::lonlocal::texthash(&get_languages_hash());
       if (ref($domconfig{'login'}) eq 'HASH') {
           if (ref($domconfig{'login'}{'helpurl'}) eq 'HASH') {
               foreach my $lang (sort(keys(%{$domconfig{'login'}{'helpurl'}}))) {
                   if ($lang eq 'nolang') {
                       push(@currlangs,$lang);
                   } elsif (defined($langchoices{$lang})) {
                       push(@currlangs,$lang);
                   } else {
                       next;
                   }
               }
           }
       }
       my @delurls = &Apache::loncommon::get_env_multiple('form.loginhelpurl_del');
       if (@currlangs > 0) {
           foreach my $lang (@currlangs) {
               if (grep(/^\Q$lang\E$/,@delurls)) {
                   $changes{'helpurl'}{$lang} = 1;
               } elsif ($env{'form.loginhelpurl_'.$lang.'.filename'}) {
                   $changes{'helpurl'}{$lang} = 1;
                   $newfile{$lang} = $env{'form.loginhelpurl_'.$lang.'.filename'};
                   push(@newlangs,$lang);
               } else {
                   $loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang};
               }
           }
       }
       unless (grep(/^nolang$/,@currlangs)) {
           if ($env{'form.loginhelpurl_nolang.filename'}) {
               $changes{'helpurl'}{'nolang'} = 1;
               $newfile{'nolang'} = $env{'form.loginhelpurl_nolang.filename'};
               push(@newlangs,'nolang');
           }
       }
       if ($env{'form.loginhelpurl_add_lang'}) {
           if ((defined($langchoices{$env{'form.loginhelpurl_add_lang'}})) &&
               ($env{'form.loginhelpurl_add_file.filename'})) {
               $newfile{$env{'form.loginhelpurl_add_lang'}} = $env{'form.loginhelpurl_add_file.filename'};
               $addedfile = $env{'form.loginhelpurl_add_lang'};
           }
       }
       if ((@newlangs > 0) || ($addedfile)) {
           my $error;
           my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
           if ($configuserok eq 'ok') {
               if ($switchserver) {
                   $error = &mt("Upload of custom help file is not permitted to this server: [_1]",$switchserver);
               } elsif ($author_ok eq 'ok') {
                   my @allnew = @newlangs;
                   if ($addedfile ne '') {
                       push(@allnew,$addedfile);
                   }
                   foreach my $lang (@allnew) {
                       my $formelem = 'loginhelpurl_'.$lang;
                       if ($lang eq $env{'form.loginhelpurl_add_lang'}) {
                           $formelem = 'loginhelpurl_add_file';
                       }
                       (my $result,$newurl{$lang}) = &publishlogo($r,'upload',$formelem,$dom,$confname,
                                                                  "help/$lang",'','',$newfile{$lang});
                       if ($result eq 'ok') {
                           $loginhash{'login'}{'helpurl'}{$lang} = $newurl{$lang};
                           $changes{'helpurl'}{$lang} = 1;
                       } else {
                           my $puberror = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$newfile{$lang},$result);
                           $errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';
                           if ((grep(/^\Q$lang\E$/,@currlangs)) &&
                               (!grep(/^\Q$lang\E$/,@delurls))) {
   
                               $loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang};
                           }
                       }
                   }
               } else {
                   $error = &mt("Upload of custom log-in help file(s) failed because an author role could not be assigned to a Domain Configuration user ([_1]) in domain: [_2].  Error was: [_3].",$confname,$dom,$author_ok);
               }
           } else {
               $error = &mt("Upload of custom log-in help file(s) failed because a Domain Configuration user ([_1]) could not be created in domain: [_2].  Error was: [_3].",$confname,$dom,$configuserok);
           }
           if ($error) {
               &Apache::lonnet::logthis($error);
               $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
           }
       }
       &process_captcha('login',\%changes,$loginhash{'login'},$domconfig{'login'});
   
       my $defaulthelpfile = '/adm/loginproblems.html';
       my $defaulttext = &mt('Default in use');
   
     my $putresult = &Apache::lonnet::put_dom('configuration',\%loginhash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%loginhash,
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         my @toggles = ('coursecatalog','adminmail','newuser');          my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');
         my %defaultchecked = (          my %defaultchecked = (
                     'coursecatalog' => 'on',                      'coursecatalog' => 'on',
                       'helpdesk'      => 'on',
                     'adminmail'     => 'off',                      'adminmail'     => 'off',
                     'newuser'       => 'off',                      'newuser'       => 'off',
         );          );
Line 3909  sub modify_login { Line 5962  sub modify_login {
         }          }
         if (keys(%changes) > 0 || $colchgtext) {          if (keys(%changes) > 0 || $colchgtext) {
             &Apache::loncommon::devalidate_domconfig_cache($dom);              &Apache::loncommon::devalidate_domconfig_cache($dom);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domainconfig'} = 1;
               }
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
                 if ($item eq 'loginvia') {                  if ($item eq 'loginvia') {
Line 3940  sub modify_login { Line 5996  sub modify_login {
                         }                          }
                         $resulttext .= '</ul></li>';                          $resulttext .= '</ul></li>';
                     }                      }
                   } elsif ($item eq 'helpurl') {
                       if (ref($changes{$item}) eq 'HASH') {
                           foreach my $lang (sort(keys(%{$changes{$item}}))) {
                               if (grep(/^\Q$lang\E$/,@delurls)) {
                                   my ($chg,$link);
                                   $link = &Apache::loncommon::modal_link($defaulthelpfile,$defaulttext,600,500);
                                   if ($lang eq 'nolang') {
                                       $chg = &mt('custom log-in help file removed for no preferred language; [_1]',$link);
                                   } else {
                                       $chg = &mt('custom log-in help file removed for specific language: [_1]; [_2]',$langchoices{$lang},$link);
                                   }
                                   $resulttext .= '<li>'.$chg.'</li>';
                               } else {
                                   my $chg;
                                   if ($lang eq 'nolang') {
                                       $chg = &mt('custom log-in help file for no preferred language');
                                   } else {
                                       $chg = &mt('custom log-in help file for specific language: [_1]',$langchoices{$lang});
                                   }
                                   $resulttext .= '<li>'.&Apache::loncommon::modal_link(
                                                         $loginhash{'login'}{'helpurl'}{$lang}.
                                                         '?inhibitmenu=yes',$chg,600,500).
                                                  '</li>';
                               }
                           }
                       }
                   } elsif ($item eq 'captcha') {
                       if (ref($loginhash{'login'}) eq 'HASH') {
                           my $chgtxt;
                           if ($loginhash{'login'}{$item} eq 'notused') {
                               $chgtxt .= &mt('No CAPTCHA validation in use for helpdesk form.');
                           } else {
                               my %captchas = &captcha_phrases();
                               if ($captchas{$loginhash{'login'}{$item}}) {
                                   $chgtxt .= &mt("Validation for helpdesk form set to $captchas{$loginhash{'login'}{$item}}.");
                               } else {
                                   $chgtxt .= &mt('Validation for helpdesk form set to unknown type.');
                               }
                           }
                           $resulttext .= '<li>'.$chgtxt.'</li>';
                       }
                   } elsif ($item eq 'recaptchakeys') {
                       if (ref($loginhash{'login'}) eq 'HASH') {
                           my ($privkey,$pubkey);
                           if (ref($loginhash{'login'}{$item}) eq 'HASH') {
                               $pubkey = $loginhash{'login'}{$item}{'public'};
                               $privkey = $loginhash{'login'}{$item}{'private'};
                           }
                           my $chgtxt .= &mt('ReCAPTCHA keys changes').'<ul>';
                           if (!$pubkey) {
                               $chgtxt .= '<li>'.&mt('Public key deleted').'</li>';
                           } else {
                               $chgtxt .= '<li>'.&mt('Public key set to [_1]',$pubkey).'</li>';
                           }
                           if (!$privkey) {
                               $chgtxt .= '<li>'.&mt('Private key deleted').'</li>';
                           } else {
                               $chgtxt .= '<li>'.&mt('Private key set to [_1]',$privkey).'</li>';
                           }
                           $chgtxt .= '</ul>';
                           $resulttext .= '<li>'.$chgtxt.'</li>';
                       }
                 } else {                  } else {
                     $resulttext .= '<li>'.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'</li>';                      $resulttext .= '<li>'.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'</li>';
                 }                  }
Line 3967  sub color_font_choices { Line 6085  sub color_font_choices {
             links => "Link colors",              links => "Link colors",
             images => "Images",              images => "Images",
             font => "Font color",              font => "Font color",
             fontmenu => "Font Menu",              fontmenu => "Font menu",
             pgbg => "Page",              pgbg => "Page",
             tabbg => "Header",              tabbg => "Header",
             sidebg => "Border",              sidebg => "Border",
Line 3979  sub color_font_choices { Line 6097  sub color_font_choices {
 }  }
   
 sub modify_rolecolors {  sub modify_rolecolors {
     my ($r,$dom,$confname,$roles,%domconfig) = @_;      my ($r,$dom,$confname,$roles,$lastactref,%domconfig) = @_;
     my ($resulttext,%rolehash);      my ($resulttext,%rolehash);
     $rolehash{'rolecolors'} = {};      $rolehash{'rolecolors'} = {};
     if (ref($domconfig{'rolecolors'}) ne 'HASH') {      if (ref($domconfig{'rolecolors'}) ne 'HASH') {
Line 3994  sub modify_rolecolors { Line 6112  sub modify_rolecolors {
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             &Apache::loncommon::devalidate_domconfig_cache($dom);              &Apache::loncommon::devalidate_domconfig_cache($dom);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domainconfig'} = 1;
               }
             $resulttext = &display_colorchgs($dom,\%changes,$roles,              $resulttext = &display_colorchgs($dom,\%changes,$roles,
                                              $rolehash{'rolecolors'});                                               $rolehash{'rolecolors'});
         } else {          } else {
Line 4019  sub modify_colors { Line 6140  sub modify_colors {
     my @images;      my @images;
     my $servadm = $r->dir_config('lonAdmEMail');      my $servadm = $r->dir_config('lonAdmEMail');
     my $errors;      my $errors;
       my %defaults;
     foreach my $role (@{$roles}) {      foreach my $role (@{$roles}) {
         if ($role eq 'login') {          if ($role eq 'login') {
             %choices = &login_choices();              %choices = &login_choices();
             @logintext = ('textcol','bgcol');              @logintext = ('textcol','bgcol');
         } else {          } else {
             %choices = &color_font_choices();              %choices = &color_font_choices();
             $confhash->{$role}{'fontmenu'} = $env{'form.'.$role.'_fontmenu'};  
         }          }
         if ($role eq 'login') {          if ($role eq 'login') {
             @images = ('img','logo','domlogo','login');              @images = ('img','logo','domlogo','login');
             @bgs = ('pgbg','mainbg','sidebg');              @bgs = ('pgbg','mainbg','sidebg');
         } else {          } else {
             @images = ('img');              @images = ('img');
             @bgs = ('pgbg','tabbg','sidebg');               @bgs = ('pgbg','tabbg','sidebg');
           }
           my %defaults = &role_defaults($role,\@bgs,\@links,\@images,\@logintext);
           unless ($env{'form.'.$role.'_font'} eq $defaults{'font'}) {
               $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'};
           }
           if ($role eq 'login') {
               foreach my $item (@logintext) {
                   $env{'form.'.$role.'_'.$item} = lc($env{'form.'.$role.'_'.$item});
                   if ($env{'form.'.$role.'_'.$item} =~ /^\w+/) {
                       $env{'form.'.$role.'_'.$item} = '#'.$env{'form.'.$role.'_'.$item};
                   }
                   unless ($env{'form.'.$role.'_'.$item} eq lc($defaults{'logintext'}{$item})) {
                       $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
                   }
               }
           } else {
               $env{'form.'.$role.'_fontmenu'} = lc($env{'form.'.$role.'_fontmenu'});
               if ($env{'form.'.$role.'_fontmenu'} =~ /^\w+/) {
                   $env{'form.'.$role.'_fontmenu'} = '#'.$env{'form.'.$role.'_fontmenu'};
               }
               unless($env{'form.'.$role.'_fontmenu'} eq lc($defaults{'fontmenu'})) {
                   $confhash->{$role}{'fontmenu'} = $env{'form.'.$role.'_fontmenu'};
               }
         }          }
         $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'};          foreach my $item (@bgs) {
         foreach my $item (@bgs,@links,@logintext) {              $env{'form.'.$role.'_'.$item} = lc($env{'form.'.$role.'_'.$item});
             $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};              if ($env{'form.'.$role.'_'.$item} =~ /^\w+/) {
                   $env{'form.'.$role.'_'.$item} = '#'.$env{'form.'.$role.'_'.$item};
               }
               unless ($env{'form.'.$role.'_'.$item} eq lc($defaults{'bgs'}{$item})) {
                   $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
               }
           }
           foreach my $item (@links) {
               $env{'form.'.$role.'_'.$item} = lc($env{'form.'.$role.'_'.$item});
               if ($env{'form.'.$role.'_'.$item} =~ /^\w+/) {
                   $env{'form.'.$role.'_'.$item} = '#'.$env{'form.'.$role.'_'.$item};
               }
               unless ($env{'form.'.$role.'_'.$item} eq lc($defaults{'links'}{$item})) {
                   $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
               }
         }          }
         my ($configuserok,$author_ok,$switchserver) =           my ($configuserok,$author_ok,$switchserver) = 
             &config_check($dom,$confname,$servadm);              &config_check($dom,$confname,$servadm);
Line 4384  sub publishlogo { Line 6542  sub publishlogo {
 # See if there is anything left  # See if there is anything left
     unless ($fname) { return ('error: no uploaded file'); }      unless ($fname) { return ('error: no uploaded file'); }
     $fname="$subdir/$fname";      $fname="$subdir/$fname";
     my $filepath='/home/'.$confname.'/public_html';      my $docroot=$r->dir_config('lonDocRoot');
       my $filepath="$docroot/priv";
       my $relpath = "$dom/$confname";
     my ($fnamepath,$file,$fetchthumb);      my ($fnamepath,$file,$fetchthumb);
     $file=$fname;      $file=$fname;
     if ($fname=~m|/|) {      if ($fname=~m|/|) {
         ($fnamepath,$file) = ($fname =~ m|^(.*)/([^/]+)$|);          ($fnamepath,$file) = ($fname =~ m|^(.*)/([^/]+)$|);
     }      }
     my @parts=split(/\//,$filepath.'/'.$fnamepath);      my @parts=split(/\//,"$filepath/$relpath/$fnamepath");
     my $count;      my $count;
     for ($count=4;$count<=$#parts;$count++) {      for ($count=5;$count<=$#parts;$count++) {
         $filepath.="/$parts[$count]";          $filepath.="/$parts[$count]";
         if ((-e $filepath)!=1) {          if ((-e $filepath)!=1) {
             mkdir($filepath,02770);              mkdir($filepath,02770);
Line 4402  sub publishlogo { Line 6562  sub publishlogo {
     if ($file=~/\.(\w+)$/ &&      if ($file=~/\.(\w+)$/ &&
         (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {          (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {
         $output =           $output = 
             &mt('Invalid file extension ([_1]) - reserved for LONCAPA use.',$1);               &mt('Invalid file extension ([_1]) - reserved for internal use.',$1); 
     } elsif ($file=~/\.(\w+)$/ &&      } elsif ($file=~/\.(\w+)$/ &&
         !defined(&Apache::loncommon::fileembstyle($1))) {          !defined(&Apache::loncommon::fileembstyle($1))) {
         $output = &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1);          $output = &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1);
     } elsif ($file=~/\.(\d+)\.(\w+)$/) {      } elsif ($file=~/\.(\d+)\.(\w+)$/) {
         $output = &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2);          $output = &mt('Filename not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2);
     } elsif (-d "$filepath/$file") {      } elsif (-d "$filepath/$file") {
         $output = &mt('File name is a directory name - rename the file and re-upload');          $output = &mt('Filename is a directory name - rename the file and re-upload');
     } else {      } else {
         my $source = $filepath.'/'.$file;          my $source = $filepath.'/'.$file;
         my $logfile;          my $logfile;
         if (!open($logfile,">>$source".'.log')) {          if (!open($logfile,">>$source".'.log')) {
             return (&mt('No write permission to Construction Space'));              return (&mt('No write permission to Authoring Space'));
         }          }
         print $logfile          print $logfile
 "\n================= Publish ".localtime()." ================\n".  "\n================= Publish ".localtime()." ================\n".
Line 4439  $env{'user.name'}.':'.$env{'user.domain' Line 6599  $env{'user.name'}.':'.$env{'user.domain'
         close(FH);          close(FH);
         chmod(0660, $source); # Permissions to rw-rw---.          chmod(0660, $source); # Permissions to rw-rw---.
   
         my $docroot=$r->dir_config('lonDocRoot');  
         my $targetdir=$docroot.'/res/'.$dom.'/'.$confname .'/'.$fnamepath;          my $targetdir=$docroot.'/res/'.$dom.'/'.$confname .'/'.$fnamepath;
         my $copyfile=$targetdir.'/'.$file;          my $copyfile=$targetdir.'/'.$file;
   
Line 4462  $env{'user.name'}.':'.$env{'user.domain' Line 6621  $env{'user.name'}.':'.$env{'user.domain'
             if (copy($source,$copyfile)) {              if (copy($source,$copyfile)) {
                 print $logfile "\nCopied original source to ".$copyfile."\n";                  print $logfile "\nCopied original source to ".$copyfile."\n";
                 $output = 'ok';                  $output = 'ok';
                 &write_metadata($dom,$confname,$formname,$targetdir,$file,$logfile);  
                 $logourl = '/res/'.$dom.'/'.$confname.'/'.$fname;                  $logourl = '/res/'.$dom.'/'.$confname.'/'.$fname;
                   push(@{$modified_urls},[$copyfile,$source]);
                   my $metaoutput = 
                       &write_metadata($dom,$confname,$formname,$targetdir,$file,$logfile);
                   unless ($registered_cleanup) {
                       my $handlers = $r->get_handlers('PerlCleanupHandler');
                       $r->set_handlers('PerlCleanupHandler' => [\&notifysubscribed,@{$handlers}]);
                       $registered_cleanup=1;
                   }
             } else {              } else {
                 print $logfile "\nUnable to write ".$copyfile.':'.$!."\n";                  print $logfile "\nUnable to write ".$copyfile.':'.$!."\n";
                 $output = &mt('Failed to copy file to RES space').", $!";                  $output = &mt('Failed to copy file to RES space').", $!";
Line 4481  $env{'user.name'}.':'.$env{'user.domain' Line 6647  $env{'user.name'}.':'.$env{'user.domain'
                             my $copyfile=$targetdir.'/tn-'.$file;                              my $copyfile=$targetdir.'/tn-'.$file;
                             if (copy($outfile,$copyfile)) {                              if (copy($outfile,$copyfile)) {
                                 print $logfile "\nCopied source to ".$copyfile."\n";                                  print $logfile "\nCopied source to ".$copyfile."\n";
                                 &write_metadata($dom,$confname,$formname,                                  my $thumb_metaoutput = 
                                                 $targetdir,'tn-'.$file,$logfile);                                      &write_metadata($dom,$confname,$formname,
                                                       $targetdir,'tn-'.$file,$logfile);
                                   push(@{$modified_urls},[$copyfile,$outfile]);
                                   unless ($registered_cleanup) {
                                       my $handlers = $r->get_handlers('PerlCleanupHandler');
                                       $r->set_handlers('PerlCleanupHandler' => [\&notifysubscribed,@{$handlers}]);
                                       $registered_cleanup=1;
                                   }
                             } else {                              } else {
                                 print $logfile "\nUnable to write ".$copyfile.                                  print $logfile "\nUnable to write ".$copyfile.
                                                ':'.$!."\n";                                                 ':'.$!."\n";
Line 4547  sub write_metadata { Line 6720  sub write_metadata {
     {      {
         print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file;          print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file;
         my $mfh;          my $mfh;
         unless (open($mfh,'>'.$targetdir.'/'.$file.'.meta')) {          if (open($mfh,'>'.$targetdir.'/'.$file.'.meta')) {
               foreach (sort(keys(%metadatafields))) {
                   unless ($_=~/\./) {
                       my $unikey=$_;
                       $unikey=~/^([A-Za-z]+)/;
                       my $tag=$1;
                       $tag=~tr/A-Z/a-z/;
                       print $mfh "\n\<$tag";
                       foreach (split(/\,/,$metadatakeys{$unikey})) {
                           my $value=$metadatafields{$unikey.'.'.$_};
                           $value=~s/\"/\'\'/g;
                           print $mfh ' '.$_.'="'.$value.'"';
                       }
                       print $mfh '>'.
                           &HTML::Entities::encode($metadatafields{$unikey},'<>&"')
                               .'</'.$tag.'>';
                   }
               }
               $output = 'ok';
               print $logfile "\nWrote metadata";
               close($mfh);
           } else {
               print $logfile "\nFailed to open metadata file";
             $output = &mt('Could not write metadata');              $output = &mt('Could not write metadata');
         }          }
         foreach (sort keys %metadatafields) {  
             unless ($_=~/\./) {  
                 my $unikey=$_;  
                 $unikey=~/^([A-Za-z]+)/;  
                 my $tag=$1;  
                 $tag=~tr/A-Z/a-z/;  
                 print $mfh "\n\<$tag";  
                 foreach (split(/\,/,$metadatakeys{$unikey})) {  
                     my $value=$metadatafields{$unikey.'.'.$_};  
                     $value=~s/\"/\'\'/g;  
                     print $mfh ' '.$_.'="'.$value.'"';  
                 }  
                 print $mfh '>'.  
                     &HTML::Entities::encode($metadatafields{$unikey},'<>&"')  
                         .'</'.$tag.'>';  
             }  
         }  
         $output = 'ok';  
         print $logfile "\nWrote metadata";  
         close($mfh);  
     }      }
       return $output;
   }
   
   sub notifysubscribed {
       foreach my $targetsource (@{$modified_urls}){
           next unless (ref($targetsource) eq 'ARRAY');
           my ($target,$source)=@{$targetsource};
           if ($source ne '') {
               if (open(my $logfh,'>>'.$source.'.log')) {
                   print $logfh "\nCleanup phase: Notifications\n";
                   my @subscribed=&subscribed_hosts($target);
                   foreach my $subhost (@subscribed) {
                       print $logfh "\nNotifying host ".$subhost.':';
                       my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);
                       print $logfh $reply;
                   }
                   my @subscribedmeta=&subscribed_hosts("$target.meta");
                   foreach my $subhost (@subscribedmeta) {
                       print $logfh "\nNotifying host for metadata only ".$subhost.':';
                       my $reply=&Apache::lonnet::critical('update:'.$target.'.meta',
                                                           $subhost);
                       print $logfh $reply;
                   }
                   print $logfh "\n============ Done ============\n";
                   close($logfh);
               }
           }
       }
       return OK;
   }
   
   sub subscribed_hosts {
       my ($target) = @_;
       my @subscribed;
       if (open(my $fh,"<$target.subscription")) {
           while (my $subline=<$fh>) {
               if ($subline =~ /^($match_lonid):/) {
                   my $host = $1;
                   if ($host ne $Apache::lonnet::perlvar{'lonHostID'}) {
                       unless (grep(/^\Q$host\E$/,@subscribed)) {
                           push(@subscribed,$host);
                       }
                   }
               }
           }
       }
       return @subscribed;
 }  }
   
 sub check_switchserver {  sub check_switchserver {
Line 4583  sub check_switchserver { Line 6805  sub check_switchserver {
     my @ids=&Apache::lonnet::current_machine_ids();      my @ids=&Apache::lonnet::current_machine_ids();
     foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }      foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
     if (!$allowed) {      if (!$allowed) {
  $switchserver='<a href="/adm/switchserver?otherserver='.$home.'&role=dc./'.$dom.'/">'.&mt('Switch Server').'</a>';   $switchserver='<a href="/adm/switchserver?otherserver='.$home.'&amp;role=dc./'.$dom.'/&amp;destinationurl=/adm/domainprefs">'.&mt('Switch Server').'</a>';
     }      }
     return $switchserver;      return $switchserver;
 }  }
   
 sub modify_quotas {  sub modify_quotas {
     my ($dom,$action,%domconfig) = @_;      my ($r,$dom,$action,$lastactref,%domconfig) = @_;
     my ($context,@usertools,@options,%validations,%titles,%confhash,%toolshash,      my ($context,@usertools,@options,%validations,%titles,%confhash,%toolshash,
         %limithash,$toolregexp,%conditions,$resulttext,%changes);          %limithash,$toolregexp,%conditions,$resulttext,%changes,$confname,$configuserok,
           $author_ok,$switchserver,$errors,$validationitemsref,$validationnamesref,
           $validationfieldsref);
     if ($action eq 'quotas') {      if ($action eq 'quotas') {
         $context = 'tools';           $context = 'tools'; 
     } else {       } else {
         $context = $action;          $context = $action;
     }      }
     if ($context eq 'requestcourses') {      if ($context eq 'requestcourses') {
         @usertools = ('official','unofficial','community');          @usertools = ('official','unofficial','community','textbook');
         @options =('norequest','approval','validate','autolimit');          @options =('norequest','approval','validate','autolimit');
         %validations = &Apache::lonnet::auto_courserequest_checks($dom);          %validations = &Apache::lonnet::auto_courserequest_checks($dom);
         %titles = &courserequest_titles();          %titles = &courserequest_titles();
         $toolregexp = join('|',@usertools);          $toolregexp = join('|',@usertools);
         %conditions = &courserequest_conditions();          %conditions = &courserequest_conditions();
           $confname = $dom.'-domainconfig';
           my $servadm = $r->dir_config('lonAdmEMail');
           ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
           ($validationitemsref,$validationnamesref,$validationfieldsref) = 
               &Apache::loncoursequeueadmin::requestcourses_validation_types();
       } elsif ($context eq 'requestauthor') {
           @usertools = ('author');
           %titles = &authorrequest_titles();
     } else {      } else {
         @usertools = ('aboutme','blog','portfolio');          @usertools = ('aboutme','blog','webdav','portfolio');
         %titles = &tool_titles();          %titles = &tool_titles();
     }      }
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);      my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
     foreach my $key (keys(%env)) {      foreach my $key (keys(%env)) {
         if ($context eq 'requestcourses') {          if ($context eq 'requestcourses') {
Line 4621  sub modify_quotas { Line 6853  sub modify_quotas {
                     $confhash{$item}{$type} = $env{$key};                      $confhash{$item}{$type} = $env{$key};
                 }                  }
             }              }
           } elsif ($context eq 'requestauthor') {
               if ($key =~ /^\Qform.authorreq_\E(.+)$/) {
                   $confhash{$1} = $env{$key};
               }
         } else {          } else {
             if ($key =~ /^form\.quota_(.+)$/) {              if ($key =~ /^form\.quota_(.+)$/) {
                 $confhash{'defaultquota'}{$1} = $env{$key};                  $confhash{'defaultquota'}{$1} = $env{$key};
             }              } elsif ($key =~ /^form\.authorquota_(.+)$/) {
             if ($key =~ /^form\.\Q$context\E_(.+)$/) {                  $confhash{'authorquota'}{$1} = $env{$key};
               } elsif ($key =~ /^form\.\Q$context\E_(.+)$/) {
                 @{$toolshash{$1}} = &Apache::loncommon::get_env_multiple($key);                  @{$toolshash{$1}} = &Apache::loncommon::get_env_multiple($key);
             }              }
         }          }
     }      }
     if ($context eq 'requestcourses') {      if (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
         my @approvalnotify = &Apache::loncommon::get_env_multiple('form.reqapprovalnotify');          my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval');
         @approvalnotify = sort(@approvalnotify);          @approvalnotify = sort(@approvalnotify);
         $confhash{'notify'}{'approval'} = join(',',@approvalnotify);          $confhash{'notify'}{'approval'} = join(',',@approvalnotify);
           my @crstypes = ('official','unofficial','community','textbook');
           my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');
           foreach my $type (@hasuniquecode) {
               if (grep(/^\Q$type\E$/,@crstypes)) {
                   $confhash{'uniquecode'}{$type} = 1;
               }
           }
           my (%newbook,%allpos);
           if ($context eq 'requestcourses') {
               foreach my $type ('textbooks','templates') {
                   @{$allpos{$type}} = (); 
                   my $invalid;
                   if ($type eq 'textbooks') {
                       $invalid = &mt('Invalid LON-CAPA course for textbook');
                   } else {
                       $invalid = &mt('Invalid LON-CAPA course for template');
                   }
                   if ($env{'form.'.$type.'_addbook'}) {
                       if (($env{'form.'.$type.'_addbook_cnum'} =~ /^$match_courseid$/) &&
                           ($env{'form.'.$type.'_addbook_cdom'} =~ /^$match_domain$/)) {
                           if (&Apache::lonnet::homeserver($env{'form.'.$type.'_addbook_cnum'},
                                                           $env{'form.'.$type.'_addbook_cdom'}) eq 'no_host') {
                               $errors .= '<li><span class="LC_error">'.$invalid.'</span></li>';
                           } else {
                               $newbook{$type} = $env{'form.'.$type.'_addbook_cdom'}.'_'.$env{'form.'.$type.'_addbook_cnum'};
                               my $position = $env{'form.'.$type.'_addbook_pos'};
                               $position =~ s/\D+//g;
                               if ($position ne '') {
                                   $allpos{$type}[$position] = $newbook{$type};
                               }
                           }
                       } else {
                           $errors .= '<li><span class="LC_error">'.$invalid.'</span></li>';
                       }
                   }
               } 
           }
         if (ref($domconfig{$action}) eq 'HASH') {          if (ref($domconfig{$action}) eq 'HASH') {
             if (ref($domconfig{$action}{'notify'}) eq 'HASH') {              if (ref($domconfig{$action}{'notify'}) eq 'HASH') {
                 if ($domconfig{$action}{'notify'}{'approval'} ne $confhash{'notify'}{'approval'}) {                  if ($domconfig{$action}{'notify'}{'approval'} ne $confhash{'notify'}{'approval'}) {
                     $changes{'notify'}{'approval'} = 1;                      $changes{'notify'}{'approval'} = 1;
                 }                  }
             } else {              } else {
                 if ($domconfig{$action}{'notify'}{'approval'}) {                  if ($confhash{'notify'}{'approval'}) {
                     $changes{'notify'}{'approval'} = 1;                      $changes{'notify'}{'approval'} = 1;
                 }                  }
             }              }
               if (ref($domconfig{$action}{'uniquecode'}) eq 'HASH') {
                   if (ref($confhash{'uniquecode'}) eq 'HASH') {
                       foreach my $crstype (keys(%{$domconfig{$action}{'uniquecode'}})) {
                           unless ($confhash{'uniquecode'}{$crstype}) {
                               $changes{'uniquecode'} = 1;
                           }
                       }
                       unless ($changes{'uniquecode'}) {
                           foreach my $crstype (keys(%{$confhash{'uniquecode'}})) {
                               unless ($domconfig{$action}{'uniquecode'}{$crstype}) {
                                   $changes{'uniquecode'} = 1;
                               }
                           }
                       }
                  } else {
                      $changes{'uniquecode'} = 1;
                  }
               } elsif (ref($confhash{'uniquecode'}) eq 'HASH') {
                   $changes{'uniquecode'} = 1;
               }
               if ($context eq 'requestcourses') {
                   foreach my $type ('textbooks','templates') {
                       if (ref($domconfig{$action}{$type}) eq 'HASH') {
                           my %deletions;
                           my @todelete = &Apache::loncommon::get_env_multiple('form.'.$type.'_del');
                           if (@todelete) {
                               map { $deletions{$_} = 1; } @todelete;
                           }
                           my %imgdeletions;
                           my @todeleteimages = &Apache::loncommon::get_env_multiple('form.'.$type.'_image_del');
                           if (@todeleteimages) {
                               map { $imgdeletions{$_} = 1; } @todeleteimages;
                           }
                           my $maxnum = $env{'form.'.$type.'_maxnum'};
                           for (my $i=0; $i<=$maxnum; $i++) {
                               my $itemid = $env{'form.'.$type.'_id_'.$i};
                               my ($key) = ($itemid =~ /^\Q$type\E_(\w+)$/); 
                               if (ref($domconfig{$action}{$type}{$key}) eq 'HASH') {
                                   if ($deletions{$key}) {
                                       if ($domconfig{$action}{$type}{$key}{'image'}) {
                                           #FIXME need to obsolete item in RES space
                                       }
                                       next;
                                   } else {
                                       my $newpos = $env{'form.'.$itemid};
                                       $newpos =~ s/\D+//g;
                                       foreach my $item ('subject','title','publisher','author') {
                                           next if ((($item eq 'author') || ($item eq 'publisher')) &&
                                                    ($type eq 'templates'));
                                           $confhash{$type}{$key}{$item} = $env{'form.'.$type.'_'.$item.'_'.$i};
                                           if ($domconfig{$action}{$type}{$key}{$item} ne $confhash{$type}{$key}{$item}) {
                                               $changes{$type}{$key} = 1;
                                           }
                                       }
                                       $allpos{$type}[$newpos] = $key;
                                   }
                                   if ($imgdeletions{$key}) {
                                       $changes{$type}{$key} = 1;
                                       #FIXME need to obsolete item in RES space
                                   } elsif ($env{'form.'.$type.'_image_'.$i.'.filename'}) {
                                       my ($cdom,$cnum) = split(/_/,$key);
                                       my ($imgurl,$error) = &process_textbook_image($r,$dom,$confname,$type.'_image_'.$i,
                                                                                     $cdom,$cnum,$type,$configuserok,
                                                                                     $switchserver,$author_ok);
                                       if ($imgurl) {
                                           $confhash{$type}{$key}{'image'} = $imgurl;
                                           $changes{$type}{$key} = 1; 
                                       }
                                       if ($error) {
                                           &Apache::lonnet::logthis($error);
                                           $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                                       } 
                                   } elsif ($domconfig{$action}{$type}{$key}{'image'}) {
                                       $confhash{$type}{$key}{'image'} = 
                                           $domconfig{$action}{$type}{$key}{'image'};
                                   }
                               }
                           }
                       }
                   }
               }
         } else {          } else {
             if ($domconfig{$action}{'notify'}{'approval'}) {              if ($confhash{'notify'}{'approval'}) {
                 $changes{'notify'}{'approval'} = 1;                  $changes{'notify'}{'approval'} = 1;
             }              }
               if (ref($confhash{'uniquecode'} eq 'HASH')) {
                   $changes{'uniquecode'} = 1;
               }
           }
           if ($context eq 'requestcourses') {
               foreach my $type ('textbooks','templates') {
                   if ($newbook{$type}) {
                       $changes{$type}{$newbook{$type}} = 1;
                       foreach my $item ('subject','title','publisher','author') {
                           next if ((($item eq 'author') || ($item eq 'publisher')) &&
                                    ($type eq 'template'));
                           $env{'form.'.$type.'_addbook_'.$item} =~ s/(`)/'/g;
                           if ($env{'form.'.$type.'_addbook_'.$item}) {
                               $confhash{$type}{$newbook{$type}}{$item} = $env{'form.'.$type.'_addbook_'.$item};
                           }
                       }
                       if ($type eq 'textbooks') {
                           if ($env{'form.'.$type.'_addbook_image.filename'} ne '') {
                               my ($cdom,$cnum) = split(/_/,$newbook{$type});
                               my ($imageurl,$error) =
                                   &process_textbook_image($r,$dom,$confname,$type.'_addbook_image',$cdom,$cnum,$type,
                                                           $configuserok,$switchserver,$author_ok);
                               if ($imageurl) {
                                   $confhash{$type}{$newbook{$type}}{'image'} = $imageurl;
                               }
                               if ($error) {
                                   &Apache::lonnet::logthis($error);
                                   $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                               }
                           }
                       }
                   }
                   if (@{$allpos{$type}} > 0) {
                       my $idx = 0;
                       foreach my $item (@{$allpos{$type}}) {
                           if ($item ne '') {
                               $confhash{$type}{$item}{'order'} = $idx;
                               if (ref($domconfig{$action}) eq 'HASH') {
                                   if (ref($domconfig{$action}{$type}) eq 'HASH') {
                                       if (ref($domconfig{$action}{$type}{$item}) eq 'HASH') {
                                           if ($domconfig{$action}{$type}{$item}{'order'} ne $idx) {
                                               $changes{$type}{$item} = 1;
                                           }
                                       }
                                   }
                               }
                               $idx ++;
                           }
                       }
                   }
               }
               if (ref($validationitemsref) eq 'ARRAY') {
                   foreach my $item (@{$validationitemsref}) {
                       if ($item eq 'fields') {
                           my @changed;
                           @{$confhash{'validation'}{$item}} = &Apache::loncommon::get_env_multiple('form.requestcourses_validation_'.$item);
                           if (@{$confhash{'validation'}{$item}} > 0) {
                               @{$confhash{'validation'}{$item}} = sort(@{$confhash{'validation'}{$item}});
                           }
                           if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
                               if (ref($domconfig{'requestcourses'}{'validation'}{$item}) eq 'ARRAY') {
                                   @changed = &Apache::loncommon::compare_arrays($confhash{'validation'}{$item},
                                                                                 $domconfig{'requestcourses'}{'validation'}{$item});
                               } else {
                                   @changed = @{$confhash{'validation'}{$item}};
                               }
                           } else {
                               @changed = @{$confhash{'validation'}{$item}};
                           }
                           if (@changed) {
                               if ($confhash{'validation'}{$item}) {
                                   $changes{'validation'}{$item} = join(', ',@{$confhash{'validation'}{$item}});
                               } else {
                                   $changes{'validation'}{$item} = &mt('None');
                               }
                           }
                       } else {
                           $confhash{'validation'}{$item} = $env{'form.requestcourses_validation_'.$item};
                           if ($item eq 'markup') {
                               if ($env{'form.requestcourses_validation_'.$item}) {
                                   $env{'form.requestcourses_validation_'.$item} =~ s/[\n\r\f]+/\s/gs;
                               }
                           }
                           if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
                               if ($domconfig{'requestcourses'}{'validation'}{$item} ne $confhash{'validation'}{$item}) {
                                   $changes{'validation'}{$item} = $confhash{'validation'}{$item};
                               }
                           } else {
                               if ($confhash{'validation'}{$item} ne '') {
                                   $changes{'validation'}{$item} = $confhash{'validation'}{$item};
                               }
                           }
                       }
                   }
               }
               if ($env{'form.validationdc'}) {
                   my $newval = $env{'form.validationdc'};
                   my %domcoords = &get_active_dcs($dom);
                   if (exists($domcoords{$newval})) {
                       $confhash{'validation'}{'dc'} = $newval;
                   }
               }
               if (ref($confhash{'validation'}) eq 'HASH') {
                   if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
                       if ($domconfig{'requestcourses'}{'validation'}{'dc'}) {
                           unless ($confhash{'validation'}{'dc'} eq $domconfig{'requestcourses'}{'validation'}{'dc'}) {
                               if ($confhash{'validation'}{'dc'} eq '') {
                                   $changes{'validation'}{'dc'} = &mt('None');
                               } else {
                                   $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
                               }
                           }
                       } elsif ($confhash{'validation'}{'dc'} ne '') {
                           $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
                       }
                   } elsif ($confhash{'validation'}{'dc'} ne '') {
                       $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
                   }
               } elsif (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
                   if ($domconfig{'requestcourses'}{'validation'}{'dc'}) {
                       $changes{'validation'}{'dc'} = &mt('None');
                   }
               }
         }          }
     } else {      } else {
         $confhash{'defaultquota'}{'default'} = $env{'form.defaultquota'};          $confhash{'defaultquota'}{'default'} = $env{'form.defaultquota'};
           $confhash{'authorquota'}{'default'} = $env{'form.authorquota'};
     }      }
     foreach my $item (@usertools) {      foreach my $item (@usertools) {
         foreach my $type (@{$types},'default','_LC_adv') {          foreach my $type (@{$types},'default','_LC_adv') {
Line 4666  sub modify_quotas { Line 7145  sub modify_quotas {
                         $confhash{$item}{$type} .= $limithash{$item}{$type};                          $confhash{$item}{$type} .= $limithash{$item}{$type};
                     }                      }
                 }                  }
               } elsif ($context eq 'requestauthor') {
                   $unset = '0';
                   if ($type eq '_LC_adv') {
                       $unset = '';
                   }
             } else {              } else {
                 if (grep(/^\Q$type\E$/,@{$toolshash{$item}})) {                  if (grep(/^\Q$type\E$/,@{$toolshash{$item}})) {
                     $confhash{$item}{$type} = 1;                      $confhash{$item}{$type} = 1;
Line 4674  sub modify_quotas { Line 7158  sub modify_quotas {
                 }                  }
             }              }
             if (ref($domconfig{$action}) eq 'HASH') {              if (ref($domconfig{$action}) eq 'HASH') {
                 if (ref($domconfig{$action}{$item}) eq 'HASH') {                  if ($action eq 'requestauthor') {
                       if ($domconfig{$action}{$type} ne $confhash{$type}) {
                           $changes{$type} = 1;
                       }
                   } elsif (ref($domconfig{$action}{$item}) eq 'HASH') {
                     if ($domconfig{$action}{$item}{$type} ne $confhash{$item}{$type}) {                      if ($domconfig{$action}{$item}{$type} ne $confhash{$item}{$type}) {
                         $changes{$item}{$type} = 1;                          $changes{$item}{$type} = 1;
                     }                      }
Line 4694  sub modify_quotas { Line 7182  sub modify_quotas {
                     if ($confhash{$item}{$type} ne $unset) {                      if ($confhash{$item}{$type} ne $unset) {
                         $changes{$item}{$type} = 1;                          $changes{$item}{$type} = 1;
                     }                      }
                   } elsif ($context eq 'requestauthor') {
                       if ($confhash{$type} ne $unset) {
                           $changes{$type} = 1;
                       }
                 } else {                  } else {
                     if (!$confhash{$item}{$type}) {                      if (!$confhash{$item}{$type}) {
                         $changes{$item}{$type} = 1;                          $changes{$item}{$type} = 1;
Line 4702  sub modify_quotas { Line 7194  sub modify_quotas {
             }              }
         }          }
     }      }
     unless ($context eq 'requestcourses') {      unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
         if (ref($domconfig{'quotas'}) eq 'HASH') {          if (ref($domconfig{'quotas'}) eq 'HASH') {
             if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') {              if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') {
                 foreach my $key (keys(%{$domconfig{'quotas'}{'defaultquota'}})) {                  foreach my $key (keys(%{$domconfig{'quotas'}{'defaultquota'}})) {
Line 4725  sub modify_quotas { Line 7217  sub modify_quotas {
                     }                      }
                 }                  }
             }              }
               if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') {
                   foreach my $key (keys(%{$domconfig{'quotas'}{'authorquota'}})) {
                       if (exists($confhash{'authorquota'}{$key})) {
                           if ($confhash{'authorquota'}{$key} ne $domconfig{'quotas'}{'authorquota'}{$key}) {
                               $changes{'authorquota'}{$key} = 1;
                           }
                       } else {
                           $confhash{'authorquota'}{$key} = $domconfig{'quotas'}{'authorquota'}{$key};
                       }
                   }
               }
         }          }
         if (ref($confhash{'defaultquota'}) eq 'HASH') {          if (ref($confhash{'defaultquota'}) eq 'HASH') {
             foreach my $key (keys(%{$confhash{'defaultquota'}})) {              foreach my $key (keys(%{$confhash{'defaultquota'}})) {
Line 4743  sub modify_quotas { Line 7246  sub modify_quotas {
                 }                  }
             }              }
         }          }
           if (ref($confhash{'authorquota'}) eq 'HASH') {
               foreach my $key (keys(%{$confhash{'authorquota'}})) {
                   if (ref($domconfig{'quotas'}) eq 'HASH') {
                       if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') {
                           if (!exists($domconfig{'quotas'}{'authorquota'}{$key})) {
                               $changes{'authorquota'}{$key} = 1;
                           }
                       } else {
                           $changes{'authorquota'}{$key} = 1;
                       }
                   } else {
                       $changes{'authorquota'}{$key} = 1;
                   }
               }
           }
     }      }
   
     foreach my $key (keys(%confhash)) {      if ($context eq 'requestauthor') {
         $domdefaults{$key} = $confhash{$key};          $domdefaults{'requestauthor'} = \%confhash;
       } else {
           foreach my $key (keys(%confhash)) {
               unless (($context eq 'requestcourses') && (($key eq 'textbooks') || ($key eq 'templates'))) {
                   $domdefaults{$key} = $confhash{$key};
               }
           }
     }      }
      
     my %quotahash = (      my %quotahash = (
                       $action => { %confhash }                        $action => { %confhash }
                     );                      );
Line 4758  sub modify_quotas { Line 7282  sub modify_quotas {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             my $cachetime = 24*60*60;              my $cachetime = 24*60*60;
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);              &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
               }
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             unless ($context eq 'requestcourses') {              unless (($context eq 'requestcourses') ||
                       ($context eq 'requestauthor')) {
                 if (ref($changes{'defaultquota'}) eq 'HASH') {                  if (ref($changes{'defaultquota'}) eq 'HASH') {
                     $resulttext .= '<li>'.&mt('Portfolio default quotas').'<ul>';                      $resulttext .= '<li>'.&mt('Portfolio default quotas').'<ul>';
                     foreach my $type (@{$types},'default') {                      foreach my $type (@{$types},'default') {
Line 4769  sub modify_quotas { Line 7296  sub modify_quotas {
                             if ($type eq 'default') {                              if ($type eq 'default') {
                                 $typetitle = $othertitle;                                  $typetitle = $othertitle;
                             }                              }
                             $resulttext .= '<li>'.&mt('[_1] set to [_2] Mb',$typetitle,$confhash{'defaultquota'}{$type}).'</li>';                              $resulttext .= '<li>'.&mt('[_1] set to [_2] MB',$typetitle,$confhash{'defaultquota'}{$type}).'</li>';
                           }
                       }
                       $resulttext .= '</ul></li>';
                   }
                   if (ref($changes{'authorquota'}) eq 'HASH') {
                       $resulttext .= '<li>'.&mt('Authoring Space default quotas').'<ul>';
                       foreach my $type (@{$types},'default') {
                           if (defined($changes{'authorquota'}{$type})) {
                               my $typetitle = $usertypes->{$type};
                               if ($type eq 'default') {
                                   $typetitle = $othertitle;
                               }
                               $resulttext .= '<li>'.&mt('[_1] set to [_2] MB',$typetitle,$confhash{'authorquota'}{$type}).'</li>';
                         }                          }
                     }                      }
                     $resulttext .= '</ul></li>';                      $resulttext .= '</ul></li>';
Line 4777  sub modify_quotas { Line 7317  sub modify_quotas {
             }              }
             my %newenv;              my %newenv;
             foreach my $item (@usertools) {              foreach my $item (@usertools) {
                 if (ref($changes{$item}) eq 'HASH') {                  my (%haschgs,%inconf);
                   if ($context eq 'requestauthor') {
                       %haschgs = %changes;
                       %inconf = %confhash;
                   } else {
                       if (ref($changes{$item}) eq 'HASH') {
                           %haschgs = %{$changes{$item}};
                       }
                       if (ref($confhash{$item}) eq 'HASH') {
                           %inconf = %{$confhash{$item}};
                       }
                   }
                   if (keys(%haschgs) > 0) {
                     my $newacc =                       my $newacc = 
                         &Apache::lonnet::usertools_access($env{'user.name'},                          &Apache::lonnet::usertools_access($env{'user.name'},
                                                           $env{'user.domain'},                                                            $env{'user.domain'},
                                                           $item,'reload',$context);                                                            $item,'reload',$context);
                     if ($context eq 'requestcourses') {                      if (($context eq 'requestcourses') ||
                           ($context eq 'requestauthor')) {
                         if ($env{'environment.canrequest.'.$item} ne $newacc) {                          if ($env{'environment.canrequest.'.$item} ne $newacc) {
                             $newenv{'environment.canrequest.'.$item} = $newacc;                              $newenv{'environment.canrequest.'.$item} = $newacc;
                         }                          }
Line 4791  sub modify_quotas { Line 7344  sub modify_quotas {
                             $newenv{'environment.availabletools.'.$item} = $newacc;                              $newenv{'environment.availabletools.'.$item} = $newacc;
                         }                          }
                     }                      }
                     $resulttext .= '<li>'.$titles{$item}.'<ul>';                      unless ($context eq 'requestauthor') {
                           $resulttext .= '<li>'.$titles{$item}.'<ul>';
                       }
                     foreach my $type (@{$types},'default','_LC_adv') {                      foreach my $type (@{$types},'default','_LC_adv') {
                         if ($changes{$item}{$type}) {                          if ($haschgs{$type}) {
                             my $typetitle = $usertypes->{$type};                              my $typetitle = $usertypes->{$type};
                             if ($type eq 'default') {                              if ($type eq 'default') {
                                 $typetitle = $othertitle;                                  $typetitle = $othertitle;
                             } elsif ($type eq '_LC_adv') {                              } elsif ($type eq '_LC_adv') {
                                 $typetitle = 'LON-CAPA Advanced Users';                                   $typetitle = 'LON-CAPA Advanced Users'; 
                             }                              }
                             if ($confhash{$item}{$type}) {                              if ($inconf{$type}) {
                                 if ($context eq 'requestcourses') {                                  if ($context eq 'requestcourses') {
                                     my $cond;                                      my $cond;
                                     if ($confhash{$item}{$type} =~ /^autolimit=(\d*)$/) {                                      if ($inconf{$type} =~ /^autolimit=(\d*)$/) {
                                         if ($1 eq '') {                                          if ($1 eq '') {
                                             $cond = &mt('(Automatic processing of any request).');                                              $cond = &mt('(Automatic processing of any request).');
                                         } else {                                          } else {
                                             $cond = &mt('(Automatic processing of requests up to limit of [quant,_1,request] per user).',$1);                                              $cond = &mt('(Automatic processing of requests up to limit of [quant,_1,request] per user).',$1);
                                         }                                          }
                                     } else {                                       } else { 
                                         $cond = $conditions{$confhash{$item}{$type}};                                          $cond = $conditions{$inconf{$type}};
                                     }                                      }
                                     $resulttext .= '<li>'.&mt('Set to be available to [_1].',$typetitle).' '.$cond.'</li>';                                      $resulttext .= '<li>'.&mt('Set to be available to [_1].',$typetitle).' '.$cond.'</li>';
                                   } elsif ($context eq 'requestauthor') {
                                       $resulttext .= '<li>'.&mt('Set to "[_1]" for "[_2]".',
                                                                $titles{$inconf{$type}},$typetitle);
   
                                 } else {                                  } else {
                                     $resulttext .= '<li>'.&mt('Set to be available to [_1]',$typetitle).'</li>';                                      $resulttext .= '<li>'.&mt('Set to be available to [_1]',$typetitle).'</li>';
                                 }                                  }
                             } else {                              } else {
                                 if ($type eq '_LC_adv') {                                  if ($type eq '_LC_adv') {
                                     if ($confhash{$item}{$type} eq '0') {                                      if ($inconf{$type} eq '0') {
                                         $resulttext .= '<li>'.&mt('Set to be unavailable to [_1]',$typetitle).'</li>';                                          $resulttext .= '<li>'.&mt('Set to be unavailable to [_1]',$typetitle).'</li>';
                                     } else {                                       } else { 
                                         $resulttext .= '<li>'.&mt('No override set for [_1]',$typetitle).'</li>';                                          $resulttext .= '<li>'.&mt('No override set for [_1]',$typetitle).'</li>';
Line 4829  sub modify_quotas { Line 7388  sub modify_quotas {
                             }                              }
                         }                          }
                     }                      }
                     $resulttext .= '</ul></li>';                      unless ($context eq 'requestauthor') {
                           $resulttext .= '</ul></li>';
                       }
                 }                  }
             }              }
             if ($action eq 'requestcourses') {              if (($action eq 'requestcourses') || ($action eq 'requestauthor')) {
                 if (ref($changes{'notify'}) eq 'HASH') {                  if (ref($changes{'notify'}) eq 'HASH') {
                     if ($changes{'notify'}{'approval'}) {                      if ($changes{'notify'}{'approval'}) {
                         if (ref($confhash{'notify'}) eq 'HASH') {                          if (ref($confhash{'notify'}) eq 'HASH') {
                             if ($confhash{'notify'}{'approval'}) {                              if ($confhash{'notify'}{'approval'}) {
                                 $resulttext .= '<li>'.&mt('Notification of requests requiring approval will be sent to: ').$confhash{'notify'}{'approval'}.'</li>';                                  $resulttext .= '<li>'.&mt('Notification of requests requiring approval will be sent to: ').$confhash{'notify'}{'approval'}.'</li>';
                             } else {                              } else {
                                 $resulttext .= '<li>'.&mt('No Domain Coordinators will receive notification of course requests requiring approval.').'</li>';                                  $resulttext .= '<li>'.&mt('No Domain Coordinators will receive notification of requests requiring approval.').'</li>';
                               }
                           }
                       }
                   }
               }
               if ($action eq 'requestcourses') {
                   my @offon = ('off','on');
                   if ($changes{'uniquecode'}) {
                       if (ref($confhash{'uniquecode'}) eq 'HASH') {
                           my $codestr = join(' ',map{ &mt($_); } sort(keys(%{$confhash{'uniquecode'}})));
                           $resulttext .= '<li>'.
                                          &mt('Generation of six character code as course identifier for distribution to students set to on for: [_1].','<b>'.$codestr.'</b>').
                                          '</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('Generation of six character code as course identifier for distribution to students set to off.').
                                          '</li>';
                       }
                   }
                   foreach my $type ('textbooks','templates') {
                       if (ref($changes{$type}) eq 'HASH') {
                           $resulttext .= '<li>'.&mt("Available $type updated").'<ul>';
                           foreach my $key (sort(keys(%{$changes{$type}}))) {
                               my %coursehash = &Apache::lonnet::coursedescription($key);
                               my $coursetitle = $coursehash{'description'};
                               my $position = $confhash{$type}{$key}{'order'} + 1;
                               $resulttext .= '<li>';
                               foreach my $item ('subject','title','publisher','author') {
                                   next if ((($item eq 'author') || ($item eq 'publisher')) &&
                                            ($type eq 'templates'));
                                   my $name = $item.':';
                                   $name =~ s/^(\w)/\U$1/;
                                   $resulttext .= &mt($name).' '.$confhash{$type}{$key}{$item}.'<br />';
                               }
                               $resulttext .= ' '.&mt('Order: [_1]',$position).'<br />';
                               if ($type eq 'textbooks') {
                                   if ($confhash{$type}{$key}{'image'}) {
                                       $resulttext .= ' '.&mt('Image: [_1]',
                                                      '<img src="'.$confhash{$type}{$key}{'image'}.'"'.
                                                      ' alt="Textbook cover" />').'<br />';
                                   }
                             }                              }
                               $resulttext .= ' '.&mt('LON-CAPA Course: [_1]',$coursetitle).'</li>';
                           }
                           $resulttext .= '</ul></li>';
                       }
                   }
                   if (ref($changes{'validation'}) eq 'HASH') {
                       if ((ref($validationitemsref) eq 'ARRAY') && (ref($validationnamesref) eq 'HASH')) {
                           $resulttext .= '<li>'.&mt('Validation of courses/communities updated').'<ul>';
                           foreach my $item (@{$validationitemsref}) {
                               if (exists($changes{'validation'}{$item})) {
                                   if ($item eq 'markup') {
                                       $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$validationnamesref->{$item},
                                                                 '<br /><pre>'.$changes{'validation'}{$item}.'</pre>').'</li>';
                                   } else {
                                       $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$validationnamesref->{$item},
                                                                 '<b>'.$changes{'validation'}{$item}.'</b>').'</li>';
                                   }
                               }
                           }
                           if (exists($changes{'validation'}{'dc'})) {
                               $resulttext .= '<li>'.&mt('Validated course requests identified as processed by: [_1]',
                                                        '<b>'.$changes{'validation'}{'dc'}.'</b>').'</li>';
                         }                          }
                     }                      }
                 }                  }
Line 4852  sub modify_quotas { Line 7475  sub modify_quotas {
         } else {          } else {
             if ($context eq 'requestcourses') {              if ($context eq 'requestcourses') {
                 $resulttext = &mt('No changes made to rights to request creation of courses.');                  $resulttext = &mt('No changes made to rights to request creation of courses.');
               } elsif ($context eq 'requestauthor') {
                   $resulttext = &mt('No changes made to rights to request author space.');
             } else {              } else {
                 $resulttext = &mt('No changes made to availability of personal information pages, blogs, portfolios or default quotas');                  $resulttext = &mt('No changes made to availability of personal information pages, blogs, portfolios or default quotas');
             }              }
Line 4860  sub modify_quotas { Line 7485  sub modify_quotas {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
     &mt('An error occurred: [_1]',$putresult).'</span>';      &mt('An error occurred: [_1]',$putresult).'</span>';
     }      }
       if ($errors) {
           $resulttext .= '<p>'.&mt('The following errors occurred when modifying Textbook settings.').
                          '<ul>'.$errors.'</ul></p>';
       }
     return $resulttext;      return $resulttext;
 }  }
   
   sub process_textbook_image {
       my ($r,$dom,$confname,$caller,$cdom,$cnum,$type,$configuserok,$switchserver,$author_ok) = @_;
       my $filename = $env{'form.'.$caller.'.filename'};
       my ($error,$url);
       my ($width,$height) = (50,50);
       if ($configuserok eq 'ok') {
           if ($switchserver) {
               $error = &mt('Upload of textbook image is not permitted to this server: [_1]',
                            $switchserver);
           } elsif ($author_ok eq 'ok') {
               my ($result,$imageurl) =
                   &publishlogo($r,'upload',$caller,$dom,$confname,
                                "$type/$dom/$cnum/cover",$width,$height);
               if ($result eq 'ok') {
                   $url = $imageurl;
               } else {
                   $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$result);
               }
           } else {
               $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3].  Error was: [_4].",$filename,$confname,$dom,$author_ok);
           }
       } else {
           $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3].  Error was: [_4].",$filename,$confname,$dom,$configuserok);
       }
       return ($url,$error);
   }
   
 sub modify_autoenroll {  sub modify_autoenroll {
     my ($dom,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,%changes);      my ($resulttext,%changes);
     my %currautoenroll;      my %currautoenroll;
     if (ref($domconfig{'autoenroll'}) eq 'HASH') {      if (ref($domconfig{'autoenroll'}) eq 'HASH') {
Line 4932  sub modify_autoenroll { Line 7588  sub modify_autoenroll {
             if ($changes{'coowners'}) {              if ($changes{'coowners'}) {
                 $resulttext .= '<li>'.&mt("$title{'coowners'} set to $offon[$env{'form.autoassign_coowners'}]").'</li>';                  $resulttext .= '<li>'.&mt("$title{'coowners'} set to $offon[$env{'form.autoassign_coowners'}]").'</li>';
                 &Apache::loncommon::devalidate_domconfig_cache($dom);                  &Apache::loncommon::devalidate_domconfig_cache($dom);
                   if (ref($lastactref) eq 'HASH') {
                       $lastactref->{'domainconfig'} = 1;
                   }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
Line 4966  sub modify_autoupdate { Line 7625  sub modify_autoupdate {
                         middlename => 'Middle Name',                          middlename => 'Middle Name',
                         generation => 'Generation',                          generation => 'Generation',
                       );                        );
     my $othertitle = &mt('All users');      $othertitle = &mt('All users');
     if (keys(%{$usertypes}) >  0) {      if (keys(%{$usertypes}) >  0) {
         $othertitle = &mt('Other users');          $othertitle = &mt('Other users');
     }      }
Line 5182  sub modify_autocreate { Line 7841  sub modify_autocreate {
             foreach my $item (@types) {              foreach my $item (@types) {
                 if ($changes{$item}) {                  if ($changes{$item}) {
                     my $newtxt = $offon[$newvals{$item}];                      my $newtxt = $offon[$newvals{$item}];
                     $resulttext .= '<li>'.&mt("$title{$item} set to [_1]$newtxt [_2]",'<b>','</b>').'</li>';                      $resulttext .= '<li>'.
                                      &mt("$title{$item} set to [_1]$newtxt [_2]",
                                          '<b>','</b>').
                                      '</li>';
                 }                  }
             }              }
             if ($changes{'xmldc'}) {              if ($changes{'xmldc'}) {
                 my ($dcname,$dcdom) = split(':',$newvals{'xmldc'});                  my ($dcname,$dcdom) = split(':',$newvals{'xmldc'});
                 my $newtxt = &Apache::loncommon::plainname($dcname,$dcdom);                  my $newtxt = &Apache::loncommon::plainname($dcname,$dcdom);
                 $resulttext .= '<li>'.&mt("$title{'xmldc'} set to [_1]$newtxt [_2]",'<b>','</b>').'</li>';                   $resulttext .= '<li>'.&mt("$title{'xmldc'} set to [_1]",'<b>'.$newtxt.'</b>').'</li>'; 
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
Line 5334  sub modify_directorysrch { Line 7996  sub modify_directorysrch {
                         } else {                          } else {
                             $chgtext =~ s/\; $//;                              $chgtext =~ s/\; $//;
                         }                          }
                         $resulttext .= '<li>'.&mt("Users from domain '<span class=\"LC_cusr_emph\">[_1]</span>' permitted to search the institutional directory set to: [_2]",$dom,$chgtext).'</li>';                          $resulttext .=
                               '<li>'.
                               &mt("Users from domain '[_1]' permitted to search the institutional directory set to: [_2]",
                                   '<span class="LC_cusr_emph">'.$dom.'</span>',$chgtext).
                               '</li>';
                     }                      }
                 }                  }
             }              }
Line 5362  sub modify_directorysrch { Line 8028  sub modify_directorysrch {
                     }                      }
                 }                  }
                 $chgtext =~ s/\; $//;                  $chgtext =~ s/\; $//;
                 $resulttext .= '<li>'.&mt("$title{'searchtypes'} set to: \"[_1]\"",$chgtext).'</li>';                  $resulttext .= '<li>'.&mt($title{'searchtypes'}.' set to: "[_1]"',$chgtext).'</li>';
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
Line 5376  sub modify_directorysrch { Line 8042  sub modify_directorysrch {
 }  }
   
 sub modify_contacts {  sub modify_contacts {
     my ($dom,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,%currsetting,%newsetting,%changes,%contacts_hash);      my ($resulttext,%currsetting,%newsetting,%changes,%contacts_hash);
     if (ref($domconfig{'contacts'}) eq 'HASH') {      if (ref($domconfig{'contacts'}) eq 'HASH') {
         foreach my $key (keys(%{$domconfig{'contacts'}})) {          foreach my $key (keys(%{$domconfig{'contacts'}})) {
Line 5386  sub modify_contacts { Line 8052  sub modify_contacts {
     my (%others,%to,%bcc);      my (%others,%to,%bcc);
     my @contacts = ('supportemail','adminemail');      my @contacts = ('supportemail','adminemail');
     my @mailings = ('errormail','packagesmail','helpdeskmail','lonstatusmail',      my @mailings = ('errormail','packagesmail','helpdeskmail','lonstatusmail',
                     'requestsmail');                      'requestsmail','updatesmail','idconflictsmail');
       my @toggles = ('reporterrors','reportupdates');
     foreach my $type (@mailings) {      foreach my $type (@mailings) {
         @{$newsetting{$type}} =           @{$newsetting{$type}} = 
             &Apache::loncommon::get_env_multiple('form.'.$type);              &Apache::loncommon::get_env_multiple('form.'.$type);
Line 5408  sub modify_contacts { Line 8075  sub modify_contacts {
         $to{$item} = $env{'form.'.$item};          $to{$item} = $env{'form.'.$item};
         $contacts_hash{'contacts'}{$item} = $to{$item};          $contacts_hash{'contacts'}{$item} = $to{$item};
     }      }
       foreach my $item (@toggles) {
           if ($env{'form.'.$item} =~ /^(0|1)$/) {
               $contacts_hash{'contacts'}{$item} = $env{'form.'.$item};
           }
       }
     if (keys(%currsetting) > 0) {      if (keys(%currsetting) > 0) {
         foreach my $item (@contacts) {          foreach my $item (@contacts) {
             if ($to{$item} ne $currsetting{$item}) {              if ($to{$item} ne $currsetting{$item}) {
Line 5442  sub modify_contacts { Line 8114  sub modify_contacts {
         $default{'helpdeskmail'} = 'supportemail';          $default{'helpdeskmail'} = 'supportemail';
         $default{'lonstatusmail'} = 'adminemail';          $default{'lonstatusmail'} = 'adminemail';
         $default{'requestsmail'} = 'adminemail';          $default{'requestsmail'} = 'adminemail';
           $default{'updatesmail'} = 'adminemail';
         foreach my $item (@contacts) {          foreach my $item (@contacts) {
            if ($to{$item} ne $default{$item}) {             if ($to{$item} ne $default{$item}) {
               $changes{$item} = 1;                $changes{$item} = 1;
            }              }
         }          }
         foreach my $type (@mailings) {          foreach my $type (@mailings) {
             if ((@{$newsetting{$type}} != 1) || ($newsetting{$type}[0] ne $default{$type})) {              if ((@{$newsetting{$type}} != 1) || ($newsetting{$type}[0] ne $default{$type})) {
Line 5462  sub modify_contacts { Line 8135  sub modify_contacts {
             }              }
         }          }
     }      }
       foreach my $item (@toggles) {
           if (($env{'form.'.$item} == 1) && ($currsetting{$item} == 0)) {
               $changes{$item} = 1;
           } elsif ((!$env{'form.'.$item}) &&
                    (($currsetting{$item} eq '') || ($currsetting{$item} == 1))) {
               $changes{$item} = 1;
           }
       }
     my $putresult = &Apache::lonnet::put_dom('configuration',\%contacts_hash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%contacts_hash,
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
               &Apache::loncommon::devalidate_domconfig_cache($dom);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domainconfig'} = 1;
               }
             my ($titles,$short_titles)  = &contact_titles();              my ($titles,$short_titles)  = &contact_titles();
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             foreach my $item (@contacts) {              foreach my $item (@contacts) {
Line 5496  sub modify_contacts { Line 8181  sub modify_contacts {
                     $resulttext .= '</li>';                      $resulttext .= '</li>';
                 }                  }
             }              }
               my @offon = ('off','on');
               if ($changes{'reporterrors'}) {
                   $resulttext .= '<li>'.
                                  &mt('E-mail error reports to [_1] set to "'.
                                      $offon[$env{'form.reporterrors'}].'".',
                                      &Apache::loncommon::modal_link('http://loncapa.org/core.html',
                                          &mt('LON-CAPA core group - MSU'),600,500)).
                                  '</li>';
               }
               if ($changes{'reportupdates'}) {
                   $resulttext .= '<li>'.
                                   &mt('E-mail record of completed LON-CAPA updates to [_1] set to "'.
                                       $offon[$env{'form.reportupdates'}].'".',
                                       &Apache::loncommon::modal_link('http://loncapa.org/core.html',
                                           &mt('LON-CAPA core group - MSU'),600,500)).
                                   '</li>';
               }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
             $resulttext = &mt('No changes made to contact information');              $resulttext = &mt('No changes made to contact information');
Line 5509  sub modify_contacts { Line 8211  sub modify_contacts {
   
 sub modify_usercreation {  sub modify_usercreation {
     my ($dom,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate);      my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate,%save_usercreate);
     my $warningmsg;      my $warningmsg;
     if (ref($domconfig{'usercreation'}) eq 'HASH') {      if (ref($domconfig{'usercreation'}) eq 'HASH') {
         foreach my $key (keys(%{$domconfig{'usercreation'}})) {          foreach my $key (keys(%{$domconfig{'usercreation'}})) {
             $curr_usercreation{$key} = $domconfig{'usercreation'}{$key};              if ($key eq 'cancreate') {
         }                  if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {
     }                      foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
     my @username_rule = &Apache::loncommon::get_env_multiple('form.username_rule');                          if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||
     my @id_rule = &Apache::loncommon::get_env_multiple('form.id_rule');                              ($item eq 'captcha') || ($item eq 'recaptchakeys')) {
     my @email_rule = &Apache::loncommon::get_env_multiple('form.email_rule');                              $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
     my @contexts = ('author','course','requestcrs','selfcreate');                          } else {
     foreach my $item(@contexts) {                              $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
         if ($item eq 'selfcreate') {                          }
             @{$cancreate{$item}} = &Apache::loncommon::get_env_multiple('form.can_createuser_'.$item);  
             my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);  
             if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) || ($domdefaults{'auth_def'} eq 'localauth'))) {  
                 if (ref($cancreate{$item}) eq 'ARRAY') {   
                     if (grep(/^login$/,@{$cancreate{$item}})) {  
                         $warningmsg = &mt('Although account creation has been set to be available for institutional logins, currently default authentication in this domain has not been set to support this.').' '.&mt('You need to set the default authentication type to Kerberos 4 or 5 (with a Kerberos domain specified), or to Local authentication, if the localauth module has been customized in your domain to authenticate institutional logins.');     
                     }                      }
                 }                  }
               } elsif ($key eq 'email_rule') {
                   $save_usercreate{$key} = $domconfig{'usercreation'}{$key};
               } else {
                   $curr_usercreation{$key} = $domconfig{'usercreation'}{$key};
             }              }
         } else {  
             $cancreate{$item} = $env{'form.can_createuser_'.$item};  
         }          }
     }      }
     my ($othertitle,$usertypes,$types) =       my @username_rule = &Apache::loncommon::get_env_multiple('form.username_rule');
         &Apache::loncommon::sorted_inst_types($dom);      my @id_rule = &Apache::loncommon::get_env_multiple('form.id_rule');
     if (ref($types) eq 'ARRAY') {      my @contexts = ('author','course','requestcrs');
         if (@{$types} > 0) {      foreach my $item(@contexts) {
             @{$cancreate{'statustocreate'}} =           $cancreate{$item} = $env{'form.can_createuser_'.$item};
                 &Apache::loncommon::get_env_multiple('form.statustocreate');  
         } else {  
             @{$cancreate{'statustocreate'}} = ();  
         }  
         push(@contexts,'statustocreate');  
     }      }
     if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {      if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {
         foreach my $item (@contexts) {          foreach my $item (@contexts) {
             if (($item eq 'selfcreate') || ($item eq 'statustocreate')) {              if ($curr_usercreation{'cancreate'}{$item} ne $cancreate{$item}) {
                 if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') {                  push(@{$changes{'cancreate'}},$item);
                     foreach my $curr (@{$curr_usercreation{'cancreate'}{$item}}) {  
                         if (ref($cancreate{$item}) eq 'ARRAY') {  
                             if (!grep(/^$curr$/,@{$cancreate{$item}})) {  
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                     push(@{$changes{'cancreate'}},$item);  
                                 }  
                             }  
                         }  
                     }  
                 } else {  
                     if ($curr_usercreation{'cancreate'}{$item} eq '') {  
                         if (@{$cancreate{$item}} > 0) {  
                             if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                 push(@{$changes{'cancreate'}},$item);  
                             }  
                         }  
                     } else {  
                         if ($curr_usercreation{'cancreate'}{$item} eq 'any') {  
                             if (@{$cancreate{$item}} < 3) {  
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                     push(@{$changes{'cancreate'}},$item);  
                                 }  
                             }  
                         } elsif ($curr_usercreation{'cancreate'}{$item} eq 'none') {  
                             if (@{$cancreate{$item}} > 0) {  
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                     push(@{$changes{'cancreate'}},$item);  
                                 }  
                             }  
                         } elsif (!grep(/^$curr_usercreation{'cancreate'}{$item}$/,@{$cancreate{$item}})) {  
                             if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                 push(@{$changes{'cancreate'}},$item);  
                             }  
                         }  
                     }  
                 }  
                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                     foreach my $type (@{$cancreate{$item}}) {  
                         if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') {  
                             if (!grep(/^$type$/,@{$curr_usercreation{'cancreate'}{$item}})) {  
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                     push(@{$changes{'cancreate'}},$item);  
                                 }  
                             }  
                         } elsif (($curr_usercreation{'cancreate'}{$item} ne 'any') &&  
                                  ($curr_usercreation{'cancreate'}{$item} ne 'none')) {  
                             if ($curr_usercreation{'cancreate'}{$item} ne $type) {  
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                     push(@{$changes{'cancreate'}},$item);  
                                 }  
                             }  
                         }  
                     }  
                 }  
             } else {  
                 if ($curr_usercreation{'cancreate'}{$item} ne $cancreate{$item}) {  
                     push(@{$changes{'cancreate'}},$item);  
                 }  
             }              }
         }          }
     } elsif (ref($curr_usercreation{'cancreate'}) eq 'ARRAY') {      } elsif (ref($curr_usercreation{'cancreate'}) eq 'ARRAY') {
Line 5658  sub modify_usercreation { Line 8293  sub modify_usercreation {
         push(@{$changes{'id_rule'}},@id_rule);          push(@{$changes{'id_rule'}},@id_rule);
     }      }
   
     if (ref($curr_usercreation{'email_rule'}) eq 'ARRAY') {  
         foreach my $type (@{$curr_usercreation{'email_rule'}}) {  
             if (!grep(/^\Q$type\E$/,@email_rule)) {  
                 push(@{$changes{'email_rule'}},$type);  
             }  
         }  
         foreach my $type (@email_rule) {  
             if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'email_rule'}})) {  
                 push(@{$changes{'email_rule'}},$type);  
             }  
         }  
     } else {  
         push(@{$changes{'email_rule'}},@email_rule);  
     }  
   
     my @authen_contexts = ('author','course','domain');      my @authen_contexts = ('author','course','domain');
     my @authtypes = ('int','krb4','krb5','loc');      my @authtypes = ('int','krb4','krb5','loc');
     my %authhash;      my %authhash;
Line 5703  sub modify_usercreation { Line 8323  sub modify_usercreation {
         }          }
     }      }
   
       $save_usercreate{'cancreate'}{'course'} = $cancreate{'course'}; 
       $save_usercreate{'cancreate'}{'author'} = $cancreate{'author'};
       $save_usercreate{'cancreate'}{'requestcrs'} = $cancreate{'requestcrs'};
       $save_usercreate{'id_rule'} = \@id_rule;
       $save_usercreate{'username_rule'} = \@username_rule,
       $save_usercreate{'authtypes'} = \%authhash;
   
     my %usercreation_hash =  (      my %usercreation_hash =  (
             usercreation => {          usercreation     => \%save_usercreate,
                               cancreate     => \%cancreate,      );
                               username_rule => \@username_rule,  
                               id_rule       => \@id_rule,  
                               email_rule    => \@email_rule,  
                               authtypes     => \%authhash,  
                             }  
             );  
   
     my $putresult = &Apache::lonnet::put_dom('configuration',\%usercreation_hash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%usercreation_hash,
                                              $dom);                                               $dom);
   
       if ($putresult eq 'ok') {
           if (keys(%changes) > 0) {
               $resulttext = &mt('Changes made:').'<ul>';
               if (ref($changes{'cancreate'}) eq 'ARRAY') {
                   my %lt = &usercreation_types();
                   foreach my $type (@{$changes{'cancreate'}}) {
                       my $chgtext = $lt{$type}.', ';
                       if ($cancreate{$type} eq 'none') {
                           $chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.');
                       } elsif ($cancreate{$type} eq 'any') {
                           $chgtext .= &mt('creation of new users is permitted for both institutional and non-institutional usernames.');
                       } elsif ($cancreate{$type} eq 'official') {
                           $chgtext .= &mt('creation of new users is only permitted for institutional usernames.');
                       } elsif ($cancreate{$type} eq 'unofficial') {
                           $chgtext .= &mt('creation of new users is only permitted for non-institutional usernames.');
                       }
                       $resulttext .= '<li>'.$chgtext.'</li>';
                   }
               }
               if (ref($changes{'username_rule'}) eq 'ARRAY') {
                   my ($rules,$ruleorder) = 
                       &Apache::lonnet::inst_userrules($dom,'username');
                   my $chgtext = '<ul>';
                   foreach my $type (@username_rule) {
                       if (ref($rules->{$type}) eq 'HASH') {
                           $chgtext .= '<li>'.$rules->{$type}{'name'}.'</li>';
                       }
                   }
                   $chgtext .= '</ul>';
                   if (@username_rule > 0) {
                       $resulttext .= '<li>'.&mt('Usernames with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';     
                   } else {
                       $resulttext .= '<li>'.&mt('There are now no username formats restricted to verified users in the institutional directory.').'</li>'; 
                   }
               }
               if (ref($changes{'id_rule'}) eq 'ARRAY') {
                   my ($idrules,$idruleorder) = 
                       &Apache::lonnet::inst_userrules($dom,'id');
                   my $chgtext = '<ul>';
                   foreach my $type (@id_rule) {
                       if (ref($idrules->{$type}) eq 'HASH') {
                           $chgtext .= '<li>'.$idrules->{$type}{'name'}.'</li>';
                       }
                   }
                   $chgtext .= '</ul>';
                   if (@id_rule > 0) {
                       $resulttext .= '<li>'.&mt('IDs with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';
                   } else {
                       $resulttext .= '<li>'.&mt('There are now no ID formats restricted to verified users in the institutional directory.').'</li>';
                   }
               }
               my %authname = &authtype_names();
               my %context_title = &context_names();
               if (ref($changes{'authtypes'}) eq 'ARRAY') {
                   my $chgtext = '<ul>';
                   foreach my $type (@{$changes{'authtypes'}}) {
                       my @allowed;
                       $chgtext .= '<li><span class="LC_cusr_emph">'.$context_title{$type}.'</span> - '.&mt('assignable authentication types: ');
                       foreach my $auth (@authtypes) {
                           if ($authhash{$type}{$auth}) {
                               push(@allowed,$authname{$auth});
                           }
                       }
                       if (@allowed > 0) {
                           $chgtext .= join(', ',@allowed).'</li>';
                       } else {
                           $chgtext .= &mt('none').'</li>';
                       }
                   }
                   $chgtext .= '</ul>';
                   $resulttext .= '<li>'.&mt('Authentication types available for assignment to new users').'<br />'.$chgtext;
                   $resulttext .= '</li>';
               }
               $resulttext .= '</ul>';
           } else {
               $resulttext = &mt('No changes made to user creation settings');
           }
       } else {
           $resulttext = '<span class="LC_error">'.
               &mt('An error occurred: [_1]',$putresult).'</span>';
       }
       if ($warningmsg ne '') {
           $resulttext .= '<br /><span class="LC_warning">'.$warningmsg.'</span><br />';
       }
       return $resulttext;
   }
   
   sub modify_selfcreation {
       my ($dom,%domconfig) = @_;
       my ($resulttext,$warningmsg,%curr_usercreation,%curr_usermodify,%changes,%cancreate);
       my (%save_usercreate,%save_usermodify);
       my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
       if (ref($types) eq 'ARRAY') {
           $usertypes->{'default'} = $othertitle;
           push(@{$types},'default');
       }
   #
   # Retrieve current domain configuration for self-creation of usernames from $domconfig{'usercreation'}.
   #
       if (ref($domconfig{'usercreation'}) eq 'HASH') {
           foreach my $key (keys(%{$domconfig{'usercreation'}})) {
               if ($key eq 'cancreate') {
                   if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {
                       foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
                           if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||
                               ($item eq 'captcha') || ($item eq 'recaptchakeys') || 
                               ($item eq 'emailusername') || ($item eq 'notify') ||
                               ($item eq 'selfcreateprocessing') || ($item eq 'shibenv')) {
                               $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
                           } else {
                               $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
                           }
                       }
                   }
               } elsif ($key eq 'email_rule') {
                   $curr_usercreation{$key} = $domconfig{'usercreation'}{$key};
               } else {
                   $save_usercreate{$key} = $domconfig{'usercreation'}{$key};
               }
           }
       }
   #
   # Retrieve current domain configuration for self-creation of usernames from $domconfig{'usermodification'}.
   #
       if (ref($domconfig{'usermodification'}) eq 'HASH') {
           foreach my $key (keys(%{$domconfig{'usermodification'}})) {
               if ($key eq 'selfcreate') {
                   $curr_usermodify{$key} = $domconfig{'usermodification'}{$key};
               } else {
                   $save_usermodify{$key} = $domconfig{'usermodification'}{$key};
               }
           }
       }
   
       my @contexts = ('selfcreate');
       @{$cancreate{'selfcreate'}} = ();
       %{$cancreate{'emailusername'}} = ();
       @{$cancreate{'statustocreate'}} = ();
       %{$cancreate{'selfcreateprocessing'}} = ();
       %{$cancreate{'shibenv'}} = ();
     my %selfcreatetypes = (      my %selfcreatetypes = (
                              sso   => 'users authenticated by institutional single sign on',                               sso   => 'users authenticated by institutional single sign on',
                              login => 'users authenticated by institutional log-in',                               login => 'users authenticated by institutional log-in',
                              email => 'users who provide a valid e-mail address for use as the username',                               email => 'users who provide a valid e-mail address for use as username',
                           );                            );
   #
   # Populate $cancreate{'selfcreate'} array reference with types of user, for which self-creation of user accounts
   # is permitted.
   #
   
       my @statuses;
       if (ref($domconfig{'inststatus'}) eq 'HASH') {
           if (ref($domconfig{'inststatus'}{'inststatusguest'}) eq 'ARRAY') {
               @statuses = @{$domconfig{'inststatus'}{'inststatusguest'}};
           }
       }
       push(@statuses,'default');
   
       foreach my $item ('login','sso','email') {
           if ($item eq 'email') {
               if ($env{'form.cancreate_email'}) {
                   push(@{$cancreate{'selfcreate'}},'email');
                   push(@contexts,'selfcreateprocessing');
                   foreach my $type (@statuses) {
                       if ($type eq 'default') {
                           $cancreate{'selfcreateprocessing'}{$type} = $env{'form.cancreate_emailprocess'};
                       } else { 
                           $cancreate{'selfcreateprocessing'}{$type} = $env{'form.cancreate_emailprocess_'.$type};
                       }
                   }
               }
           } else {
               if ($env{'form.cancreate_'.$item}) {
                   push(@{$cancreate{'selfcreate'}},$item);
               }
           }
       }
       my (@email_rule,%userinfo,%savecaptcha);
       my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();
   #
   # Populate $cancreate{'emailusername'}{$type} hash ref with information fields (if new user will provide data
   # value set to one), if self-creation with e-mail address permitted, where $type is user type: faculty, staff, student etc.
   #
   
       if ($env{'form.cancreate_email'}) {
           push(@contexts,'emailusername');
           if (ref($types) eq 'ARRAY') {
               foreach my $type (@{$types}) {
                   if (ref($infofields) eq 'ARRAY') {
                       foreach my $field (@{$infofields}) {
                           if ($env{'form.canmodify_emailusername_'.$type.'_'.$field} =~ /^(required|optional)$/) {
                               $cancreate{'emailusername'}{$type}{$field} = $1;
                           }
                       }
                   }
               }
           }
   #
   # Populate $cancreate{'notify'} hash ref with names of Domain Coordinators who are to be notified of
   # queued requests for self-creation of account using e-mail address as username
   #
   
           my @approvalnotify = &Apache::loncommon::get_env_multiple('form.selfcreationnotifyapproval');
           @approvalnotify = sort(@approvalnotify);
           $cancreate{'notify'}{'approval'} = join(',',@approvalnotify);
           if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {
               if (ref($curr_usercreation{'cancreate'}{'notify'}) eq 'HASH') {
                   if ($curr_usercreation{'cancreate'}{'notify'}{'approval'} ne $cancreate{'notify'}{'approval'}) {
                       push(@{$changes{'cancreate'}},'notify');
                   }
               } else {
                   if ($cancreate{'notify'}{'approval'}) {
                       push(@{$changes{'cancreate'}},'notify');
                   }
               }
           } elsif ($cancreate{'notify'}{'approval'}) {
               push(@{$changes{'cancreate'}},'notify');
           }
   
   #
   # Retrieve rules (if any) governing types of e-mail address which may be used as a username
   #
           @email_rule = &Apache::loncommon::get_env_multiple('form.email_rule');
           &process_captcha('cancreate',\%changes,\%savecaptcha,$curr_usercreation{'cancreate'});
           if (ref($curr_usercreation{'email_rule'}) eq 'ARRAY') {
               if (@{$curr_usercreation{'email_rule'}} > 0) {
                   foreach my $type (@{$curr_usercreation{'email_rule'}}) {
                       if (!grep(/^\Q$type\E$/,@email_rule)) {
                           push(@{$changes{'email_rule'}},$type);
                       }
                   }
               }
               if (@email_rule > 0) {
                   foreach my $type (@email_rule) {
                       if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'email_rule'}})) {
                           push(@{$changes{'email_rule'}},$type);
                       }
                   }
               }
           } elsif (@email_rule > 0) {
               push(@{$changes{'email_rule'}},@email_rule);
           }
       }
   #  
   # Check if domain default is set appropriately, if self-creation of accounts is to be available for
   # institutional log-in.
   #
       if (grep(/^login$/,@{$cancreate{'selfcreate'}})) {
           my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
           if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) || 
                  ($domdefaults{'auth_def'} eq 'localauth'))) {
               $warningmsg = &mt('Although account creation has been set to be available for institutional logins, currently default authentication in this domain has not been set to support this.').' '.
                             &mt('You need to set the default authentication type to Kerberos 4 or 5 (with a Kerberos domain specified), or to Local authentication, if the localauth module has been customized in your domain to authenticate institutional logins.');
           }
       }
       my @fields = ('lastname','firstname','middlename','generation',
                     'permanentemail','id');
       my @shibfields = (@fields,'inststatus');
       my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
   #
   # Where usernames may created for institutional log-in and/or institutional single sign on:
   # (a) populate $cancreate{'statustocreate'} array reference with institutional status types who
   # may self-create accounts 
   # (b) populate $save_usermodify{'selfcreate'} hash reference with status types, and information fields
   # which the user may supply, if institutional data is unavailable.
   #
       if (($env{'form.cancreate_login'}) || ($env{'form.cancreate_sso'})) {
           if (ref($types) eq 'ARRAY') {
               if (@{$types} > 1) {
                   @{$cancreate{'statustocreate'}} = &Apache::loncommon::get_env_multiple('form.statustocreate');
                   push(@contexts,'statustocreate');
               } else {
                   undef($cancreate{'statustocreate'});
               } 
               foreach my $type (@{$types}) {
                   my @modifiable =  &Apache::loncommon::get_env_multiple('form.canmodify_'.$type);
                   foreach my $field (@fields) {
                       if (grep(/^\Q$field\E$/,@modifiable)) {
                           $save_usermodify{'selfcreate'}{$type}{$field} = 1;
                       } else {
                           $save_usermodify{'selfcreate'}{$type}{$field} = 0;
                       }
                   }
               }
               if (ref($curr_usermodify{'selfcreate'}) eq 'HASH') {
                   foreach my $type (@{$types}) {
                       if (ref($curr_usermodify{'selfcreate'}{$type}) eq 'HASH') {
                           foreach my $field (@fields) {
                               if ($save_usermodify{'selfcreate'}{$type}{$field} ne
                                   $curr_usermodify{'selfcreate'}{$type}{$field}) {
                                   push(@{$changes{'selfcreate'}},$type);
                                   last;
                               }
                           }
                       }
                   }
               } else {
                   foreach my $type (@{$types}) {
                       push(@{$changes{'selfcreate'}},$type);
                   }
               }
           }
           foreach my $field (@shibfields) {
               if ($env{'form.shibenv_'.$field} ne '') {
                   $cancreate{'shibenv'}{$field} = $env{'form.shibenv_'.$field};
               }
           }
           if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {
               if (ref($curr_usercreation{'cancreate'}{'shibenv'}) eq 'HASH') {
                   foreach my $field (@shibfields) {
                       if ($env{'form.shibenv_'.$field} ne $curr_usercreation{'cancreate'}{'shibenv'}{$field}) {
                           push(@{$changes{'cancreate'}},'shibenv');
                       }
                   }
               } else {
                   foreach my $field (@shibfields) {
                       if ($env{'form.shibenv_'.$field}) {
                           push(@{$changes{'cancreate'}},'shibenv');
                           last;
                       }
                   }
               }
           }
       }
       foreach my $item (@contexts) {
           if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') {
               foreach my $curr (@{$curr_usercreation{'cancreate'}{$item}}) {
                   if (ref($cancreate{$item}) eq 'ARRAY') {
                       if (!grep(/^$curr$/,@{$cancreate{$item}})) {
                           if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                               push(@{$changes{'cancreate'}},$item);
                           }
                       }
                   }
               }
               if (ref($cancreate{$item}) eq 'ARRAY') {
                   foreach my $type (@{$cancreate{$item}}) {
                       if (!grep(/^$type$/,@{$curr_usercreation{'cancreate'}{$item}})) {
                           if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                               push(@{$changes{'cancreate'}},$item);
                           }
                       }
                   }
               }
           } elsif (ref($curr_usercreation{'cancreate'}{$item}) eq 'HASH') {
               if (ref($cancreate{$item}) eq 'HASH') {
                   foreach my $curr (keys(%{$curr_usercreation{'cancreate'}{$item}})) {
                       if (ref($curr_usercreation{'cancreate'}{$item}{$curr}) eq 'HASH') {
                           foreach my $field (keys(%{$curr_usercreation{'cancreate'}{$item}{$curr}})) {
                               unless ($curr_usercreation{'cancreate'}{$item}{$curr}{$field} eq $cancreate{$item}{$curr}{$field}) {
                                   if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                       push(@{$changes{'cancreate'}},$item);
                                   }
                               }
                           }
                       } elsif ($item eq 'selfcreateprocessing') {
                           if ($cancreate{$item}{$curr} ne $curr_usercreation{'cancreate'}{$item}{$curr}) {
                               if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                   push(@{$changes{'cancreate'}},$item);
                               }
                           }
                       } else {
                           if (!$cancreate{$item}{$curr}) {
                               if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                   push(@{$changes{'cancreate'}},$item);
                               }
                           }
                       }
                   }
                   foreach my $field (keys(%{$cancreate{$item}})) {
                       if (ref($cancreate{$item}{$field}) eq 'HASH') {
                           foreach my $inner (keys(%{$cancreate{$item}{$field}})) {
                               if (ref($curr_usercreation{'cancreate'}{$item}{$field}) eq 'HASH') {
                                   unless ($curr_usercreation{'cancreate'}{$item}{$field}{$inner} eq $cancreate{$item}{$field}{$inner}) {
                                       if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                           push(@{$changes{'cancreate'}},$item);
                                       }
                                   }
                               } else {
                                   if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                       push(@{$changes{'cancreate'}},$item);
                                   }
                               }
                           }
                       } elsif ($item eq 'selfcreateprocessing') {
                           if ($cancreate{$item}{$field} ne $curr_usercreation{'cancreate'}{$item}{$field}) {
                               if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                   push(@{$changes{'cancreate'}},$item);
                               }
                           }
                       } else {
                           if (!$curr_usercreation{'cancreate'}{$item}{$field}) {
                               if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                   push(@{$changes{'cancreate'}},$item);
                               }
                           }
                       }
                   }
               }
           } elsif ($curr_usercreation{'cancreate'}{$item}) {
               if (ref($cancreate{$item}) eq 'ARRAY') {
                   if (!grep(/^\Q$curr_usercreation{'cancreate'}{$item}\E$/,@{$cancreate{$item}})) {
                       if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                           push(@{$changes{'cancreate'}},$item);
                       }
                   }
               } elsif (ref($cancreate{$item}) eq 'HASH') {
                   if (!$cancreate{$item}{$curr_usercreation{'cancreate'}{$item}}) {
                       if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                           push(@{$changes{'cancreate'}},$item);
                       }
                   }
               }
           } elsif ($item eq 'emailusername') {
               if (ref($cancreate{$item}) eq 'HASH') {
                   foreach my $type (keys(%{$cancreate{$item}})) {
                       if (ref($cancreate{$item}{$type}) eq 'HASH') {
                           foreach my $field (keys(%{$cancreate{$item}{$type}})) {
                               if ($cancreate{$item}{$type}{$field}) {
                                   if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                       push(@{$changes{'cancreate'}},$item);
                                   }
                                   last;
                               }
                           }
                       }
                   }
               }
           }
       }
   #
   # Populate %save_usercreate hash with updates to self-creation configuration.
   #
       $save_usercreate{'cancreate'}{'captcha'} = $savecaptcha{'captcha'};
       $save_usercreate{'cancreate'}{'recaptchakeys'} = $savecaptcha{'recaptchakeys'};
       $save_usercreate{'cancreate'}{'selfcreate'} = $cancreate{'selfcreate'};
       if (ref($cancreate{'notify'}) eq 'HASH') {
           $save_usercreate{'cancreate'}{'notify'} = $cancreate{'notify'};
       }
       if (ref($cancreate{'selfcreateprocessing'}) eq 'HASH') {
           $save_usercreate{'cancreate'}{'selfcreateprocessing'} = $cancreate{'selfcreateprocessing'};
       }
       if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {
           $save_usercreate{'cancreate'}{'statustocreate'} = $cancreate{'statustocreate'};
       }
       if (ref($cancreate{'shibenv'}) eq 'HASH') {
           $save_usercreate{'cancreate'}{'shibenv'} = $cancreate{'shibenv'};
       }
       $save_usercreate{'cancreate'}{'emailusername'} = $cancreate{'emailusername'};
       $save_usercreate{'emailrule'} = \@email_rule;
   
       my %userconfig_hash = (
               usercreation     => \%save_usercreate,
               usermodification => \%save_usermodify,
       );
       my $putresult = &Apache::lonnet::put_dom('configuration',\%userconfig_hash,
                                                $dom);
   #
   # Accumulate details of changes to domain cofiguration for self-creation of usernames in $resulttext
   #
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if (ref($changes{'cancreate'}) eq 'ARRAY') {              if (ref($changes{'cancreate'}) eq 'ARRAY') {
                 my %lt = &usercreation_types();                  my %lt = &selfcreation_types();
                 foreach my $type (@{$changes{'cancreate'}}) {                  foreach my $type (@{$changes{'cancreate'}}) {
                     my $chgtext;                      my $chgtext;
                     unless ($type eq 'statustocreate') {  
                         $chgtext = $lt{$type}.', ';  
                     }  
                     if ($type eq 'selfcreate') {                      if ($type eq 'selfcreate') {
                         if (@{$cancreate{$type}} == 0) {                          if (@{$cancreate{$type}} == 0) {
                             $chgtext .= &mt('creation of a new user account is not permitted.');                              $chgtext .= &mt('Self creation of a new user account is not permitted.');
                         } else {                          } else {
                             $chgtext .= &mt('creation of a new account is permitted for:').'<ul>';                              $chgtext .= &mt('Self-creation of a new account is permitted for:').
                                           '<ul>';
                             foreach my $case (@{$cancreate{$type}}) {                              foreach my $case (@{$cancreate{$type}}) {
                                 $chgtext .= '<li>'.$selfcreatetypes{$case}.'</li>';                                  $chgtext .= '<li>'.$selfcreatetypes{$case}.'</li>';
                             }                              }
Line 5744  sub modify_usercreation { Line 8818  sub modify_usercreation {
                                 if (grep(/^(login|sso)$/,@{$cancreate{$type}})) {                                  if (grep(/^(login|sso)$/,@{$cancreate{$type}})) {
                                     if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {                                      if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {
                                         if (@{$cancreate{'statustocreate'}} == 0) {                                          if (@{$cancreate{'statustocreate'}} == 0) {
                                             $chgtext .= '<br /><span class="LC_warning">'.&mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").'</span>';                                              $chgtext .= '<br />'.
                                                           '<span class="LC_warning">'.
                                                           &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").
                                                           '</span>';
                                         }                                          }
                                     }                                      }
                                 }                                  }
                             }                              }
                         }                          }
                       } elsif ($type eq 'shibenv') {
                           if (keys(%{$cancreate{$type}}) == 0) {
                               $chgtext .= &mt('Shibboleth-autheticated user does not use environment variables to set user information'); 
                           } else {
                               $chgtext .= &mt('Shibboleth-autheticated user information set from environment variables, as follows:').
                                           '<ul>';
                               foreach my $field (@shibfields) {
                                   next if ($cancreate{$type}{$field} eq '');
                                   if ($field eq 'inststatus') {
                                       $chgtext .= '<li>'.&mt('Institutional status').' -- '.$cancreate{$type}{$field}.'</li>';
                                   } else {
                                       $chgtext .= '<li>'.$fieldtitles{$field}.' -- '.$cancreate{$type}{$field}.'</li>';
                                   }
                               }
                               $chgtext .= '</ul>';
                           }  
                     } elsif ($type eq 'statustocreate') {                      } elsif ($type eq 'statustocreate') {
                         if ((ref($cancreate{'selfcreate'}) eq 'ARRAY') &&                          if ((ref($cancreate{'selfcreate'}) eq 'ARRAY') &&
                             (ref($cancreate{'statustocreate'}) eq 'ARRAY')) {                              (ref($cancreate{'statustocreate'}) eq 'ARRAY')) {
                             if (@{$cancreate{'selfcreate'}} > 0) {                              if (@{$cancreate{'selfcreate'}} > 0) {
                                 if (@{$cancreate{'statustocreate'}} == 0) {                                  if (@{$cancreate{'statustocreate'}} == 0) {
   
                                     $chgtext .= &mt("Institutional affiliations permitted to create accounts set to 'None'.");                                      $chgtext .= &mt("Institutional affiliations permitted to create accounts set to 'None'.");
                                     if (!grep(/^email$/,@{$cancreate{'selfcreate'}})) {                                      if (!grep(/^email$/,@{$cancreate{'selfcreate'}})) {
                                         $chgtext .= '<br /><span class="LC_warning">'.&mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").'</span>';                                          $chgtext .= '<br />'.
                                     }                                                       '<span class="LC_warning">'.
                                                       &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").
                                                       '</span>';
                                       }
                                 } elsif (ref($usertypes) eq 'HASH') {                                  } elsif (ref($usertypes) eq 'HASH') {
                                     if (grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {                                      if (grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {
                                         $chgtext .= &mt('Creation of a new account for an institutional user is restricted to the following institutional affiliation(s):');                                          $chgtext .= &mt('Creation of a new account for an institutional user is restricted to the following institutional affiliation(s):');
Line 5776  sub modify_usercreation { Line 8871  sub modify_usercreation {
                                     }                                      }
                                     $chgtext .= '</ul>';                                      $chgtext .= '</ul>';
                                     if (!grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {                                      if (!grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {
                                         $chgtext .= '<br /><span class="LC_warning">'.&mt('However, users authenticated by institutional login/single sign on are not currently permitted to create accounts.').'</span>';                                          $chgtext .= '<br /><span class="LC_warning">'.
                                                       &mt('However, users authenticated by institutional login/single sign on are not currently permitted to create accounts.').
                                                       '</span>';
                                     }                                      }
                                 }                                  }
                             } else {                              } else {
Line 5787  sub modify_usercreation { Line 8884  sub modify_usercreation {
                                 }                                  }
                             }                              }
                         }                          }
                     } else {                      } elsif ($type eq 'selfcreateprocessing') {
                         if ($cancreate{$type} eq 'none') {                          my %choices = &Apache::lonlocal::texthash (
                             $chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.');                                                                      automatic => 'Automatic approval',
                         } elsif ($cancreate{$type} eq 'any') {                                                                      approval  => 'Queued for approval',
                             $chgtext .= &mt('creation of new users is permitted for both institutional and non-institutional usernames.');                                                                    );
                         } elsif ($cancreate{$type} eq 'official') {                          if (@statuses > 1) {
                             $chgtext .= &mt('creation of new users is only permitted for institutional usernames.');                              $chgtext .= &mt('Processing of requests to create account with e-mail address as username set as follows:'). 
                         } elsif ($cancreate{$type} eq 'unofficial') {                                          '<ul>';
                             $chgtext .= &mt('creation of new users is only permitted for non-institutional usernames.');                             foreach my $type (@statuses) {
                                  if ($type eq 'default') {
                                      $chgtext .= '<li>'.$othertitle.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$type}}.'</li>';
                                  } else {
                                      $chgtext .= '<li>'.$usertypes->{$type}.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$type}}.'</li>';
                                  }
                              }
                              $chgtext .= '</ul>';
                           } else {
                              $chgtext .= &mt('Processing of requests to create account with e-mail address as username set to: "[_1]"',
                                            $choices{$cancreate{'selfcreateprocessing'}{'default'}});
                           }
                       } elsif ($type eq 'captcha') {
                           if ($savecaptcha{$type} eq 'notused') {
                               $chgtext .= &mt('No CAPTCHA validation in use for self-creation screen.');
                           } else {
                               my %captchas = &captcha_phrases();
                               if ($captchas{$savecaptcha{$type}}) {
                                   $chgtext .= &mt("Validation for self-creation screen set to $captchas{$savecaptcha{$type}}.");
                               } else {
                                   $chgtext .= &mt('Validation for self-creation screen set to unknown type.');
                               }
                           }
                       } elsif ($type eq 'recaptchakeys') {
                           my ($privkey,$pubkey);
                           if (ref($savecaptcha{$type}) eq 'HASH') {
                               $pubkey = $savecaptcha{$type}{'public'};
                               $privkey = $savecaptcha{$type}{'private'};
                           }
                           $chgtext .= &mt('ReCAPTCHA keys changes').'<ul>';
                           if (!$pubkey) {
                               $chgtext .= '<li>'.&mt('Public key deleted').'</li>';
                           } else {
                               $chgtext .= '<li>'.&mt('Public key set to [_1]',$pubkey).'</li>';
                           }
                           if (!$privkey) {
                               $chgtext .= '<li>'.&mt('Private key deleted').'</li>';
                           } else {
                               $chgtext .= '<li>'.&mt('Private key set to [_1]',$pubkey).'</li>';
                           }
                           $chgtext .= '</ul>';
                       } elsif ($type eq 'emailusername') {
                           if (ref($cancreate{'emailusername'}) eq 'HASH') {
                               if (ref($types) eq 'ARRAY') {
                                   foreach my $type (@{$types}) {
                                       if (ref($cancreate{'emailusername'}{$type}) eq 'HASH') {
                                           if (keys(%{$cancreate{'emailusername'}{$type}}) > 0) {
                                               $chgtext .= &mt('When self-creating account with e-mail as username, the following information will be provided by [_1]:',"'$usertypes->{$type}'").
                                                       '<ul>';
                                               foreach my $field (@{$infofields}) {
                                                   if ($cancreate{'emailusername'}{$type}{$field}) {
                                                       $chgtext .= '<li>'.$infotitles->{$field}.'</li>';
                                                   }
                                               }
                                               $chgtext .= '</ul>';
                                           } else {
                                               $chgtext .= &mt('When self creating account with e-mail as username, no information besides e-mail address will be provided by [_1].',"'$usertypes->{$type}'").'<br />';
                                           }
                                       } else {
                                           $chgtext .= &mt('When self creating account with e-mail as username, no information besides e-mail address will be provided by [_1].',"'$usertypes->{$type}'").'<br />';
                                       }
                                   }
                               }
                           }
                       } elsif ($type eq 'notify') {
                           $chgtext = &mt('No Domain Coordinators will receive notification of username requests requiring approval.');
                           if (ref($changes{'cancreate'}) eq 'ARRAY') {
                               if ((grep(/^notify$/,@{$changes{'cancreate'}})) && (ref($cancreate{'notify'}) eq 'HASH')) {
                                   if ($cancreate{'notify'}{'approval'}) {
                                       $chgtext = &mt('Notification of username requests requiring approval will be sent to: ').$cancreate{'notify'}{'approval'};
                                   }
                               }
                         }                          }
                     }                      }
                     $resulttext .= '<li>'.$chgtext.'</li>';                      if ($chgtext) {
                 }                          $resulttext .= '<li>'.$chgtext.'</li>';
             }  
             if (ref($changes{'username_rule'}) eq 'ARRAY') {  
                 my ($rules,$ruleorder) =   
                     &Apache::lonnet::inst_userrules($dom,'username');  
                 my $chgtext = '<ul>';  
                 foreach my $type (@username_rule) {  
                     if (ref($rules->{$type}) eq 'HASH') {  
                         $chgtext .= '<li>'.$rules->{$type}{'name'}.'</li>';  
                     }                      }
                 }                  }
                 $chgtext .= '</ul>';  
                 if (@username_rule > 0) {  
                     $resulttext .= '<li>'.&mt('Usernames with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';       
                 } else {  
                     $resulttext .= '<li>'.&mt('There are now no username formats restricted to verified users in the institutional directory.').'</li>';   
                 }  
             }  
             if (ref($changes{'id_rule'}) eq 'ARRAY') {  
                 my ($idrules,$idruleorder) =   
                     &Apache::lonnet::inst_userrules($dom,'id');  
                 my $chgtext = '<ul>';  
                 foreach my $type (@id_rule) {  
                     if (ref($idrules->{$type}) eq 'HASH') {  
                         $chgtext .= '<li>'.$idrules->{$type}{'name'}.'</li>';  
                     }  
                 }  
                 $chgtext .= '</ul>';  
                 if (@id_rule > 0) {  
                     $resulttext .= '<li>'.&mt('IDs with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';  
                 } else {  
                     $resulttext .= '<li>'.&mt('There are now no ID formats restricted to verified users in the institutional directory.').'</li>';  
                 }  
             }              }
             if (ref($changes{'email_rule'}) eq 'ARRAY') {              if (ref($changes{'email_rule'}) eq 'ARRAY') {
                 my ($emailrules,$emailruleorder) =                  my ($emailrules,$emailruleorder) =
Line 5844  sub modify_usercreation { Line 8982  sub modify_usercreation {
                 }                  }
                 $chgtext .= '</ul>';                  $chgtext .= '</ul>';
                 if (@email_rule > 0) {                  if (@email_rule > 0) {
                     $resulttext .= '<li>'.&mt('Accounts may not be created by users self-enrolling with e-mail addresses of the following types: ').$chgtext.'</li>';                      $resulttext .= '<li>'.
                                      &mt('Accounts may not be created by users self-enrolling with e-mail addresses of the following types: ').
                                          $chgtext.
                                      '</li>';
                 } else {                  } else {
                     $resulttext .= '<li>'.&mt('There are now no restrictions on e-mail addresses which may be used as a username when self-enrolling.').'</li>';                      $resulttext .= '<li>'.
                 }                                     &mt('There are now no restrictions on e-mail addresses which may be used as a username when self-enrolling.').
             }                                     '</li>';
                   }
             my %authname = &authtype_names();              }
             my %context_title = &context_names();              if (ref($changes{'selfcreate'}) eq 'ARRAY') {
             if (ref($changes{'authtypes'}) eq 'ARRAY') {                  $resulttext .= '<li>'.&mt('When self-creating institutional account:').'<ul>';
                 my $chgtext = '<ul>';                  my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
                 foreach my $type (@{$changes{'authtypes'}}) {                  foreach my $type (@{$changes{'selfcreate'}}) {
                     my @allowed;                      my $typename = $type;
                     $chgtext .= '<li><span class="LC_cusr_emph">'.$context_title{$type}.'</span> - '.&mt('assignable authentication types: ');                      if (ref($usertypes) eq 'HASH') {
                     foreach my $auth (@authtypes) {                          if ($usertypes->{$type} ne '') {
                         if ($authhash{$type}{$auth}) {                              $typename = $usertypes->{$type};
                             push(@allowed,$authname{$auth});                          }
                       }
                       my @modifiable;
                       $resulttext .= '<li>'.
                                       &mt('Self-creation of account by users with status: [_1]',
                                           '<span class="LC_cusr_emph">'.$typename.'</span>').
                                       ' - '.&mt('modifiable fields (if institutional data blank): ');
                       foreach my $field (@fields) {
                           if ($save_usermodify{'selfcreate'}{$type}{$field}) {
                               push(@modifiable,'<b>'.$fieldtitles{$field}.'</b>');
                         }                          }
                     }                      }
                     if (@allowed > 0) {                      if (@modifiable > 0) {
                         $chgtext .= join(', ',@allowed).'</li>';                          $resulttext .= join(', ',@modifiable);
                     } else {                      } else {
                         $chgtext .= &mt('none').'</li>';                          $resulttext .= &mt('none');
                     }                      }
                       $resulttext .= '</li>';
                 }                  }
                 $chgtext .= '</ul>';                  $resulttext .= '</ul></li>';
                 $resulttext .= '<li>'.&mt('Authentication types available for assignment to new users').'<br />'.$chgtext;  
                 $resulttext .= '</li>';  
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
             $resulttext = &mt('No changes made to user creation settings');              $resulttext = &mt('No changes made to self-creation settings');
         }          }
     } else {      } else {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
Line 5886  sub modify_usercreation { Line 9035  sub modify_usercreation {
     return $resulttext;      return $resulttext;
 }  }
   
   sub process_captcha {
       my ($container,$changes,$newsettings,$current) = @_;
       return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH') || (ref($current) eq 'HASH'));
       $newsettings->{'captcha'} = $env{'form.'.$container.'_captcha'};
       unless ($newsettings->{'captcha'} eq 'recaptcha' || $newsettings->{'captcha'} eq 'notused') {
           $newsettings->{'captcha'} = 'original';
       }
       if ($current->{'captcha'} ne $newsettings->{'captcha'}) {
           if ($container eq 'cancreate') {
               if (ref($changes->{'cancreate'}) eq 'ARRAY') {
                   push(@{$changes->{'cancreate'}},'captcha');
               } elsif (!defined($changes->{'cancreate'})) {
                   $changes->{'cancreate'} = ['captcha'];
               }
           } else {
               $changes->{'captcha'} = 1;
           }
       }
       my ($newpub,$newpriv,$currpub,$currpriv);
       if ($newsettings->{'captcha'} eq 'recaptcha') {
           $newpub = $env{'form.'.$container.'_recaptchapub'};
           $newpriv = $env{'form.'.$container.'_recaptchapriv'};
           $newpub =~ s/[^\w\-]//g;
           $newpriv =~ s/[^\w\-]//g;
           $newsettings->{'recaptchakeys'} = {
                                                public  => $newpub,
                                                private => $newpriv,
                                             };
       }
       if (ref($current->{'recaptchakeys'}) eq 'HASH') {
           $currpub = $current->{'recaptchakeys'}{'public'};
           $currpriv = $current->{'recaptchakeys'}{'private'};
           unless ($newsettings->{'captcha'} eq 'recaptcha') {
               $newsettings->{'recaptchakeys'} = {
                                                    public  => '',
                                                    private => '',
                                                 }
           }
       }
       if (($newpub ne $currpub) || ($newpriv ne $currpriv)) {
           if ($container eq 'cancreate') {
               if (ref($changes->{'cancreate'}) eq 'ARRAY') {
                   push(@{$changes->{'cancreate'}},'recaptchakeys');
               } elsif (!defined($changes->{'cancreate'})) {
                   $changes->{'cancreate'} = ['recaptchakeys'];
               }
           } else {
               $changes->{'recaptchakeys'} = 1;
           }
       }
       return;
   }
   
 sub modify_usermodification {  sub modify_usermodification {
     my ($dom,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%curr_usermodification,%changes);      my ($resulttext,%curr_usermodification,%changes,%modifyhash);
     if (ref($domconfig{'usermodification'}) eq 'HASH') {      if (ref($domconfig{'usermodification'}) eq 'HASH') {
         foreach my $key (keys(%{$domconfig{'usermodification'}})) {          foreach my $key (keys(%{$domconfig{'usermodification'}})) {
             $curr_usermodification{$key} = $domconfig{'usermodification'}{$key};              if ($key eq 'selfcreate') {
                   $modifyhash{$key} = $domconfig{'usermodification'}{$key};
               } else {  
                   $curr_usermodification{$key} = $domconfig{'usermodification'}{$key};
               }
         }          }
     }      }
     my @contexts = ('author','course','selfcreate');      my @contexts = ('author','course');
     my %context_title = (      my %context_title = (
                            author => 'In author context',                             author => 'In author context',
                            course => 'In course context',                             course => 'In course context',
                            selfcreate => 'When self creating account',   
                         );                          );
     my @fields = ('lastname','firstname','middlename','generation',      my @fields = ('lastname','firstname','middlename','generation',
                   'permanentemail','id');                    'permanentemail','id');
Line 5906  sub modify_usermodification { Line 9111  sub modify_usermodification {
                   author => ['ca','aa'],                    author => ['ca','aa'],
                   course => ['st','ep','ta','in','cr'],                    course => ['st','ep','ta','in','cr'],
                 );                  );
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
     if (ref($types) eq 'ARRAY') {  
         push(@{$types},'default');  
         $usertypes->{'default'} = $othertitle;  
     }  
     $roles{'selfcreate'} = $types;    
     my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();      my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
     my %modifyhash;  
     foreach my $context (@contexts) {      foreach my $context (@contexts) {
         foreach my $role (@{$roles{$context}}) {          foreach my $role (@{$roles{$context}}) {
             my @modifiable =  &Apache::loncommon::get_env_multiple('form.canmodify_'.$role);              my @modifiable =  &Apache::loncommon::get_env_multiple('form.canmodify_'.$role);
Line 5959  sub modify_usermodification { Line 9157  sub modify_usermodification {
                     if (ref($changes{$context}) eq 'ARRAY') {                      if (ref($changes{$context}) eq 'ARRAY') {
                         foreach my $role (@{$changes{$context}}) {                          foreach my $role (@{$changes{$context}}) {
                             my $rolename;                              my $rolename;
                             if ($context eq 'selfcreate') {                              if ($role eq 'cr') {
                                 $rolename = $role;                                  $rolename = &mt('Custom');
                                 if (ref($usertypes) eq 'HASH') {  
                                     if ($usertypes->{$role} ne '') {  
                                         $rolename = $usertypes->{$role};  
                                     }  
                                 }  
                             } else {                              } else {
                                 if ($role eq 'cr') {                                  $rolename = &Apache::lonnet::plaintext($role);
                                     $rolename = &mt('Custom');  
                                 } else {  
                                     $rolename = &Apache::lonnet::plaintext($role);  
                                 }  
                             }                              }
                             my @modifiable;                              my @modifiable;
                             if ($context eq 'selfcreate') {                              $resulttext .= '<li><span class="LC_cusr_emph">'.&mt('Target user with [_1] role',$rolename).'</span> - '.&mt('modifiable fields: ');
                                 $resulttext .= '<li><span class="LC_cusr_emph">'.&mt('Self-creation of account by users with status: [_1]',$rolename).'</span> - '.&mt('modifiable fields (if institutional data blank): ');  
                             } else {  
                                 $resulttext .= '<li><span class="LC_cusr_emph">'.&mt('Target user with [_1] role',$rolename).'</span> - '.&mt('modifiable fields: ');  
                             }  
                             foreach my $field (@fields) {                              foreach my $field (@fields) {
                                 if ($modifyhash{$context}{$role}{$field}) {                                  if ($modifyhash{$context}{$role}{$field}) {
                                     push(@modifiable,$fieldtitles{$field});                                      push(@modifiable,$fieldtitles{$field});
Line 6007  sub modify_usermodification { Line 9192  sub modify_usermodification {
 }  }
   
 sub modify_defaults {  sub modify_defaults {
     my ($dom,$r) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors);      my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors);
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
     my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def');      my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def','portal_def');
     my @authtypes = ('internal','krb4','krb5','localauth');      my @authtypes = ('internal','krb4','krb5','localauth');
     foreach my $item (@items) {      foreach my $item (@items) {
         $newvalues{$item} = $env{'form.'.$item};          $newvalues{$item} = $env{'form.'.$item};
Line 6046  sub modify_defaults { Line 9231  sub modify_defaults {
                     push(@errors,$item);                      push(@errors,$item);
                 }                  }
             }              }
           } elsif ($item eq 'portal_def') {
               if ($newvalues{$item} ne '') {
                   unless ($newvalues{$item} =~ /^https?\:\/\/(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])\/?$/) {
                       push(@errors,$item);
                   }
               }
         }          }
         if (grep(/^\Q$item\E$/,@errors)) {          if (grep(/^\Q$item\E$/,@errors)) {
             $newvalues{$item} = $domdefaults{$item};              $newvalues{$item} = $domdefaults{$item};
Line 6058  sub modify_defaults { Line 9249  sub modify_defaults {
                          defaults => \%newvalues,                           defaults => \%newvalues,
                         );                          );
     my $title = &defaults_titles();      my $title = &defaults_titles();
   
       my $currinststatus;
       if (ref($domconfig{'inststatus'}) eq 'HASH') {
           $currinststatus = $domconfig{'inststatus'};
       } else {
           my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
           $currinststatus = {
                                inststatustypes => $usertypes,
                                inststatusorder => $types,
                                inststatusguest => [],
                             };
       }
       my @todelete = &Apache::loncommon::get_env_multiple('form.inststatus_delete');
       my @allpos;
       my %guests;
       my %alltypes;
       my ($currtitles,$currguests,$currorder);
       if (ref($currinststatus) eq 'HASH') {
           if (ref($currinststatus->{'inststatusorder'}) eq 'ARRAY') {
               foreach my $type (@{$currinststatus->{'inststatusorder'}}) {
                   if (ref($currinststatus->{inststatustypes}) eq 'HASH') {
                       if ($currinststatus->{inststatustypes}->{$type} ne '') {
                           $currtitles .= $currinststatus->{inststatustypes}->{$type}.',';
                       }
                   }
                   unless (grep(/^\Q$type\E$/,@todelete)) { 
                       my $position = $env{'form.inststatus_pos_'.$type};
                       $position =~ s/\D+//g;
                       $allpos[$position] = $type;
                       $alltypes{$type} = $env{'form.inststatus_title_'.$type};
                       $alltypes{$type} =~ s/`//g;
                       if ($env{'form.inststatus_guest_'.$type}) {
                           $guests{$type} = 1;
                       }
                   }
               }
               if (ref($currinststatus->{'inststatusguest'}) eq 'ARRAY') {
                   $currguests = join(',',@{$currinststatus->{'inststatusguest'}});
               }
               $currorder = join(',',@{$currinststatus->{'inststatusorder'}});
               $currtitles =~ s/,$//;
           }
       }
       if ($env{'form.addinststatus'}) {
           my $newtype = $env{'form.addinststatus'};
           $newtype =~ s/\W//g;
           unless (exists($alltypes{$newtype})) {
               if ($env{'form.addinststatus_guest'}) {
                   $guests{$newtype} = 1;
               }
               $alltypes{$newtype} = $env{'form.addinststatus_title'};
               $alltypes{$newtype} =~ s/`//g; 
               my $position = $env{'form.addinststatus_pos'};
               $position =~ s/\D+//g;
               if ($position ne '') {
                   $allpos[$position] = $newtype;
               }
           }
       }
       my (@orderedstatus,@orderedguests);
       foreach my $type (@allpos) {
           unless (($type eq '') || (grep(/^\Q$type\E$/,@orderedstatus))) {
               push(@orderedstatus,$type);
               if ($guests{$type}) {
                   push(@orderedguests,$type);
               }
           }
       }
       foreach my $type (keys(%alltypes)) {
           unless (grep(/^\Q$type\E$/,@orderedstatus)) {
               delete($alltypes{$type});
           }
       }
       $defaults_hash{'inststatus'} = {
                                        inststatustypes => \%alltypes,
                                        inststatusorder => \@orderedstatus,
                                        inststatusguest => \@orderedguests,
                                      };
       if (ref($defaults_hash{'inststatus'}) eq 'HASH') {
           foreach my $item ('inststatustypes','inststatusorder','inststatusguest') {
               $domdefaults{$item} = $defaults_hash{'inststatus'}{$item};
           }
       }
       if ($currorder ne join(',',@orderedstatus)) {
           $changes{'inststatus'}{'inststatusorder'} = 1;
       }
       if ($currguests ne join(',',@orderedguests)) {
           $changes{'inststatus'}{'inststatusguest'} = 1;
       }
       my $newtitles;
       foreach my $item (@orderedstatus) {
           $newtitles .= $alltypes{$item}.',';
       }
       $newtitles =~ s/,$//;
       if ($currtitles ne $newtitles) {
           $changes{'inststatus'}{'inststatustypes'} = 1;
       }
     my $putresult = &Apache::lonnet::put_dom('configuration',\%defaults_hash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%defaults_hash,
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             my $version = $r->dir_config('lonVersion');              my $version = &Apache::lonnet::get_server_loncaparev($dom);
             my $mailmsgtext = "Changes made to domain settings in a LON-CAPA installation - domain: $dom (running version: $version) - dns_domain.tab needs to be updated with the following changes, to support legacy 2.4, 2.5 and 2.6 versions of LON-CAPA.\n\n";              my $mailmsgtext = "Changes made to domain settings in a LON-CAPA installation - domain: $dom (running version: $version) - dns_domain.tab needs to be updated with the following changes, to support legacy 2.4, 2.5 and 2.6 versions of LON-CAPA.\n\n";
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
                 my $value = $env{'form.'.$item};                  if ($item eq 'inststatus') {
                 if ($value eq '') {                      if (ref($changes{'inststatus'}) eq 'HASH') {
                     $value = &mt('none');                          if (($changes{'inststatus'}{'inststatustypes'}) || $changes{'inststatus'}{'inststatusorder'}) {
                 } elsif ($item eq 'auth_def') {                              $resulttext .= '<li>'.&mt('Institutional user status types set to:').' ';
                     my %authnames = &authtype_names();                              foreach my $type (@orderedstatus) { 
                     my %shortauth = (                                  $resulttext .= $alltypes{$type}.', ';
                              internal => 'int',                              }
                              krb4 => 'krb4',                              $resulttext =~ s/, $//;
                              krb5 => 'krb5',                              $resulttext .= '</li>';
                              localauth  => 'loc',                          }
                     );                          if ($changes{'inststatus'}{'inststatusguest'}) {
                     $value = $authnames{$shortauth{$value}};                              $resulttext .= '<li>'; 
                               if (@orderedguests) {
                                   $resulttext .= &mt('Types assignable to "non-institutional" usernames set to:').' ';
                                   foreach my $type (@orderedguests) {
                                       $resulttext .= $alltypes{$type}.', ';
                                   }
                                   $resulttext =~ s/, $//;
                               } else {
                                   $resulttext .= &mt('Types assignable to "non-institutional" usernames set to none.');
                               }
                               $resulttext .= '</li>';
                           }
                       }
                   } else {
                       my $value = $env{'form.'.$item};
                       if ($value eq '') {
                           $value = &mt('none');
                       } elsif ($item eq 'auth_def') {
                           my %authnames = &authtype_names();
                           my %shortauth = (
                                             internal   => 'int',
                                             krb4       => 'krb4',
                                             krb5       => 'krb5',
                                             localauth  => 'loc',
                           );
                           $value = $authnames{$shortauth{$value}};
                       }
                       $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$item},$value).'</li>';
                       $mailmsgtext .= "$title->{$item} set to $value\n";  
                 }                  }
                 $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$item},$value).'</li>';  
                 $mailmsgtext .= "$title->{$item} set to $value\n";    
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
             $mailmsgtext .= "\n";              $mailmsgtext .= "\n";
             my $cachetime = 24*60*60;              my $cachetime = 24*60*60;
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);              &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
               }
             if ($changes{'auth_def'} || $changes{'auth_arg_def'} || $changes{'lang_def'} || $changes{'datelocale_def'}) {              if ($changes{'auth_def'} || $changes{'auth_arg_def'} || $changes{'lang_def'} || $changes{'datelocale_def'}) {
                 my $sysmail = $r->dir_config('lonSysEMail');                  my $notify = 1;
                 &Apache::lonmsg::sendemail($sysmail,"LON-CAPA Domain Settings Change - $dom",$mailmsgtext);                  if (ref($domconfig{'contacts'}) eq 'HASH') {
                       if ($domconfig{'contacts'}{'reportupdates'} == 0) {
                           $notify = 0;
                       }
                   }
                   if ($notify) {
                       &Apache::lonmsg::sendemail('installrecord@loncapa.org',
                                                  "LON-CAPA Domain Settings Change - $dom",
                                                  $mailmsgtext);
                   }
             }              }
         } else {          } else {
             $resulttext = &mt('No changes made to default authentication/language/timezone settings');              $resulttext = &mt('No changes made to default authentication/language/timezone settings');
Line 6108  sub modify_defaults { Line 9434  sub modify_defaults {
 }  }
   
 sub modify_scantron {  sub modify_scantron {
     my ($r,$dom,$confname,%domconfig) = @_;      my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
     my ($resulttext,%confhash,%changes,$errors);      my ($resulttext,%confhash,%changes,$errors);
     my $custom = 'custom.tab';      my $custom = 'custom.tab';
     my $default = 'default.tab';      my $default = 'default.tab';
Line 6169  sub modify_scantron { Line 9495  sub modify_scantron {
                 }                  }
                 $resulttext .= '</ul>';                  $resulttext .= '</ul>';
                 &Apache::loncommon::devalidate_domconfig_cache($dom);                  &Apache::loncommon::devalidate_domconfig_cache($dom);
                   if (ref($lastactref) eq 'HASH') {
                       $lastactref->{'domainconfig'} = 1;
                   }
             } else {              } else {
                 $resulttext = &mt('No changes made to bubblesheet format file');                  $resulttext = &mt('No changes made to bubblesheet format file');
             }              }
Line 6187  sub modify_scantron { Line 9516  sub modify_scantron {
 }  }
   
 sub modify_coursecategories {  sub modify_coursecategories {
     my ($dom,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,%deletions,%reorderings,%needreordering,%adds,%changes,$errors,      my ($resulttext,%deletions,%reorderings,%needreordering,%adds,%changes,$errors,
         $cathash);          $cathash);
     my @deletecategory = &Apache::loncommon::get_env_multiple('form.deletecategory');      my @deletecategory = &Apache::loncommon::get_env_multiple('form.deletecategory');
       my @catitems = ('unauth','auth');
       my @cattypes = ('std','domonly','codesrch','none');
     if (ref($domconfig{'coursecategories'}) eq 'HASH') {      if (ref($domconfig{'coursecategories'}) eq 'HASH') {
         $cathash = $domconfig{'coursecategories'}{'cats'};          $cathash = $domconfig{'coursecategories'}{'cats'};
         if ($domconfig{'coursecategories'}{'togglecats'} ne $env{'form.togglecats'}) {          if ($domconfig{'coursecategories'}{'togglecats'} ne $env{'form.togglecats'}) {
Line 6209  sub modify_coursecategories { Line 9540  sub modify_coursecategories {
             $changes{'categorizecomm'} = 1;              $changes{'categorizecomm'} = 1;
             $domconfig{'coursecategories'}{'categorizecomm'} = $env{'form.categorizecomm'};              $domconfig{'coursecategories'}{'categorizecomm'} = $env{'form.categorizecomm'};
         }          }
           foreach my $item (@catitems) {
               if (grep(/^\Q$env{'form.coursecat_'.$item}\E$/,@cattypes)) {
                   if ($domconfig{'coursecategories'}{$item} ne $env{'form.coursecat_'.$item}) {
                       $changes{$item} = 1;
                       $domconfig{'coursecategories'}{$item} = $env{'form.coursecat_'.$item};
                   }
               }
           }
     } else {      } else {
         $changes{'togglecats'} = 1;          $changes{'togglecats'} = 1;
         $changes{'categorize'} = 1;          $changes{'categorize'} = 1;
Line 6220  sub modify_coursecategories { Line 9559  sub modify_coursecategories {
                                              togglecatscomm => $env{'form.togglecatscomm'},                                               togglecatscomm => $env{'form.togglecatscomm'},
                                              categorizecomm => $env{'form.categorizecomm'},                                               categorizecomm => $env{'form.categorizecomm'},
                                          };                                           };
           foreach my $item (@catitems) {
               if ($env{'form.coursecat_'.$item} ne 'std') {
                   $changes{$item} = 1;
               }
               if (grep(/^\Q$env{'form.coursecat_'.$item}\E$/,@cattypes)) {
                   $domconfig{'coursecategories'}{$item} = $env{'form.coursecat_'.$item};
               }
           }
     }      }
     if (ref($cathash) eq 'HASH') {      if (ref($cathash) eq 'HASH') {
         if (($domconfig{'coursecategories'}{'cats'}{'instcode::0'} ne '')  && ($env{'form.instcode'} == 0)) {          if (($domconfig{'coursecategories'}{'cats'}{'instcode::0'} ne '')  && ($env{'form.instcode'} == 0)) {
Line 6342  sub modify_coursecategories { Line 9689  sub modify_coursecategories {
                          dom  => 'set in Domain ("Modify Course/Community")',                           dom  => 'set in Domain ("Modify Course/Community")',
                          crs  => 'set in Course ("Course Configuration")',                           crs  => 'set in Course ("Course Configuration")',
                          comm => 'set in Community ("Community Configuration")',                           comm => 'set in Community ("Community Configuration")',
                            none     => 'No catalog',
                            std      => 'Standard catalog',
                            domonly  => 'Domain-only catalog',
                            codesrch => 'Code search form',
                         );                          );
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if ($changes{'togglecats'}) {              if ($changes{'togglecats'}) {
Line 6356  sub modify_coursecategories { Line 9707  sub modify_coursecategories {
             if ($changes{'categorizecomm'}) {              if ($changes{'categorizecomm'}) {
                 $resulttext .= '<li>'.&mt("$title{'categorizecomm'} $level{$env{'form.categorizecomm'}}").'</li>';                  $resulttext .= '<li>'.&mt("$title{'categorizecomm'} $level{$env{'form.categorizecomm'}}").'</li>';
             }              }
               if ($changes{'unauth'}) {
                   $resulttext .= '<li>'.&mt('Catalog type for unauthenticated users set to "'.$level{$env{'form.coursecat_unauth'}}.'"').'</li>';
               }
               if ($changes{'auth'}) {
                   $resulttext .= '<li>'.&mt('Catalog type for authenticated users set to "'.$level{$env{'form.coursecat_auth'}}.'"').'</li>';
               }
             if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {              if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {
                 my $cathash;                  my $cathash;
                 if (ref($domconfig{'coursecategories'}) eq 'HASH') {                  if (ref($domconfig{'coursecategories'}) eq 'HASH') {
Line 6400  sub modify_coursecategories { Line 9757  sub modify_coursecategories {
                 }                  }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
               if ($changes{'unauth'} || $changes{'auth'}) {
                   my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
                   if ($changes{'auth'}) {
                       $domdefaults{'catauth'} = $domconfig{'coursecategories'}{'auth'};
                   }
                   if ($changes{'unauth'}) {
                       $domdefaults{'catunauth'} = $domconfig{'coursecategories'}{'unauth'};
                   }
                   my $cachetime = 24*60*60;
                   &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
                   if (ref($lastactref) eq 'HASH') {
                       $lastactref->{'domdefaults'} = 1;
                   }
               }
         } else {          } else {
             $resulttext = '<span class="LC_error">'.              $resulttext = '<span class="LC_error">'.
                           &mt('An error occurred: [_1]',$putresult).'</span>';                            &mt('An error occurred: [_1]',$putresult).'</span>';
Line 6462  sub modify_serverstatuses { Line 9833  sub modify_serverstatuses {
     my %serverstatushash =  (      my %serverstatushash =  (
                                 serverstatuses => \%newserverstatus,                                  serverstatuses => \%newserverstatus,
                             );                              );
     my %changes;  
     foreach my $type (@pages) {      foreach my $type (@pages) {
         foreach my $setting ('namedusers','machines') {          foreach my $setting ('namedusers','machines') {
             my (@current,@new);              my (@current,@new);
Line 6537  sub modify_serverstatuses { Line 9907  sub modify_serverstatuses {
   
 sub modify_helpsettings {  sub modify_helpsettings {
     my ($r,$dom,$confname,%domconfig) = @_;      my ($r,$dom,$confname,%domconfig) = @_;
   my ($resulttext,$errors,%changes,%helphash);      my ($resulttext,$errors,%changes,%helphash);
        my %defaultchecked = ('submitbugs' => 'on');
   my $customhelpfile  = $env{'form.loginhelpurl.filename'};      my @offon = ('off','on');
     my $defaulthelpfile = 'defaulthelp.html';  
   my $servadm = $r->dir_config('lonAdmEMail');  
     my ($configuserok,$author_ok,$switchserver) =   
         &config_check($dom,$confname,$servadm);  
    
   my %defaultchecked = ('submitbugs' => 'on');  
   my @offon = ('off','on');  
     my %title = ( submitbugs     => 'Display link for users to submit a bug',   
      loginhelpurl  => 'Unauthenticated login help page set to custom file');  
        
     my @toggles = ('submitbugs');      my @toggles = ('submitbugs');
   
     $helphash{'helpsettings'} = {};  
       
     if (ref($domconfig{'helpsettings'}) ne 'HASH') {  
         if ($domconfig{'helpsettings'} eq '') {  
             $domconfig{'helpsettings'} = {};  
         }  
     }  
       
     if (ref($domconfig{'helpsettings'}) eq 'HASH') {      if (ref($domconfig{'helpsettings'}) eq 'HASH') {
      
         foreach my $item (@toggles) {          foreach my $item (@toggles) {
                      if ($defaultchecked{$item} eq 'on') { 
  if ($defaultchecked{$item} eq 'on') {                   if ($domconfig{'helpsettings'}{$item} eq '') {
  if (($domconfig{'helpsettings'}{$item} eq '') &&                      if ($env{'form.'.$item} eq '0') {
  ($env{'form.'.$item} eq '0')) {                          $changes{$item} = 1;
  $changes{$item} = 1;                      }
  } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {                  } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {
  $changes{$item} = 1;                      $changes{$item} = 1;
  }                  }
  } elsif ($defaultchecked{$item} eq 'off') {              } elsif ($defaultchecked{$item} eq 'off') {
  if (($domconfig{'helpsettings'}{$item} eq '') &&                  if ($domconfig{'helpsettings'}{$item} eq '') {
  ($env{'form.'.$item} eq '1')) {                      if ($env{'form.'.$item} eq '1') {
  $changes{$item} = 1;                          $changes{$item} = 1;
  } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {                      }
  $changes{$item} = 1;                  } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {
  }                      $changes{$item} = 1;
  }                  }
  $helphash{'helpsettings'}{$item} = $env{'form.'.$item};              }
  }              if (($env{'form.'.$item} eq '0') || ($env{'form.'.$item} eq '1')) {
                   $helphash{'helpsettings'}{$item} = $env{'form.'.$item};
  if ($customhelpfile ne '') {  
  my $error;  
  if ($configuserok eq 'ok') {  
  if ($switchserver) {  
  $error = &mt("Upload of custom help file is not permitted to this server: [_1]",$switchserver);  
  } else {  
  if ($author_ok eq 'ok') {  
  my ($result,$loginhelpurl) =  
  &publishlogo($r,'upload','loginhelpurl',$dom,  
  $confname,'help','','',$customhelpfile);  
  if ($result eq 'ok') {  
  $helphash{'helpsettings'}{'loginhelpurl'} = $loginhelpurl;  
  $changes{'loginhelpurl'} = 1;  
  } else {  
  $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$customhelpfile,$result);  
  }  
  } else {  
  $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3].  Error was: [_4].",$customhelpfile,$confname,$dom,$author_ok);  
  }  
  }  
  } else {  
  $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3].  Error was: [_4].",$customhelpfile,$confname,$dom,$configuserok);  
  }  
  if ($error) {  
  &Apache::lonnet::logthis($error);  
  $errors .= '<li><span class="LC_error">'.$error.'</span></li>';  
  }  
  }  
   
         if ($domconfig{'helpsettings'}{'loginhelpurl'} ne '') {  
             if ($env{'form.loginhelpurl_del'}) {  
                 $helphash{'helpsettings'}{'loginhelpurl'} = '';  
                 $changes{'loginhelpurl'} = 1;  
             }              }
         }          }
     }      }
       
       
     my $putresult;      my $putresult;
       
     if (keys(%changes) > 0) {      if (keys(%changes) > 0) {
     $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom);          $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom);
     } else {          if ($putresult eq 'ok') {
     $putresult = 'ok';              $resulttext = &mt('Changes made:').'<ul>';
     }              foreach my $item (sort(keys(%changes))) {
                                                                if ($item eq 'submitbugs') {
     if ($putresult eq 'ok') {                      $resulttext .= '<li>'.&mt('Display link to: [_1] set to "'.$offon[$env{'form.'.$item}].'".',
         if (keys(%changes) > 0) {                                                &Apache::loncommon::modal_link('http://bugs.loncapa.org',
  $resulttext = &mt('Changes made:').'<ul>';                                                &mt('LON-CAPA bug tracker'),600,500)).'</li>';
  foreach my $item (sort(keys(%changes))) {                  }
  if ($item eq 'submitbugs') {              }
  $resulttext .= '<li>'.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'</li>';              $resulttext .= '</ul>';
  }          } else {
  if ($item eq 'loginhelpurl') {              $resulttext = &mt('No changes made to help settings');
  if ($helphash{'helpsettings'}{'loginhelpurl'} eq '') {              $errors .= '<li><span class="LC_error">'.
                         $resulttext .= '<li>'.&mt('[_1] help file removed; [_2] file will be used for the unathorized help page in this domain.',$customhelpfile,$defaulthelpfile).'</li>';                         &mt('An error occurred storing the settings: [_1]',
                     } else {                             $putresult).'</span></li>';
                         $resulttext .= '<li>'.&mt("$title{$item} [_1]",$customhelpfile).'</li>';          }
                     }  
  }  
  }  
  $resulttext .= '</ul>';  
  } else {  
  $resulttext = &mt('No changes made to help settings');  
  }  
     } else {  
         $resulttext = '<span class="LC_error">'.  
     &mt('An error occurred: [_1]',$putresult).'</span>';  
     }      }
     if ($errors) {      if ($errors) {
         $resulttext .= &mt('The following errors occurred: ').'<ul>'.          $resulttext .= '<br />'.&mt('The following errors occurred: ').'<ul>'.
                        $errors.'</ul>';                         $errors.'</ul>';
     }      }
     return $resulttext;      return $resulttext;
 }  }
   
 sub modify_coursedefaults {  sub modify_coursedefaults {
     my ($dom,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,$errors,%changes,%defaultshash);      my ($resulttext,$errors,%changes,%defaultshash);
     my %defaultchecked = ('canuse_pdfforms' => 'off');      my %defaultchecked = ('canuse_pdfforms' => 'off');
     my @offon = ('off','on');  
     my @toggles = ('canuse_pdfforms');      my @toggles = ('canuse_pdfforms');
       my @numbers = ('anonsurvey_threshold','uploadquota_official','uploadquota_unofficial',
                      'uploadquota_community','uploadquota_textbook');
       my @types = ('official','unofficial','community','textbook');
       my %staticdefaults = (
                              anonsurvey_threshold => 10,
                              uploadquota          => 500,
                            );
   
     $defaultshash{'coursedefaults'} = {};      $defaultshash{'coursedefaults'} = {};
   
Line 6679  sub modify_coursedefaults { Line 9989  sub modify_coursedefaults {
                 if (($domconfig{'coursedefaults'}{$item} eq '') &&                  if (($domconfig{'coursedefaults'}{$item} eq '') &&
                     ($env{'form.'.$item} eq '0')) {                      ($env{'form.'.$item} eq '0')) {
                     $changes{$item} = 1;                      $changes{$item} = 1;
                 } elsif ($domconfig{'coursdefaults'}{$item} ne $env{'form.'.$item}) {                  } elsif ($domconfig{'coursedefaults'}{$item} ne $env{'form.'.$item}) {
                     $changes{$item} = 1;                      $changes{$item} = 1;
                 }                  }
             } elsif ($defaultchecked{$item} eq 'off') {              } elsif ($defaultchecked{$item} eq 'off') {
Line 6692  sub modify_coursedefaults { Line 10002  sub modify_coursedefaults {
             }              }
             $defaultshash{'coursedefaults'}{$item} = $env{'form.'.$item};              $defaultshash{'coursedefaults'}{$item} = $env{'form.'.$item};
         }          }
         my $currdefresponder = $domconfig{'coursedefaults'}{'anonsurvey_threshold'};          foreach my $item (@numbers) {
         my $newdefresponder = $env{'form.anonsurvey_threshold'};              my ($currdef,$newdef);
         $newdefresponder =~ s/\D//g;              $newdef = $env{'form.'.$item};
         if ($newdefresponder eq '' || $newdefresponder < 1) {              if ($item eq 'anonsurvey_threshold') {
             $newdefresponder = 1;                  $currdef = $domconfig{'coursedefaults'}{$item};
         }                  $newdef =~ s/\D//g;
         $defaultshash{'coursedefaults'}{'anonsurvey_threshold'} = $newdefresponder;                  if ($newdef eq '' || $newdef < 1) {
         if ($currdefresponder ne $newdefresponder) {                      $newdef = 1;
             unless ($currdefresponder eq '' && $newdefresponder == 10) {                  }
                 $changes{'anonsurvey_threshold'} = 1;                  $defaultshash{'coursedefaults'}{$item} = $newdef;
               } else {
                   my ($type) = ($item =~ /^\Quploadquota_\E(\w+)$/);
                   if (ref($domconfig{'coursedefaults'}{'uploadquota'}) eq 'HASH') {
                       $currdef = $domconfig{'coursedefaults'}{'uploadquota'}{$type};
                   }
                   $newdef =~ s/[^\w.\-]//g;
                   $defaultshash{'coursedefaults'}{'uploadquota'}{$type} = $newdef;
               }
               if ($currdef ne $newdef) {
                   my $staticdef;
                   if ($item eq 'anonsurvey_threshold') {
                       unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) {
                           $changes{$item} = 1;
                       }
                   } else {
                       unless (($currdef eq '') && ($newdef == $staticdefaults{'uploadquota'})) {
                           $changes{'uploadquota'} = 1;
                       }
                   }
               }
           }
   
           my $officialcreds = $env{'form.official_credits'};
           $officialcreds =~ s/[^\d.]+//g;
           my $unofficialcreds = $env{'form.unofficial_credits'};
           $unofficialcreds =~ s/[^\d.]+//g;
           my $textbookcreds = $env{'form.textbook_credits'};
           $textbookcreds =~ s/[^\d.]+//g;
           if (ref($domconfig{'coursedefaults'}{'coursecredits'} ne 'HASH') &&
                   ($env{'form.coursecredits'} eq '1')) {
                   $changes{'coursecredits'} = 1;
           } else {
               if (($domconfig{'coursedefaults'}{'coursecredits'}{'official'} ne $officialcreds)  ||
                   ($domconfig{'coursedefaults'}{'coursecredits'}{'unofficial'} ne $unofficialcreds) ||
                   ($domconfig{'coursedefaults'}{'coursecredits'}{'textbook'} ne $textbookcreds)) {
                   $changes{'coursecredits'} = 1;
             }              }
         }          }
           $defaultshash{'coursedefaults'}{'coursecredits'} = {
               official   => $officialcreds,
               unofficial => $unofficialcreds,
               textbook   => $textbookcreds,
           }
     }      }
     my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             if ($changes{'canuse_pdfforms'}) {              my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
                 my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);              if (($changes{'canuse_pdfforms'}) || ($changes{'coursecredits'}) || 
                 $domdefaults{'canuse_pdfforms'}=$defaultshash{'coursedefaults'}{'canuse_pdfforms'};                  ($changes{'uploadquota'})) { 
                   if ($changes{'canuse_pdfforms'}) {
                       $domdefaults{'canuse_pdfforms'}=$defaultshash{'coursedefaults'}{'canuse_pdfforms'};
                   }
                   if ($changes{'coursecredits'}) {
                       if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
                           $domdefaults{'officialcredits'} =
                               $defaultshash{'coursedefaults'}{'coursecredits'}{'official'};
                           $domdefaults{'unofficialcredits'} =
                               $defaultshash{'coursedefaults'}{'coursecredits'}{'unofficial'};
                           $domdefaults{'textbookcredits'} =
                               $domdefaults{'coursedefaults'}{'coursecredits'}{'textbook'};
                       }
                   }
                   if ($changes{'uploadquota'}) {
                       if (ref($defaultshash{'coursedefaults'}{'uploadquota'}) eq 'HASH') {
                           foreach my $type (@types) {
                               $domdefaults{$type.'quota'}=$defaultshash{'coursedefaults'}{'uploadquota'}{$type};
                           }
                       }
                   }
                 my $cachetime = 24*60*60;                  my $cachetime = 24*60*60;
                 &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);                  &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
                   if (ref($lastactref) eq 'HASH') {
                       $lastactref->{'domdefaults'} = 1;
                   }
             }              }
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
Line 6724  sub modify_coursedefaults { Line 10098  sub modify_coursedefaults {
                         $resulttext .= '<li>'.&mt('Course/Community users can create/upload PDF forms set to "off"').'</li>';                          $resulttext .= '<li>'.&mt('Course/Community users can create/upload PDF forms set to "off"').'</li>';
                     }                      }
                 } elsif ($item eq 'anonsurvey_threshold') {                  } elsif ($item eq 'anonsurvey_threshold') {
                         $resulttext .= '<li>'.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'</li>';                      $resulttext .= '<li>'.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'</li>';
                 }                   } elsif ($item eq 'uploadquota') {
                       if (ref($defaultshash{'coursedefaults'}{'uploadquota'}) eq 'HASH') {
                           $resulttext .= '<li>'.&mt('Default quota for content uploaded to a course/community via Course Editor set as follows:').'<ul>'.
                                          '<li>'.&mt('Official courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'official'}.'</b>').'</li>'.
                                          '<li>'.&mt('Unofficial courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'unofficial'}.'</b>').'</li>'.
                                          '<li>'.&mt('Textbook courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'textbook'}.'</b>').'</li>'.
   
                                          '<li>'.&mt('Communities: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'community'}.'</b>').'</li>'.
                                          '</ul>'.
                                          '</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('Default quota for content uploaded via Course Editor remains default: [_1] MB',$staticdefaults{'uploadquota'}).'</li>';
                       }
                   } elsif ($item eq 'coursecredits') {
                       if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
                           if (($domdefaults{'officialcredits'} eq '') &&
                               ($domdefaults{'unofficialcredits'} eq '') &&
                               ($domdefaults{'textbookcredits'} eq '')) {
                               $resulttext .= '<li>'.&mt('Student credits not in use for courses in this domain').'</li>';
                           } else {
                               $resulttext .= '<li>'.&mt('Student credits can be set per course by a Domain Coordinator, with the following defaults applying:').'<ul>'.
                                              '<li>'.&mt('Official courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'official'}).'</li>'.
                                              '<li>'.&mt('Unofficial courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'unofficial'}).'</li>'.
                                              '<li>'.&mt('Textbook courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'textbook'}).'</li>'.
                                              '</ul>'.
                                              '</li>';
                           }
                       } else {
                           $resulttext .= '<li>'.&mt('Student credits not in use for courses in this domain').'</li>';
                       }
                   }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
Line 6738  sub modify_coursedefaults { Line 10142  sub modify_coursedefaults {
     return $resulttext;      return $resulttext;
 }  }
   
   sub modify_selfenrollment {
       my ($dom,$lastactref,%domconfig) = @_;
       my ($resulttext,$errors,%changes,%selfenrollhash,%ordered);
       my @types = ('official','unofficial','community','textbook');
       my %titles = &tool_titles();
       my %descs = &Apache::lonuserutils::selfenroll_default_descs();
       ($ordered{'admin'},my $titlesref) = &Apache::lonuserutils::get_selfenroll_titles();
       $ordered{'default'} = ['types','registered','approval','limit'];
   
       my (%roles,%shown,%toplevel);
       $roles{'0'} = &Apache::lonnet::plaintext('dc');
   
       if (ref($domconfig{'selfenrollment'}) ne 'HASH') {
           if ($domconfig{'selfenrollment'} eq '') {
               $domconfig{'selfenrollment'} = {};
           }
       }
       %toplevel = (
                     admin      => 'Configuration Rights',
                     default    => 'Default settings',
                     validation => 'Validation of self-enrollment requests',
                   );
       my ($itemsref,$namesref,$fieldsref) = &Apache::lonuserutils::selfenroll_validation_types();
   
       if (ref($ordered{'admin'}) eq 'ARRAY') {
           foreach my $item (@{$ordered{'admin'}}) {
               foreach my $type (@types) {
                   if ($env{'form.selfenrolladmin_'.$item.'_'.$type}) {
                       $selfenrollhash{'admin'}{$type}{$item} = 1;
                   } else {
                       $selfenrollhash{'admin'}{$type}{$item} = 0;
                   }
                   if (ref($domconfig{'selfenrollment'}{'admin'}) eq 'HASH') {
                       if (ref($domconfig{'selfenrollment'}{'admin'}{$type}) eq 'HASH') {
                           if ($selfenrollhash{'admin'}{$type}{$item} ne
                               $domconfig{'selfenrollment'}{'admin'}{$type}{$item})  {
                               push(@{$changes{'admin'}{$type}},$item);
                           }
                       } else {
                           if (!$selfenrollhash{'admin'}{$type}{$item}) {
                               push(@{$changes{'admin'}{$type}},$item);
                           }
                       }
                   } elsif (!$selfenrollhash{'admin'}{$type}{$item}) {
                       push(@{$changes{'admin'}{$type}},$item);
                   }
               }
           }
       }
   
       foreach my $item (@{$ordered{'default'}}) {
           foreach my $type (@types) {
               my $value = $env{'form.selfenrolldefault_'.$item.'_'.$type};
               if ($item eq 'types') {
                   unless (($value eq 'all') || ($value eq 'dom')) {
                       $value = '';
                   }
               } elsif ($item eq 'registered') {
                   unless ($value eq '1') {
                       $value = 0;
                   }
               } elsif ($item eq 'approval') {
                   unless ($value =~ /^[012]$/) {
                       $value = 0;
                   }
               } else {
                   unless (($value eq 'allstudents') || ($value eq 'selfenrolled')) {
                       $value = 'none';
                   }
               }
               $selfenrollhash{'default'}{$type}{$item} = $value;
               if (ref($domconfig{'selfenrollment'}{'default'}) eq 'HASH') {
                   if (ref($domconfig{'selfenrollment'}{'default'}{$type}) eq 'HASH') {
                       if ($selfenrollhash{'default'}{$type}{$item} ne
                            $domconfig{'selfenrollment'}{'default'}{$type}{$item})  {
                            push(@{$changes{'default'}{$type}},$item);
                       }
                   } else {
                       push(@{$changes{'default'}{$type}},$item);
                   }
               } else {
                   push(@{$changes{'default'}{$type}},$item);
               }
               if ($item eq 'limit') {
                   if (($value eq 'allstudents') || ($value eq 'selfenrolled')) {
                       $env{'form.selfenrolldefault_cap_'.$type} =~ s/\D//g;
                       if ($env{'form.selfenrolldefault_cap_'.$type} ne '') {
                           $selfenrollhash{'default'}{$type}{'cap'} = $env{'form.selfenrolldefault_cap_'.$type};
                       }
                   } else {
                       $selfenrollhash{'default'}{$type}{'cap'} = '';
                   }
                   if (ref($domconfig{'selfenrollment'}{'default'}{$type}) eq 'HASH') {
                       if ($selfenrollhash{'default'}{$type}{'cap'} ne
                            $domconfig{'selfenrollment'}{'admin'}{$type}{'cap'})  {
                            push(@{$changes{'default'}{$type}},'cap');
                       }
                   } elsif ($selfenrollhash{'default'}{$type}{'cap'} ne '') {
                       push(@{$changes{'default'}{$type}},'cap');
                   }
               }
           }
       }
   
       foreach my $item (@{$itemsref}) {
           if ($item eq 'fields') {
               my @changed;
               @{$selfenrollhash{'validation'}{$item}} = &Apache::loncommon::get_env_multiple('form.selfenroll_validation_'.$item);
               if (@{$selfenrollhash{'validation'}{$item}} > 0) {
                   @{$selfenrollhash{'validation'}{$item}} = sort(@{$selfenrollhash{'validation'}{$item}});
               }
               if (ref($domconfig{'selfenrollment'}{'validation'}) eq 'HASH') {
                   if (ref($domconfig{'selfenrollment'}{'validation'}{$item}) eq 'ARRAY') {
                       @changed = &Apache::loncommon::compare_arrays($selfenrollhash{'validation'}{$item},
                                                                     $domconfig{'selfenrollment'}{'validation'}{$item});
                   } else {
                       @changed = @{$selfenrollhash{'validation'}{$item}};
                   }
               } else {
                   @changed = @{$selfenrollhash{'validation'}{$item}};
               }
               if (@changed) {
                   if ($selfenrollhash{'validation'}{$item}) { 
                       $changes{'validation'}{$item} = join(', ',@{$selfenrollhash{'validation'}{$item}});
                   } else {
                       $changes{'validation'}{$item} = &mt('None');
                   }
               }
           } else {
               $selfenrollhash{'validation'}{$item} = $env{'form.selfenroll_validation_'.$item};
               if ($item eq 'markup') {
                  if ($env{'form.selfenroll_validation_'.$item}) {
                      $env{'form.selfenroll_validation_'.$item} =~ s/[\n\r\f]+/\s/gs;
                  }
               }
               if (ref($domconfig{'selfenrollment'}{'validation'}) eq 'HASH') {
                   if ($domconfig{'selfenrollment'}{'validation'}{$item} ne $selfenrollhash{'validation'}{$item}) {
                       $changes{'validation'}{$item} = $selfenrollhash{'validation'}{$item};
                   }
               }
           }
       }
   
       my $putresult = &Apache::lonnet::put_dom('configuration',{'selfenrollment' => \%selfenrollhash},
                                                $dom);
       if ($putresult eq 'ok') {
           if (keys(%changes) > 0) {
               my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
               $resulttext = &mt('Changes made:').'<ul>';
               foreach my $key ('admin','default','validation') {
                   if (ref($changes{$key}) eq 'HASH') {
                       $resulttext .= '<li>'.$toplevel{$key}.'<ul>';
                       if ($key eq 'validation') {
                           foreach my $item (@{$itemsref}) {
                               if (exists($changes{$key}{$item})) {
                                   if ($item eq 'markup') {
                                       $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$namesref->{$item},
                                                                 '<br /><pre>'.$changes{$key}{$item}.'</pre>').'</li>';
                                   } else {  
                                       $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$namesref->{$item},
                                                                 '<b>'.$changes{$key}{$item}.'</b>').'</li>';
                                   }
                               }
                           }
                       } else {
                           foreach my $type (@types) {
                               if ($type eq 'community') {
                                   $roles{'1'} = &mt('Community personnel');
                               } else {
                                   $roles{'1'} = &mt('Course personnel');
                               }
                               if (ref($changes{$key}{$type}) eq 'ARRAY') {
                                   if (ref($selfenrollhash{$key}{$type}) eq 'HASH') {
                                       if ($key eq 'admin') {
                                           my @mgrdc = ();
                                           if (ref($ordered{$key}) eq 'ARRAY') {
                                               foreach my $item (@{$ordered{'admin'}}) {
                                                   if (ref($selfenrollhash{$key}{$type}) eq 'HASH') { 
                                                       if ($selfenrollhash{$key}{$type}{$item} eq '0') {
                                                           push(@mgrdc,$item);
                                                       }
                                                   }
                                               }
                                               if (@mgrdc) {
                                                   $domdefaults{$type.'selfenrolladmdc'} = join(',',@mgrdc);
                                               } else {
                                                   delete($domdefaults{$type.'selfenrolladmdc'});
                                               }
                                           }
                                       } else {
                                           if (ref($ordered{$key}) eq 'ARRAY') {
                                               foreach my $item (@{$ordered{$key}}) {
                                                   if (grep(/^\Q$item\E$/,@{$changes{$key}{$type}})) {
                                                       $domdefaults{$type.'selfenroll'.$item} =
                                                           $selfenrollhash{$key}{$type}{$item};
                                                   }
                                               }
                                           }
                                       }
                                   }
                                   $resulttext .= '<li>'.$titles{$type}.'<ul>';
                                   foreach my $item (@{$ordered{$key}}) {
                                       if (grep(/^\Q$item\E$/,@{$changes{$key}{$type}})) {
                                           $resulttext .= '<li>';
                                           if ($key eq 'admin') {
                                               $resulttext .= &mt('[_1] -- management by: [_2]',$titlesref->{$item},
                                                                  '<b>'.$roles{$selfenrollhash{'admin'}{$type}{$item}}.'</b>');
                                           } else {
                                               $resulttext .= &mt('[_1] set to: [_2]',$titlesref->{$item},
                                                                  '<b>'.$descs{$item}{$selfenrollhash{'default'}{$type}{$item}}.'</b>');
                                           }
                                           $resulttext .= '</li>';
                                       }
                                   }
                                   $resulttext .= '</ul></li>';
                               }
                           }
                           $resulttext .= '</ul></li>'; 
                       }
                   }
                   if ((exists($changes{'admin'})) || (exists($changes{'default'}))) {
                       my $cachetime = 24*60*60;
                       &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
                       if (ref($lastactref) eq 'HASH') {
                           $lastactref->{'domdefaults'} = 1;
                       }
                   }
               }
               $resulttext .= '</ul>';
           } else {
               $resulttext = &mt('No changes made to self-enrollment settings');
           }
       } else {
           $resulttext = '<span class="LC_error">'.
               &mt('An error occurred: [_1]',$putresult).'</span>';
       }
       return $resulttext;
   }
   
 sub modify_usersessions {  sub modify_usersessions {
     my ($dom,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my @types = ('version','excludedomain','includedomain');      my @hostingtypes = ('version','excludedomain','includedomain');
     my @prefixes = ('remote','hosted');      my @offloadtypes = ('primary','default');
       my %types = (
                     remote => \@hostingtypes,
                     hosted => \@hostingtypes,
                     spares => \@offloadtypes,
                   );
       my @prefixes = ('remote','hosted','spares');
     my @lcversions = &Apache::lonnet::all_loncaparevs();      my @lcversions = &Apache::lonnet::all_loncaparevs();
     my (%by_ip,%by_location,@intdoms);      my (%by_ip,%by_location,@intdoms);
     &build_location_hashes(\@intdoms,\%by_ip,\%by_location);      &build_location_hashes(\@intdoms,\%by_ip,\%by_location);
Line 6750  sub modify_usersessions { Line 10399  sub modify_usersessions {
     foreach my $prefix (@prefixes) {      foreach my $prefix (@prefixes) {
         $defaultshash{'usersessions'}{$prefix} = {};          $defaultshash{'usersessions'}{$prefix} = {};
     }      }
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
     my $resulttext;      my $resulttext;
     my %iphost = &Apache::lonnet::get_iphost();      my %iphost = &Apache::lonnet::get_iphost();
     foreach my $prefix (@prefixes) {      foreach my $prefix (@prefixes) {
         foreach my $type (@types) {          next if ($prefix eq 'spares');
           foreach my $type (@{$types{$prefix}}) {
             my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};              my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
             if ($type eq 'version') {              if ($type eq 'version') {
                 my $value = $env{'form.'.$prefix.'_'.$type};                  my $value = $env{'form.'.$prefix.'_'.$type};
Line 6846  sub modify_usersessions { Line 10496  sub modify_usersessions {
             }              }
         }          }
     }      }
     if (keys(%changes) > 0) {  
       my @alldoms = &Apache::lonnet::all_domains();
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my %spareid = &current_offloads_to($dom,$domconfig{'usersessions'},\%servers);
       my $savespares;
   
       foreach my $lonhost (sort(keys(%servers))) {
           my $serverhomeID =
               &Apache::lonnet::get_server_homeID($servers{$lonhost});
           my $serverhostname = &Apache::lonnet::hostname($lonhost);
           $defaultshash{'usersessions'}{'spares'}{$lonhost} = {};
           my %spareschg;
           foreach my $type (@{$types{'spares'}}) {
               my @okspares;
               my @checked = &Apache::loncommon::get_env_multiple('form.spare_'.$type.'_'.$lonhost);
               foreach my $server (@checked) {
                   if (&Apache::lonnet::hostname($server) ne '') {
                       unless (&Apache::lonnet::hostname($server) eq $serverhostname) {
                           unless (grep(/^\Q$server\E$/,@okspares)) {
                               push(@okspares,$server);
                           }
                       }
                   }
               }
               my $new = $env{'form.newspare_'.$type.'_'.$lonhost};
               my $newspare;
               if (($new ne '') && (&Apache::lonnet::hostname($new))) {
                   unless (&Apache::lonnet::hostname($new) eq $serverhostname) {
                       $newspare = $new;
                   }
               }
               my @spares;
               if (($newspare ne '') && (!grep(/^\Q$newspare\E$/,@okspares))) {
                   @spares = sort(@okspares,$newspare);
               } else {
                   @spares = sort(@okspares);
               }
               $defaultshash{'usersessions'}{'spares'}{$lonhost}{$type} = \@spares;
               if (ref($spareid{$lonhost}) eq 'HASH') {
                   if (ref($spareid{$lonhost}{$type}) eq 'ARRAY') {
                       my @diffs = &Apache::loncommon::compare_arrays($spareid{$lonhost}{$type},\@spares);
                       if (@diffs > 0) {
                           $spareschg{$type} = 1;
                       }
                   }
               }
           }
           if (keys(%spareschg) > 0) {
               $changes{'spares'}{$lonhost} = \%spareschg;
           }
       }
   
       if (ref($domconfig{'usersessions'}) eq 'HASH') {
           if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') {
               if (ref($changes{'spares'}) eq 'HASH') {
                   if (keys(%{$changes{'spares'}}) > 0) {
                       $savespares = 1;
                   }
               }
           } else {
               $savespares = 1;
           }
       }
   
       my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');
       if ((keys(%changes) > 0) || ($savespares)) {
         my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,          my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                                  $dom);                                                   $dom);
         if ($putresult eq 'ok') {          if ($putresult eq 'ok') {
Line 6860  sub modify_usersessions { Line 10575  sub modify_usersessions {
             }              }
             my $cachetime = 24*60*60;              my $cachetime = 24*60*60;
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);              &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
             my %lt = &usersession_titles();              if (ref($lastactref) eq 'HASH') {
             $resulttext = &mt('Changes made:').'<ul>';                  $lastactref->{'domdefaults'} = 1;
             foreach my $prefix (@prefixes) {              }
                 if (ref($changes{$prefix}) eq 'HASH') {              if (keys(%changes) > 0) {
                     $resulttext .= '<li>'.$lt{$prefix}.'<ul>';                  my %lt = &usersession_titles();
                     foreach my $type (@types) {                  $resulttext = &mt('Changes made:').'<ul>';
                         if (defined($changes{$prefix}{$type})) {                  foreach my $prefix (@prefixes) {
                             my $newvalue;                      if (ref($changes{$prefix}) eq 'HASH') {
                             if (ref($defaultshash{'usersessions'}) eq 'HASH') {                          $resulttext .= '<li>'.$lt{$prefix}.'<ul>';
                                 if (ref($defaultshash{'usersessions'}{$prefix})) {                          if ($prefix eq 'spares') {
                                     if ($type eq 'version') {                              if (ref($changes{$prefix}) eq 'HASH') {
                                         $newvalue = $defaultshash{'usersessions'}{$prefix}{$type};                                  foreach my $lonhost (sort(keys(%{$changes{$prefix}}))) {
                                     } elsif (ref($defaultshash{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {                                      $resulttext .= '<li><b>'.$lonhost.'</b> ';
                                         if (@{$defaultshash{'usersessions'}{$prefix}{$type}} > 0) {                                      my $lonhostdom = &Apache::lonnet::host_domain($lonhost);
                                             $newvalue = join(', ',@{$defaultshash{'usersessions'}{$prefix}{$type}});                                      my $cachekey = &escape('spares').':'.&escape($lonhostdom);
                                       &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
                                       if (ref($changes{$prefix}{$lonhost}) eq 'HASH') {
                                           foreach my $type (@{$types{$prefix}}) {
                                               if ($changes{$prefix}{$lonhost}{$type}) {
                                                   my $offloadto = &mt('None');
                                                   if (ref($defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}) eq 'ARRAY') {
                                                       if (@{$defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}} > 0) {   
                                                           $offloadto = join(', ',@{$defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}});
                                                       }
                                                   }
                                                   $resulttext .= &mt('[_1] set to: [_2].','<i>'.$lt{$type}.'</i>',$offloadto).('&nbsp;'x3);
                                               }
                                           }
                                       }
                                       $resulttext .= '</li>';
                                   }
                               }
                           } else {
                               foreach my $type (@{$types{$prefix}}) {
                                   if (defined($changes{$prefix}{$type})) {
                                       my $newvalue;
                                       if (ref($defaultshash{'usersessions'}) eq 'HASH') {
                                           if (ref($defaultshash{'usersessions'}{$prefix})) {
                                               if ($type eq 'version') {
                                                   $newvalue = $defaultshash{'usersessions'}{$prefix}{$type};
                                               } elsif (ref($defaultshash{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {
                                                   if (@{$defaultshash{'usersessions'}{$prefix}{$type}} > 0) {
                                                       $newvalue = join(', ',@{$defaultshash{'usersessions'}{$prefix}{$type}});
                                                   }
                                               }
                                         }                                          }
                                     }                                      }
                                       if ($newvalue eq '') {
                                           if ($type eq 'version') {
                                               $resulttext .= '<li>'.&mt('[_1] set to: off',$lt{$type}).'</li>';
                                           } else {
                                               $resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';
                                           }
                                       } else {
                                           if ($type eq 'version') {
                                               $newvalue .= ' '.&mt('(or later)'); 
                                           }
                                           $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';
                                       }
                                 }                                  }
                             }                              }
                             if ($newvalue eq '') {                          }
                                 if ($type eq 'version') {                          $resulttext .= '</ul>';
                                     $resulttext .= '<li>'.&mt('[_1] set to: off',$lt{$type}).'</li>';                      }
                   }
                   $resulttext .= '</ul>';
               } else {
                   $resulttext = $nochgmsg;
               }
           } else {
               $resulttext = '<span class="LC_error">'.
                             &mt('An error occurred: [_1]',$putresult).'</span>';
           }
       } else {
           $resulttext = $nochgmsg;
       }
       return $resulttext;
   }
   
   sub modify_loadbalancing {
       my ($dom,%domconfig) = @_;
       my $primary_id = &Apache::lonnet::domain($dom,'primary');
       my $intdom = &Apache::lonnet::internet_dom($primary_id);
       my ($othertitle,$usertypes,$types) =
           &Apache::loncommon::sorted_inst_types($dom);
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my @sparestypes = ('primary','default');
       my %typetitles = &sparestype_titles();
       my $resulttext;
       my (%currbalancer,%currtargets,%currrules,%existing);
       if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
           %existing = %{$domconfig{'loadbalancing'}};
       }
       &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
                                 \%currtargets,\%currrules);
       my ($saveloadbalancing,%defaultshash,%changes);
       my ($alltypes,$othertypes,$titles) =
           &loadbalancing_titles($dom,$intdom,$usertypes,$types);
       my %ruletitles = &offloadtype_text();
       my @deletions = &Apache::loncommon::get_env_multiple('form.loadbalancing_delete');
       for (my $i=0; $i<$env{'form.loadbalancing_total'}; $i++) {
           my $balancer = $env{'form.loadbalancing_lonhost_'.$i};
           if ($balancer eq '') {
               next;
           }
           if (!exists($servers{$balancer})) {
               if (exists($currbalancer{$balancer})) {
                   push(@{$changes{'delete'}},$balancer);
               }
               next;
           }
           if ((@deletions > 0) && (grep(/^\Q$i\E$/,@deletions))) {
               push(@{$changes{'delete'}},$balancer);
               next;
           }
           if (!exists($currbalancer{$balancer})) {
               push(@{$changes{'add'}},$balancer);
           }
           $defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'} = [];
           $defaultshash{'loadbalancing'}{$balancer}{'targets'}{'default'} = [];
           $defaultshash{'loadbalancing'}{$balancer}{'rules'} = {};
           unless (ref($domconfig{'loadbalancing'}) eq 'HASH') {
               $saveloadbalancing = 1;
           }
           foreach my $sparetype (@sparestypes) {
               my @targets = &Apache::loncommon::get_env_multiple('form.loadbalancing_target_'.$i.'_'.$sparetype);
               my @offloadto;
               foreach my $target (@targets) {
                   if (($servers{$target}) && ($target ne $balancer)) {
                       if ($sparetype eq 'default') {
                           if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'}) eq 'ARRAY') {
                               next if (grep(/^\Q$target\E$/,@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'}}));
                           }
                       }
                       unless(grep(/^\Q$target\E$/,@offloadto)) {
                           push(@offloadto,$target);
                       }
                   }
                   $defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto;
               }
           }
           if (ref($currtargets{$balancer}) eq 'HASH') {
               foreach my $sparetype (@sparestypes) {
                   if (ref($currtargets{$balancer}{$sparetype}) eq 'ARRAY') {
                       my @targetdiffs = &Apache::loncommon::compare_arrays($currtargets{$balancer}{$sparetype},$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype});
                       if (@targetdiffs > 0) {
                           $changes{'curr'}{$balancer}{'targets'} = 1;
                       }
                   } elsif (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
                       if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {
                           $changes{'curr'}{$balancer}{'targets'} = 1;
                       }
                   }
               }
           } else {
               if (ref($defaultshash{'loadbalancing'}{$balancer}) eq 'HASH') {
                   foreach my $sparetype (@sparestypes) {
                       if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
                           if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {
                               $changes{'curr'}{$balancer}{'targets'} = 1;
                           }
                       }
                   }
               }
           }
           my $ishomedom;
           if (&Apache::lonnet::host_domain($balancer) eq $dom) {
               $ishomedom = 1;
           }
           if (ref($alltypes) eq 'ARRAY') {
               foreach my $type (@{$alltypes}) {
                   my $rule;
                   unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) &&
                            (!$ishomedom)) {
                       $rule = $env{'form.loadbalancing_rules_'.$i.'_'.$type};
                   }
                   if ($rule eq 'specific') {
                       $rule = $env{'form.loadbalancing_singleserver_'.$i.'_'.$type};
                   }
                   $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type} = $rule;
                   if (ref($currrules{$balancer}) eq 'HASH') {
                       if ($rule ne $currrules{$balancer}{$type}) {
                           $changes{'curr'}{$balancer}{'rules'}{$type} = 1;
                       }
                   } elsif ($rule ne '') {
                       $changes{'curr'}{$balancer}{'rules'}{$type} = 1;
                   }
               }
           }
       }
       my $nochgmsg = &mt('No changes made to Load Balancer settings.');
       if ((keys(%changes) > 0) || ($saveloadbalancing)) {
           unless (ref($defaultshash{'loadbalancing'}) eq 'HASH') {
               $defaultshash{'loadbalancing'} = {};
           }
           my $putresult = &Apache::lonnet::put_dom('configuration',
                                                    \%defaultshash,$dom);
           if ($putresult eq 'ok') {
               if (keys(%changes) > 0) {
                   my %toupdate;
                   if (ref($changes{'delete'}) eq 'ARRAY') {
                       foreach my $balancer (sort(@{$changes{'delete'}})) {
                           $resulttext .= '<li>'.&mt('Load Balancing discontinued for: [_1]',$balancer).'</li>';
                           $toupdate{$balancer} = 1;
                       }
                   }
                   if (ref($changes{'add'}) eq 'ARRAY') {
                       foreach my $balancer (sort(@{$changes{'add'}})) {
                           $resulttext .= '<li>'.&mt('Load Balancing enabled for: [_1]',$balancer);
                           $toupdate{$balancer} = 1;
                       }
                   }
                   if (ref($changes{'curr'}) eq 'HASH') {
                       foreach my $balancer (sort(keys(%{$changes{'curr'}}))) {
                           if (ref($changes{'curr'}{$balancer}) eq 'HASH') {
                               if ($changes{'curr'}{$balancer}{'targets'}) {
                                   my %offloadstr;
                                   foreach my $sparetype (@sparestypes) {
                                       if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
                                           if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {
                                               $offloadstr{$sparetype} = join(', ',@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}});
                                           }
                                       }
                                   }
                                   if (keys(%offloadstr) == 0) {
                                       $resulttext .= '<li>'.&mt("Servers to which Load Balance server offloads set to 'None', by default").'</li>';
                                   } else {
                                       my $showoffload;
                                       foreach my $sparetype (@sparestypes) {
                                           $showoffload .= '<i>'.$typetitles{$sparetype}.'</i>:&nbsp;';
                                           if (defined($offloadstr{$sparetype})) {
                                               $showoffload .= $offloadstr{$sparetype};
                                           } else {
                                               $showoffload .= &mt('None');
                                           }
                                           $showoffload .= ('&nbsp;'x3);
                                       }
                                       $resulttext .= '<li>'.&mt('By default, Load Balancer: [_1] set to offload to - [_2]',$balancer,$showoffload).'</li>';
                                   }
                               }
                           }
                           if (ref($changes{'curr'}{$balancer}{'rules'}) eq 'HASH') {
                               if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) {
                                   foreach my $type (@{$alltypes}) {
                                       if ($changes{'curr'}{$balancer}{'rules'}{$type}) {
                                           my $rule = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type};
                                           my $balancetext;
                                           if ($rule eq '') {
                                               $balancetext =  $ruletitles{'default'};
                                           } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer') ||
                                                    ($rule eq 'balancer') || ($rule eq 'offloadedto')) {
                                               $balancetext =  $ruletitles{$rule};
                                               if (($rule eq 'balancer') || ($rule eq 'offloadedto')) {
                                                   foreach my $sparetype (@sparestypes) {
                                                       if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
                                                           map { $toupdate{$_} = 1; } (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}});
                                                       }
                                                   }
                                               }
                                           } else {
                                               $balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type});
                                           }
                                           $resulttext .= '<li>'.&mt('Load Balancer: [_1] -- balancing for [_2] set to - "[_3]"',$balancer,$titles->{$type},$balancetext).'</li>';
                                       }
                                   }
                               }
                           }
                           if (keys(%toupdate)) {
                               my %thismachine;
                               my $updatedhere;
                               my $cachetime = 60*60*24;
                               map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
                               foreach my $lonhost (keys(%toupdate)) {
                                   if ($thismachine{$lonhost}) {
                                       unless ($updatedhere) {
                                           &Apache::lonnet::do_cache_new('loadbalancing',$dom,
                                                                         $defaultshash{'loadbalancing'},
                                                                         $cachetime);
                                           $updatedhere = 1;
                                       }
                                 } else {                                  } else {
                                     $resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';                                      my $cachekey = &escape('loadbalancing').':'.&escape($dom);
                                       &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
                                 }                                  }
                             } else {  
                                 if ($type eq 'version') {  
                                     $newvalue .= ' '.&mt('(or later)');   
                                 }   
                                 $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';   
                             }                              }
                         }                          }
                     }                      }
                     $resulttext .= '</ul>';  
                 }                  }
                   if ($resulttext ne '') {
                       $resulttext = &mt('Changes made:').'<ul>'.$resulttext.'</ul>';
                   } else {
                       $resulttext = $nochgmsg;
                   }
               } else {
                   $resulttext = $nochgmsg;
             }              }
             $resulttext .= '</ul>';  
         } else {          } else {
             $resulttext = '<span class="LC_error">'.              $resulttext = '<span class="LC_error">'.
                           &mt('An error occurred: [_1]',$putresult).'</span>';                            &mt('An error occurred: [_1]',$putresult).'</span>';
         }          }
     } else {      } else {
         $resulttext =  &mt('No changes made to settings for user session hosting.');          $resulttext = $nochgmsg;
     }      }
     return $resulttext;      return $resulttext;
 }  }
Line 6941  sub recurse_cat_deletes { Line 10915  sub recurse_cat_deletes {
                 delete($coursecategories->{$subitem});                  delete($coursecategories->{$subitem});
                 $deletions->{$subitem} = 1;                  $deletions->{$subitem} = 1;
                 &recurse_cat_deletes($subitem,$coursecategories,$deletions);                  &recurse_cat_deletes($subitem,$coursecategories,$deletions);
             }    
         }  
     }  
     return;  
 }  
   
 sub dom_servers {  
     my ($dom) = @_;  
     my (%uniqservers,%servers);  
     my $primaryserver = &Apache::lonnet::hostname(&Apache::lonnet::domain($dom,'primary'));  
     my @machinedoms = &Apache::lonnet::machine_domains($primaryserver);  
     foreach my $mdom (@machinedoms) {  
         my %currservers = %servers;  
         my %server = &Apache::lonnet::get_servers($mdom);  
         %servers = (%currservers,%server);  
     }  
     my %by_hostname;  
     foreach my $id (keys(%servers)) {  
         push(@{$by_hostname{$servers{$id}}},$id);  
     }  
     foreach my $hostname (sort(keys(%by_hostname))) {  
         if (@{$by_hostname{$hostname}} > 1) {  
             my $match = 0;  
             foreach my $id (@{$by_hostname{$hostname}}) {  
                 if (&Apache::lonnet::host_domain($id) eq $dom) {  
                     $uniqservers{$id} = $hostname;  
                     $match = 1;  
                 }  
             }              }
             unless ($match) {  
                 $uniqservers{$by_hostname{$hostname}[0]} = $hostname;  
             }  
         } else {  
             $uniqservers{$by_hostname{$hostname}[0]} = $hostname;  
         }          }
     }      }
     return %uniqservers;      return;
 }  }
   
 sub get_active_dcs {  sub get_active_dcs {
     my ($dom) = @_;      my ($dom) = @_;
     my %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc']);      my $now = time;
       my %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc'],$now,$now);
     my %domcoords;      my %domcoords;
     my $numdcs = 0;      my $numdcs = 0;
     my $now = time;  
     foreach my $server (keys(%dompersonnel)) {      foreach my $server (keys(%dompersonnel)) {
         foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {          foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {
             my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user);              my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user);
             my ($end,$start) = split(':',$dompersonnel{$server}{$user});              $domcoords{$uname.':'.$udom} = $dompersonnel{$server}{$user};
             if (($end eq '') || ($end == 0) || ($end > $now)) {  
                 if ($start <= $now) {  
                     $domcoords{$uname.':'.$udom} = $dompersonnel{$server}{$user};  
                 }  
             }  
         }          }
     }      }
     return %domcoords;      return %domcoords;
 }  }
   
 sub active_dc_picker {  sub active_dc_picker {
     my ($dom,$curr_dc) = @_;      my ($dom,$numinrow,$inputtype,$name,%currhash) = @_;
     my %domcoords = &get_active_dcs($dom);       my %domcoords = &get_active_dcs($dom);
     my @dcs = sort(keys(%domcoords));      my @domcoord = keys(%domcoords);
     my $numdcs = scalar(@dcs);       if (keys(%currhash)) {
     my $datatable;          foreach my $dc (keys(%currhash)) {
     my $numinrow = 2;              unless (exists($domcoords{$dc})) {
                   push(@domcoord,$dc);
               }
           }
       }
       @domcoord = sort(@domcoord);
       my $numdcs = scalar(@domcoord);
       my $rows = 0;
       my $table;
     if ($numdcs > 1) {      if ($numdcs > 1) {
         $datatable = '<table>';          $table = '<table>';
         for (my $i=0; $i<@dcs; $i++) {          for (my $i=0; $i<@domcoord; $i++) {
             my $rem = $i%($numinrow);              my $rem = $i%($numinrow);
             if ($rem == 0) {              if ($rem == 0) {
                 if ($i > 0) {                  if ($i > 0) {
                     $datatable .= '</tr>';                      $table .= '</tr>';
                 }                  }
                 $datatable .= '<tr>';                  $table .= '<tr>';
                   $rows ++;
             }              }
             my $check = ' ';              my $check = '';
             if ($curr_dc eq '') {              if ($inputtype eq 'radio') {
                 if (!$i) {                   if (keys(%currhash) == 0) {
                     $check = ' checked="checked" ';                      if (!$i) {
                           $check = ' checked="checked"';
                       }
                   } elsif (exists($currhash{$domcoord[$i]})) {
                       $check = ' checked="checked"';
                   }
               } else {
                   if (exists($currhash{$domcoord[$i]})) {
                       $check = ' checked="checked"';
                 }                  }
             } elsif ($dcs[$i] eq $curr_dc) {  
                 $check = ' checked="checked" ';  
             }              }
             if ($i == @dcs - 1) {              if ($i == @domcoord - 1) {
                 my $colsleft = $numinrow - $rem;                  my $colsleft = $numinrow - $rem;
                 if ($colsleft > 1) {                  if ($colsleft > 1) {
                     $datatable .= '<td colspan="'.$colsleft.'">';                      $table .= '<td class="LC_left_item" colspan="'.$colsleft.'">';
                 } else {                  } else {
                     $datatable .= '<td>';                      $table .= '<td class="LC_left_item">';
                 }                  }
             } else {              } else {
                 $datatable .= '<td>';                  $table .= '<td class="LC_left_item">';
             }              }
             my ($dcname,$dcdom) = split(':',$dcs[$i]);              my ($dcname,$dcdom) = split(':',$domcoord[$i]);
             $datatable .= '<span class="LC_nobreak"><label>'.              my $user = &Apache::loncommon::plainname($dcname,$dcdom);
                           '<input type="radio" name="autocreate_xmldc"'.              $table .= '<span class="LC_nobreak"><label>'.
                           ' value="'.$dcs[$i].'"'.$check.'/>'.                        '<input type="'.$inputtype.'" name="'.$name.'"'.
                           &Apache::loncommon::plainname($dcname,$dcdom).                        ' value="'.$domcoord[$i].'"'.$check.' />'.$user;
                           '</label></span></td>';              if ($user ne $dcname.':'.$dcdom) {
                   $table .=  ' ('.$dcname.':'.$dcdom.')';
               }
               $table .= '</label></span></td>';
           }
           $table .= '</tr></table>';
       } elsif ($numdcs == 1) {
           my ($dcname,$dcdom) = split(':',$domcoord[0]);
           my $user = &Apache::loncommon::plainname($dcname,$dcdom);
           if ($inputtype eq 'radio') {
               $table = '<input type="hidden" name="'.$name.'" value="'.$domcoord[0].'" />'.$user;
               if ($user ne $dcname.':'.$dcdom) {
                   $table .=  ' ('.$dcname.':'.$dcdom.')';
               }
           } else {
               my $check;
               if (exists($currhash{$domcoord[0]})) {
                   $check = ' checked="checked"';
               }
               $table = '<span class="LC_nobreak"><label>'.
                        '<input type="checkbox" name="'.$name.'" '.
                        'value="'.$domcoord[0].'"'.$check.' />'.$user;
               if ($user ne $dcname.':'.$dcdom) {
                   $table .=  ' ('.$dcname.':'.$dcdom.')';
               }
               $table .= '</label></span>';
               $rows ++;
         }          }
         $datatable .= '</tr></table>';  
     } elsif (@dcs) {  
         $datatable .= '<input type="hidden" name="autocreate_dc" value="'.  
                       $dcs[0].'" />';  
     }      }
     return ($numdcs,$datatable);      return ($numdcs,$table,$rows);
 }  }
   
 sub usersession_titles {  sub usersession_titles {
     return &Apache::lonlocal::texthash(      return &Apache::lonlocal::texthash(
                hosted => 'Hosting of sessions for users from other domains on servers in this domain',                 hosted => 'Hosting of sessions for users from other domains on servers in this domain',
   
                remote => 'Hosting of sessions for users in this domain on servers in other domains',                 remote => 'Hosting of sessions for users in this domain on servers in other domains',
                  spares => 'Servers offloaded to, when busy',
                version => 'LON-CAPA version requirement',                 version => 'LON-CAPA version requirement',
                excludedomain => 'Allow all, but exclude specific domains',                 excludedomain => 'Allow all, but exclude specific domains',
                includedomain => 'Deny all, but include specific domains',                 includedomain => 'Deny all, but include specific domains',
                  primary => 'Primary (checked first)',
                  default => 'Default',
            );             );
 }  }
   
   sub id_for_thisdom {
       my (%servers) = @_;
       my %altids;
       foreach my $server (keys(%servers)) {
           my $serverhome = &Apache::lonnet::get_server_homeID($servers{$server});
           if ($serverhome ne $server) {
               $altids{$serverhome} = $server;
           }
       }
       return %altids;
   }
   
   sub count_servers {
       my ($currbalancer,%servers) = @_;
       my (@spares,$numspares);
       foreach my $lonhost (sort(keys(%servers))) {
           next if ($currbalancer eq $lonhost);
           push(@spares,$lonhost);
       }
       if ($currbalancer) {
           $numspares = scalar(@spares);
       } else {
           $numspares = scalar(@spares) - 1;
       }
       return ($numspares,@spares);
   }
   
   sub lonbalance_targets_js {
       my ($dom,$types,$servers,$settings) = @_;
       my $select = &mt('Select');
       my ($alltargets,$allishome,$allinsttypes,@alltypes);
       if (ref($servers) eq 'HASH') {
           $alltargets = join("','",sort(keys(%{$servers})));
           my @homedoms;
           foreach my $server (sort(keys(%{$servers}))) {
               if (&Apache::lonnet::host_domain($server) eq $dom) {
                   push(@homedoms,'1');
               } else {
                   push(@homedoms,'0');
               }
           }
           $allishome = join("','",@homedoms);
       }
       if (ref($types) eq 'ARRAY') {
           if (@{$types} > 0) {
               @alltypes = @{$types};
           }
       }
       push(@alltypes,'default','_LC_adv','_LC_author','_LC_internetdom','_LC_external');
       $allinsttypes = join("','",@alltypes);
       my (%currbalancer,%currtargets,%currrules,%existing);
       if (ref($settings) eq 'HASH') {
           %existing = %{$settings};
       }
       &get_loadbalancers_config($servers,\%existing,\%currbalancer,
                                 \%currtargets,\%currrules);
       my $balancers = join("','",sort(keys(%currbalancer)));
       return <<"END";
   
   <script type="text/javascript">
   // <![CDATA[
   
   currBalancers = new Array('$balancers');
   
   function toggleTargets(balnum) {
       var lonhostitem = document.getElementById('loadbalancing_lonhost_'+balnum);
       var prevhostitem = document.getElementById('loadbalancing_prevlonhost_'+balnum);
       var balancer = lonhostitem.options[lonhostitem.selectedIndex].value;
       var prevbalancer = prevhostitem.value;
       var baltotal = document.getElementById('loadbalancing_total').value;
       prevhostitem.value = balancer;
       if (prevbalancer != '') {
           var prevIdx = currBalancers.indexOf(prevbalancer);
           if (prevIdx != -1) {
               currBalancers.splice(prevIdx,1);
           }
       }
       if (balancer == '') {
           hideSpares(balnum);
       } else {
           var currIdx = currBalancers.indexOf(balancer);
           if (currIdx == -1) {
               currBalancers.push(balancer);
           }
           var homedoms = new Array('$allishome');
           var ishomedom = homedoms[lonhostitem.selectedIndex];
           showSpares(balancer,ishomedom,balnum);
       }
       balancerChange(balnum,baltotal,'change',prevbalancer,balancer);
       return;
   }
   
   function showSpares(balancer,ishomedom,balnum) {
       var alltargets = new Array('$alltargets');
       var insttypes = new Array('$allinsttypes');
       var offloadtypes = new Array('primary','default');
   
       document.getElementById('loadbalancing_targets_'+balnum).style.display='block';
       document.getElementById('loadbalancing_disabled_'+balnum).style.display='none';
    
       for (var i=0; i<offloadtypes.length; i++) {
           var count = 0;
           for (var j=0; j<alltargets.length; j++) {
               if (alltargets[j] != balancer) {
                   var item = document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+count);
                   item.value = alltargets[j];
                   item.style.textAlign='left';
                   item.style.textFace='normal';
                   document.getElementById('loadbalancing_targettxt_'+balnum+'_'+offloadtypes[i]+'_'+count).innerHTML = alltargets[j];
                   if (currBalancers.indexOf(alltargets[j]) == -1) {
                       item.disabled = '';
                   } else {
                       item.disabled = 'disabled';
                       item.checked = false;
                   }
                   count ++;
               }
           }
       }
       for (var k=0; k<insttypes.length; k++) {
           if ((insttypes[k] == '_LC_external') || (insttypes[k] == '_LC_internetdom')) {
               if (ishomedom == 1) {
                   document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='block';
                   document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='block';
               } else {
                   document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='none';
                   document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='none';
               }
           } else {
               document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='block';
               document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='block';
           }
           if ((insttypes[k] != '_LC_external') && 
               ((insttypes[k] != '_LC_internetdom') ||
                ((insttypes[k] == '_LC_internetdom') && (ishomedom == 1)))) {
               var item = document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]);
               item.options.length = 0;
               item.options[0] = new Option("","",true,true);
               var idx = 0;
               for (var m=0; m<alltargets.length; m++) {
                   if ((currBalancers.indexOf(alltargets[m]) == -1) && (alltargets[m] != balancer)) {
                       idx ++;
                       item.options[idx] = new Option(alltargets[m],alltargets[m],false,false);
                   }
               }
           }
       }
       return;
   }
   
   function hideSpares(balnum) {
       var alltargets = new Array('$alltargets');
       var insttypes = new Array('$allinsttypes');
       var offloadtypes = new Array('primary','default');
   
       document.getElementById('loadbalancing_targets_'+balnum).style.display='none';
       document.getElementById('loadbalancing_disabled_'+balnum).style.display='block';
   
       var total = alltargets.length - 1;
       for (var i=0; i<offloadtypes; i++) {
           for (var j=0; j<total; j++) {
              document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+j).checked = false;
              document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+j).value = '';
              document.getElementById('loadbalancing_targettxt_'+balnum+'_'+offloadtypes[i]+'_'+j).innerHTML = '';
           }
       }
       for (var k=0; k<insttypes.length; k++) {
           document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='none';
           document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='none';
           if (insttypes[k] != '_LC_external') {
               document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]).length = 0;
               document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]).options[0] = new Option("","",true,true);
           }
       }
       return;
   }
   
   function checkOffloads(item,balnum,type) {
       var alltargets = new Array('$alltargets');
       var offloadtypes = new Array('primary','default');
       if (item.checked) {
           var total = alltargets.length - 1;
           var other;
           if (type == offloadtypes[0]) {
               other = offloadtypes[1];
           } else {
               other = offloadtypes[0];
           }
           for (var i=0; i<total; i++) {
               var server = document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).value;
               if (server == item.value) {
                   if (document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).checked) {
                       document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).checked = false;
                   }
               }
           }
       }
       return;
   }
   
   function singleServerToggle(balnum,type) {
       var offloadtoSelIdx = document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).selectedIndex;
       if (offloadtoSelIdx == 0) {
           document.getElementById('loadbalancing_rules_'+balnum+'_'+type+'_0').checked = true;
           document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '';
   
       } else {
           document.getElementById('loadbalancing_rules_'+balnum+'_'+type+'_2').checked = true;
           document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '$select';
       }
       return;
   }
   
   function balanceruleChange(formname,balnum,type) {
       if (type == '_LC_external') {
           return;
       }
       var typesRules = getIndicesByName(formname,'loadbalancing_rules_'+balnum+'_'+type);
       for (var i=0; i<typesRules.length; i++) {
           if (formname.elements[typesRules[i]].checked) {
               if (formname.elements[typesRules[i]].value != 'specific') {
                   document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).selectedIndex = 0;
                   document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '';
               } else {
                   document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '$select';
               }
           }
       }
       return;
   }
   
   function balancerDeleteChange(balnum) {
       var hostitem = document.getElementById('loadbalancing_lonhost_'+balnum);
       var baltotal = document.getElementById('loadbalancing_total').value;
       var addtarget;
       var removetarget;
       var action = 'delete';
       if (document.getElementById('loadbalancing_delete_'+balnum)) {
           var lonhost = hostitem.value;
           var currIdx = currBalancers.indexOf(lonhost);
           if (document.getElementById('loadbalancing_delete_'+balnum).checked) {
               if (currIdx != -1) {
                   currBalancers.splice(currIdx,1);
               }
               addtarget = lonhost;
           } else {
               if (currIdx == -1) {
                   currBalancers.push(lonhost);
               }
               removetarget = lonhost;
               action = 'undelete';
           }
           balancerChange(balnum,baltotal,action,addtarget,removetarget);
       }
       return;
   }
   
   function balancerChange(balnum,baltotal,action,addtarget,removetarget) {
       if (baltotal > 1) {
           var offloadtypes = new Array('primary','default');
           var alltargets = new Array('$alltargets');
           var insttypes = new Array('$allinsttypes');
           for (var i=0; i<baltotal; i++) {
               if (i != balnum) {
                   for (var j=0; j<offloadtypes.length; j++) {
                       var total = alltargets.length - 1;
                       for (var k=0; k<total; k++) {
                           var serveritem = document.getElementById('loadbalancing_target_'+i+'_'+offloadtypes[j]+'_'+k);
                           var server = serveritem.value;
                           if ((action == 'delete') || (action == 'change' && addtarget != ''))  {
                               if (server == addtarget) {
                                   serveritem.disabled = '';
                               }
                           }
                           if ((action == 'undelete') || (action == 'change' && removetarget != '')) {
                               if (server == removetarget) {
                                   serveritem.disabled = 'disabled';
                                   serveritem.checked = false;
                               }
                           }
                       }
                   }
                   for (var j=0; j<insttypes.length; j++) {
                       if (insttypes[j] != '_LC_external') {
                           if (document.getElementById('loadbalancing_singleserver_'+i+'_'+insttypes[j])) {
                               var singleserver = document.getElementById('loadbalancing_singleserver_'+i+'_'+insttypes[j]);
                               var currSel = singleserver.selectedIndex;
                               var currVal = singleserver.options[currSel].value;
                               if ((action == 'delete') || (action == 'change' && addtarget != '')) {
                                   var numoptions = singleserver.options.length;
                                   var needsnew = 1;
                                   for (var k=0; k<numoptions; k++) {
                                       if (singleserver.options[k] == addtarget) {
                                           needsnew = 0;
                                           break;
                                       }
                                   }
                                   if (needsnew == 1) {
                                       singleserver.options[numoptions] = new Option(addtarget,addtarget,false,false);
                                   }
                               }
                               if ((action == 'undelete') || (action == 'change' && removetarget != '')) {
                                   singleserver.options.length = 0;
                                   if ((currVal) && (currVal != removetarget)) {
                                       singleserver.options[0] = new Option("","",false,false);
                                   } else {
                                       singleserver.options[0] = new Option("","",true,true);
                                   }
                                   var idx = 0;
                                   for (var m=0; m<alltargets.length; m++) {
                                       if (currBalancers.indexOf(alltargets[m]) == -1) {
                                           idx ++;
                                           if (currVal == alltargets[m]) {
                                               singleserver.options[idx] = new Option(alltargets[m],alltargets[m],true,true);
                                           } else {
                                               singleserver.options[idx] = new Option(alltargets[m],alltargets[m],false,false);
                                           }
                                       }
                                   }
                               }
                           }
                       }
                   }
               }
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   END
   }
   
   sub new_spares_js {
       my @sparestypes = ('primary','default');
       my $types = join("','",@sparestypes);
       my $select = &mt('Select');
       return <<"END";
   
   <script type="text/javascript">
   // <![CDATA[
   
   function updateNewSpares(formname,lonhost) {
       var types = new Array('$types');
       var include = new Array();
       var exclude = new Array();
       for (var i=0; i<types.length; i++) {
           var spareboxes = getIndicesByName(formname,'spare_'+types[i]+'_'+lonhost);
           for (var j=0; j<spareboxes.length; j++) {
               if (formname.elements[spareboxes[j]].checked) {
                   exclude.push(formname.elements[spareboxes[j]].value);
               } else {
                   include.push(formname.elements[spareboxes[j]].value);
               }
           }
       }
       for (var i=0; i<types.length; i++) {
           var newSpare = document.getElementById('newspare_'+types[i]+'_'+lonhost);
           var selIdx = newSpare.selectedIndex;
           var currnew = newSpare.options[selIdx].value;
           var okSpares = new Array();
           for (var j=0; j<newSpare.options.length; j++) {
               var possible = newSpare.options[j].value;
               if (possible != '') {
                   if (exclude.indexOf(possible) == -1) {
                       okSpares.push(possible);
                   } else {
                       if (currnew == possible) {
                           selIdx = 0;
                       }
                   }
               }
           }
           for (var k=0; k<include.length; k++) {
               if (okSpares.indexOf(include[k]) == -1) {
                   okSpares.push(include[k]);
               }
           }
           okSpares.sort();
           newSpare.options.length = 0;
           if (selIdx == 0) {
               newSpare.options[0] = new Option("$select","",true,true);
           } else {
               newSpare.options[0] = new Option("$select","",false,false);
           }
           for (var m=0; m<okSpares.length; m++) {
               var idx = m+1;
               var selThis = 0;
               if (selIdx != 0) {
                   if (okSpares[m] == currnew) {
                       selThis = 1;
                   }
               }
               if (selThis == 1) {
                   newSpare.options[idx] = new Option(okSpares[m],okSpares[m],true,true);
               } else {
                   newSpare.options[idx] = new Option(okSpares[m],okSpares[m],false,false);
               }
           }
       }
       return;
   }
   
   function checkNewSpares(lonhost,type) {
       var newSpare = document.getElementById('newspare_'+type+'_'+lonhost);
       var chosen =  newSpare.options[newSpare.selectedIndex].value;
       if (chosen != '') { 
           var othertype;
           var othernewSpare;
           if (type == 'primary') {
               othernewSpare = document.getElementById('newspare_default_'+lonhost);
           }
           if (type == 'default') {
               othernewSpare = document.getElementById('newspare_primary_'+lonhost);
           }
           if (othernewSpare.options[othernewSpare.selectedIndex].value == chosen) {
               othernewSpare.selectedIndex = 0;
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   END
   
   }
   
   sub common_domprefs_js {
       return <<"END";
   
   <script type="text/javascript">
   // <![CDATA[
   
   function getIndicesByName(formname,item) {
       var group = new Array();
       for (var i=0;i<formname.elements.length;i++) {
           if (formname.elements[i].name == item) {
               group.push(formname.elements[i].id);
           }
       }
       return group;
   }
   
   // ]]>
   </script>
   
   END
   
   }
   
   sub recaptcha_js {
       my %lt = &captcha_phrases();
       return <<"END";
   
   <script type="text/javascript">
   // <![CDATA[
   
   function updateCaptcha(caller,context) {
       var privitem;
       var pubitem;
       var privtext;
       var pubtext;
       if (document.getElementById(context+'_recaptchapub')) {
           pubitem = document.getElementById(context+'_recaptchapub');
       } else {
           return;
       }
       if (document.getElementById(context+'_recaptchapriv')) {
           privitem = document.getElementById(context+'_recaptchapriv');
       } else {
           return;
       }
       if (document.getElementById(context+'_recaptchapubtxt')) {
           pubtext = document.getElementById(context+'_recaptchapubtxt');
       } else {
           return;
       }
       if (document.getElementById(context+'_recaptchaprivtxt')) {
           privtext = document.getElementById(context+'_recaptchaprivtxt');
       } else {
           return;
       }
       if (caller.checked) {
           if (caller.value == 'recaptcha') {
               pubitem.type = 'text';
               privitem.type = 'text';
               pubitem.size = '40';
               privitem.size = '40';
               pubtext.innerHTML = "$lt{'pub'}";
               privtext.innerHTML = "$lt{'priv'}";
           } else {
               pubitem.type = 'hidden';
               privitem.type = 'hidden';
               pubtext.innerHTML = '';
               privtext.innerHTML = '';
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   END
   
   }
   
   sub toggle_display_js {
       return <<"END";
   
   <script type="text/javascript">
   // <![CDATA[
   
   function toggleDisplay(domForm,caller) {
       if (document.getElementById(caller)) {
           var divitem = document.getElementById(caller);
           var optionsElement = domForm.coursecredits;
           if (caller == 'emailoptions') {
               optionsElement = domForm.cancreate_email; 
           }
           if (optionsElement.length) {
               var currval;
               for (var i=0; i<optionsElement.length; i++) {
                   if (optionsElement[i].checked) {
                      currval = optionsElement[i].value;
                   }
               }
               if (currval == 1) {
                   divitem.style.display = 'block';
               } else {
                   divitem.style.display = 'none';
               }
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   END
   
   }
   
   sub captcha_phrases {
       return &Apache::lonlocal::texthash (
                    priv => 'Private key',
                    pub  => 'Public key',
                    original  => 'original (CAPTCHA)',
                    recaptcha => 'successor (ReCAPTCHA)',
                    notused   => 'unused',
       );
   }
   
   sub devalidate_remote_domconfs {
       my ($dom,$cachekeys) = @_;
       return unless (ref($cachekeys) eq 'HASH');
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my %thismachine;
       map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
       my @posscached = ('domainconfig','domdefaults');
       if (keys(%servers) > 1) {
           foreach my $server (keys(%servers)) {
               next if ($thismachine{$server});
               my @cached;
               foreach my $name (@posscached) {
                   if ($cachekeys->{$name}) {
                       push(@cached,&escape($name).':'.&escape($dom));
                   }
               }
               if (@cached) {
                   &Apache::lonnet::remote_devalidate_cache($server,\@cached);
               }
           }
       }
       return;
   }
   
 1;  1;

Removed from v.1.139  
changed lines
  Added in v.1.160.6.54


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>