Diff for /loncom/interface/domainprefs.pm between versions 1.51 and 1.183

version 1.51, 2008/05/15 01:56:44 version 1.183, 2013/01/09 18:14:04
Line 28 Line 28
 ###############################################################  ###############################################################
 ##############################################################  ##############################################################
   
   =pod
   
   =head1 NAME
   
   Apache::domainprefs.pm
   
   =head1 SYNOPSIS
   
   Handles configuration of a LON-CAPA domain.  
   
   This is part of the LearningOnline Network with CAPA project
   described at http://www.lon-capa.org.
   
   
   =head1 OVERVIEW
   
   Each institution using LON-CAPA will typically have a single domain designated 
   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"
   the LON-CAPA instance. In addition, an institution will typically have a language
   and timezone which are used for the majority of courses.
   
   LON-CAPA provides a mechanism to display and modify these defaults, as well as a 
   host of other domain-wide settings which determine the types of functionality
   available to users and courses in the domain.
   
   There is also a mechanism to configure cataloging of courses in the domain, and
   controls on the operation of automated processes which govern such things as
   roster updates, user directory updates and processing of course requests.
   
   The domain coordination manual which is built dynamically on install/update of 
   LON-CAPA from the relevant help items provides more information about domain 
   configuration.
   
   Most of the domain settings are stored in the configuration.db GDBM file which is
   housed on the primary library server for the domain in /home/httpd/lonUsers/$dom,
   where $dom is the domain.  The configuration.db stores settings in a number of 
   frozen hashes of hashes.  In a few cases, domain information must be uploaded to
   the domain as files (e.g., image files for logos etc., or plain text files for
   bubblesheet formats).  In this case the domainprefs.pm must be running in a user
   session hosted on the primary library server in the domain, as these files are 
   stored in author space belonging to a special $dom-domainconfig user.   
   
   domainprefs.pm in combination with lonconfigsettings.pm will retrieve and display
   the current settings, and provides an interface to make modifications.
   
   =head1 SUBROUTINES
   
   =over
   
   =item print_quotas()
   
   Inputs: 4 
   
   $dom,$settings,$rowtotal,$action.
   
   $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 
   number of rows displayed on the page, and $action is the context (quotas,  
   requestcourses or requestauthor).
   
   The print_quotas routine was orginally created to display/store information
   about default quota sizes for portfolio spaces for the different types of 
   institutional affiliation in the domain (e.g., Faculty, Staff, Student etc.), 
   but is now also used to manage availability of user tools: 
   i.e., blogs, aboutme page, and portfolios, and the course request tool,
   used by course owners to request creation of a course.
   
   Outputs: 1
   
   $datatable  - HTML containing form elements which allow settings to be changed. 
   
   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 
   (official, unofficial and community).  In each case the radio buttons allow the 
   selection of one of four values:
   
   0, approval, validate, autolimit=N (where N is blank, or a positive integer).
   which have the following effects:
   
   0
   
   =over
   
   - course requests are not allowed for this course types/affiliation
   
   =back
   
   approval 
   
   =over 
   
   - course requests must be approved by a Doman Coordinator in the 
   course's domain
   
   =back
   
   validate 
   
   =over
   
   - an institutional validation (e.g., check requestor is instructor
   of record) needs to be passed before the course will be created.  The required
   validation is in localenroll.pm on the primary library server for the course 
   domain.
   
   =back
   
   autolimit 
   
   =over
    
   - course requests will be processed automatically up to a limit of
   N requests for the course type for the particular requestor.
   If N is undefined, there is no limit to the number of course requests
   which a course owner may submit and have processed automatically. 
   
   =back
   
   =item modify_quotas() 
   
   =back
   
   =cut
   
 package Apache::domainprefs;  package Apache::domainprefs;
   
 use strict;  use strict;
Line 37  use Apache::loncommon(); Line 162  use Apache::loncommon();
 use Apache::lonhtmlcommon();  use Apache::lonhtmlcommon();
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonmsg();  use Apache::lonmsg();
 use LONCAPA;  use Apache::lonconfigsettings;
   use LONCAPA qw(:DEFAULT :match);
 use LONCAPA::Enrollment;  use LONCAPA::Enrollment;
   use LONCAPA::lonauthcgi();
 use File::Copy;  use File::Copy;
 use Locale::Language;  use Locale::Language;
   use DateTime::TimeZone;
   use DateTime::Locale;
   
   my $registered_cleanup;
   my $modified_urls;
   
 sub handler {  sub handler {
     my $r=shift;      my $r=shift;
Line 50  sub handler { Line 182  sub handler {
         return OK;          return OK;
     }      }
   
       my $context = 'domain';
     my $dom = $env{'request.role.domain'};      my $dom = $env{'request.role.domain'};
     my $domdesc = &Apache::lonnet::domain($dom,'description');      my $domdesc = &Apache::lonnet::domain($dom,'description');
     if (&Apache::lonnet::allowed('mau',$dom)) {      if (&Apache::lonnet::allowed('mau',$dom)) {
Line 60  sub handler { Line 193  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']);                                              ['phase','actions']);
     my $phase = 'pickactions';      my $phase = 'pickactions';
     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','directorysrch',                  'quotas','autoenroll','autoupdate','autocreate',
                 'usercreation','usermodification','contacts','defaults',                  'directorysrch','usercreation','usermodification',
                 'scantron','coursecategories'],$dom);                  'contacts','defaults','scantron','coursecategories',
                   'serverstatuses','requestcourses','helpsettings',
                   'coursedefaults','usersessions','loadbalancing',
                   'requestauthor'],$dom);
     my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',      my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
                        'autoupdate','directorysrch','contacts',                         'autoupdate','autocreate','directorysrch','contacts',
                        'usercreation','usermodification','scantron',                         'usercreation','usermodification','scantron',
                        'coursecategories');                         'requestcourses','requestauthor','coursecategories',
                          'serverstatuses','helpsettings',
                          'coursedefaults','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',
                      help => 'Default_Color_Schemes',                       help => 'Domain_Configuration_Color_Schemes',
                      header => [{col1 => 'Student Settings',                       header => [{col1 => 'Student Settings',
                                  col2 => '',},                                   col2 => '',},
                                 {col1 => 'Coordinator Settings',                                  {col1 => 'Coordinator Settings',
Line 89  sub handler { Line 239  sub handler {
                                 {col1 => 'Administrator Settings',                                  {col1 => 'Administrator Settings',
                                  col2 => '',}],                                   col2 => '',}],
                     },                      },
         'login' =>            'login' =>
                     { text => 'Log-in page options',                      { text => 'Log-in page options',
                       help => 'Domain_Log-in_Page',                        help => 'Domain_Configuration_Login_Page',
                       header => [{col1 => 'Item',                        header => [{col1 => 'Log-in Page Items',
                                   col2 => '',}],                                    col2 => '',},
                                    {col1 => 'Log-in Help',
                                     col2 => 'Value'}],
                     },                      },
         'defaults' =>           'defaults' => 
                     { text => 'Default authentication/language',                      { text => 'Default authentication/language/timezone/portal',
                       help => '',                        help => 'Domain_Configuration_LangTZAuth',
                       header => [{col1 => 'Setting',                        header => [{col1 => 'Setting',
                                   col2 => 'Value'}],                                    col2 => 'Value'}],
                     },                      },
         'quotas' =>           'quotas' => 
                     { text => 'Default quotas for user portfolios',                      { text => 'Blogs, personal web pages, webDAV, portfolios',
                       help => 'Default_User_Quota',                        help => 'Domain_Configuration_Quotas',
                       header => [{col1 => 'User type',                        header => [{col1 => 'User affiliation',
                                   col2 => 'Default quota'}],                                    col2 => 'Available tools',
                                     col3 => 'Portfolio quota',}],
                     },                      },
         'autoenroll' =>          'autoenroll' =>
                    { text => 'Auto-enrollment settings',                     { text => 'Auto-enrollment settings',
                      help => 'Domain_Auto_Enrollment',                       help => 'Domain_Configuration_Auto_Enrollment',
                      header => [{col1 => 'Configuration setting',                       header => [{col1 => 'Configuration setting',
                                  col2 => 'Value(s)'}],                                   col2 => 'Value(s)'}],
                    },                     },
         'autoupdate' =>           'autoupdate' => 
                    { text => 'Auto-update settings',                     { text => 'Auto-update settings',
                      help => 'Domain_Auto_Update',                       help => 'Domain_Configuration_Auto_Updates',
                      header => [{col1 => 'Setting',                       header => [{col1 => 'Setting',
                                  col2 => 'Value',},                                   col2 => 'Value',},
                                   {col1 => 'Setting',
                                    col2 => 'Affiliation'},
                                 {col1 => 'User population',                                  {col1 => 'User population',
                                  col2 => 'Updataeable user data'}],                                   col2 => 'Updateable user data'}],
                     },
           'autocreate' => 
                     { text => 'Auto-course creation settings',
                        help => 'Domain_Configuration_Auto_Creation',
                        header => [{col1 => 'Configuration Setting',
                                    col2 => 'Value',}],
                   },                    },
         'directorysrch' =>           'directorysrch' => 
                   { text => 'Institutional directory searches',                    { text => 'Institutional directory searches',
                     help => 'Domain_Directory_Search',                      help => 'Domain_Configuration_InstDirectory_Search',
                     header => [{col1 => 'Setting',                      header => [{col1 => 'Setting',
                                 col2 => 'Value',}],                                  col2 => 'Value',}],
                   },                    },
         'contacts' =>          'contacts' =>
                   { text => 'Contact Information',                    { text => 'Contact Information',
                     help => 'Domain_Contact_Information',                      help => 'Domain_Configuration_Contact_Info',
                     header => [{col1 => 'Setting',                      header => [{col1 => 'Setting',
                                 col2 => 'Value',}],                                  col2 => 'Value',}],
                   },                    },
   
         'usercreation' =>           'usercreation' => 
                   { text => 'User creation',                    { text => 'User creation',
                     help => 'Domain_User_Creation',                      help => 'Domain_Configuration_User_Creation',
                     header => [{col1 => 'Format rule type',                      header => [{col1 => 'Format rule type',
                                 col2 => 'Format rules in force'},                                  col2 => 'Format rules in force'},
                                {col1 => 'User account creation',                                 {col1 => 'User account creation',
Line 144  sub handler { Line 305  sub handler {
                                {col1 => 'Context',                                 {col1 => 'Context',
                                 col2 => 'Assignable authentication types'}],                                  col2 => 'Assignable authentication types'}],
                   },                    },
         'usermodification' =>           'usermodification' =>
                   { text => 'User modification',                    { text => 'User modification',
                     help => 'Domain_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 updateable in author context'},
                                {col1 => 'Target user has role',                                 {col1 => 'Target user has role',
                                 col2 => 'User information updateable in course context'}],                                  col2 => 'User information updateable in course context'},
                                  {col1 => "Status of user",
                                   col2 => 'Information settable when self-creating account (if directory data blank)'}],
                   },                    },
         'scantron' =>           'scantron' =>
                   { text => 'Scantron format file',                    { text => 'Bubblesheet format file',
                     help => 'Domain_Scantron_Formats',                      help => 'Domain_Configuration_Scantron_Format',
                     header => [ {col1 => 'Item',                      header => [ {col1 => 'Item',
                                  col2 => '',                                   col2 => '',
                               }],                                }],
                   },                    },
         'coursecategories' =>           'requestcourses' => 
                   { text => 'Cataloging of courses',                   {text => 'Request creation of courses',
                     help => 'Domain_Course_Catalog',                    help => 'Domain_Configuration_Request_Courses',
                     header => [  {col1 => 'Categories',                    header => [{col1 => 'User affiliation',
                                   col2 => '',                                col2 => 'Availability/Processing of requests',},
                               }],                               {col1 => 'Setting',
                   }                                col2 => 'Value'}],
                    },
           'requestauthor' =>
                    {text => 'Request authoring space',
                     help => 'Domain_Configuration_Request_Author',
                     header => [{col1 => 'User affiliation',
                                 col2 => 'Availability/Processing of requests',},
                                {col1 => 'Setting',
                                 col2 => 'Value'}],
                    },
           'coursecategories' =>
                     { text => 'Cataloging of courses/communities',
                       help => 'Domain_Configuration_Cataloging_Courses',
                       header => [{col1 => 'Category settings',
                                   col2 => '',},
                                  {col1 => 'Categories',
                                   col2 => '',
                                  }],
                     },
           'serverstatuses' =>
                    {text   => 'Access to server status pages',
                     help   => 'Domain_Configuration_Server_Status',
                     header => [{col1 => 'Status Page',
                                 col2 => 'Other named users',
                                 col3 => 'Specific IPs',
                               }],
                    },
           'helpsettings' =>
                    {text   => 'Help page settings',
                     help   => 'Domain_Configuration_Help_Settings',
                     header => [{col1 => 'Help Settings (logged-in users)',
                                 col2 => 'Value'}],
                    },
           'coursedefaults' => 
                    {text => 'Course/Community defaults',
                     help => 'Domain_Configuration_Course_Defaults',
                     header => [{col1 => 'Defaults which can be overridden in each course by a CC',
                                 col2 => 'Value',},
                                {col1 => 'Defaults which can be overridden for each course by a DC',
                                 col2 => 'Value',},],
                    },
           'privacy' => 
                    {text   => 'User Privacy',
                     help   => 'Domain_Configuration_User_Privacy',
                     header => [{col1 => 'Setting',
                                 col2 => 'Value',}],
                    },
           'usersessions' =>
                    {text  => 'User session hosting/offloading',
                     help  => 'Domain_Configuration_User_Sessions',
                     header => [{col1 => 'Domain server',
                                 col2 => 'Servers to offload sessions to when busy'},
                                {col1 => 'Hosting of users from other domains',
                                 col2 => 'Rules'},
                                {col1 => "Hosting domain's own users elsewhere",
                                 col2 => 'Rules'}],
                    },
            'loadbalancing' =>
                    {text  => 'Dedicated Load Balancer',
                     help  => 'Domain_Configuration_Load_Balancing',
                     header => [{col1 => 'Balancers',
                                 col2 => 'Default destinations',
                                 col3 => 'User affiliation',
                                 col4 => 'Overrides'},
                               ],
                    },
     );      );
       if (keys(%servers) > 1) {
           $prefs{'login'}  = { text   => 'Log-in page options',
                                help   => 'Domain_Configuration_Login_Page',
                               header => [{col1 => 'Log-in Service',
                                           col2 => 'Server Setting',},
                                          {col1 => 'Log-in Page Items',
                                           col2 => ''},
                                          {col1 => 'Log-in Help',
                                           col2 => 'Value'}],
                              };
       }
   
   
   
     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=>"Pick functionality"});        text=>"Settings to display/modify"});
     my $confname = $dom.'-domainconfig';      my $confname = $dom.'-domainconfig';
   
     if ($phase eq 'process') {      if ($phase eq 'process') {
         &Apache::lonhtmlcommon::add_breadcrumb          &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,\@roles);
           ({href=>"javascript:changePage(document.$phase,'display')",  
             text=>"Domain Configuration"},  
            {href=>"javascript:changePage(document.$phase,'$phase')",  
             text=>"Updated"});  
         &print_header($r,$phase);  
         foreach my $item (@prefs_order) {  
             if (grep(/^\Q$item\E$/,@actions)) {  
                 $r->print('<h3>'.&mt($prefs{$item}{'text'}).'</h3>'.  
                           &process_changes($r,$dom,$confname,$item,  
                           \@roles,%domconfig));  
             }  
         }  
         $r->print('<p>');  
         &print_footer($r,$phase,'display','Back to configuration display',  
                       \@actions);  
         $r->print('</p>');  
     } elsif ($phase eq 'display') {      } elsif ($phase eq 'display') {
         &Apache::lonhtmlcommon::add_breadcrumb          my $js = &recaptcha_js();
             ({href=>"javascript:changePage(document.$phase,'display')",          if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
               text=>"Domain Configuration"});              my ($othertitle,$usertypes,$types) =
         &print_header($r,$phase);                  &Apache::loncommon::sorted_inst_types($dom);
         if (@actions > 0) {              $js .= &lonbalance_targets_js($dom,$types,\%servers,
             my $rowsum = 0;                                            $domconfig{'loadbalancing'}).
             my (%output,%rowtotal,@items);                     &new_spares_js().
             my $halfway = @actions/2;                     &common_domprefs_js().
             foreach my $item (@prefs_order) {                     &Apache::loncommon::javascript_array_indexof();
                 if (grep(/^\Q$item\E$/,@actions)) {          }
                     push(@items,$item);          &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);
                     ($output{$item},$rowtotal{$item}) =       } else {
                         &print_config_box($r,$dom,$confname,$phase,  # check if domconfig user exists for the domain.
                                           $item,$prefs{$item},          my $servadm = $r->dir_config('lonAdmEMail');
                                           $domconfig{$item});          my ($configuserok,$author_ok,$switchserver) =
                     $rowsum += $rowtotal{$item};              &config_check($dom,$confname,$servadm);
                 }          unless ($configuserok eq 'ok') {
             }              &Apache::lonconfigsettings::print_header($r,$phase,$context);
             my $colend;              $r->print(&mt('The domain configuration user "[_1]" has yet to be created.',
             my $halfway = $rowsum/2;                             $confname).
             my $aggregate = 0;                        '<br />'
             my $sumleft = 0;              );
             my $sumright = 0;              if ($switchserver) {
             my $crossover;                  $r->print(&mt('Ordinarily, that domain configuration user is created when the ./UPDATE script is run to install LON-CAPA for the first time.').
             for (my $i=0; $i<@items; $i++) {                            '<br />'.
                 $aggregate += $rowtotal{$items[$i]};                            &mt('However, that does not apply when new domains are added to a multi-domain server, and ./UPDATE has not been run recently.').
                 if ($aggregate > $halfway) {                            '<br />'.
                     $crossover = $i;                            &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).
                     last;                            '<br />'.
                 }                            &mt('To do that now, use the following link: [_1]',$switchserver)
             }                  );
             for (my $i=0; $i<$crossover; $i++) {              } else {
                 $sumleft += $rowtotal{$items[$i]};                   $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 />'.
             for (my $i=$crossover+1; $i<@items; $i++) {                            &mt('Once that is done, you will be able to use the web-based "Set domain configuration" to configure the domain')
                 $sumright += $rowtotal{$items[$i]};                  );
             }              }
             if ((@items > 1) && ($env{'form.numcols'} == 2)) {              $r->print(&Apache::loncommon::end_page());
                 my $sumdiff = $sumright - $sumleft;              return OK;
                 if ($sumdiff > 0) {  
                     $colend = $crossover + 1;  
                 } else {  
                     $colend = $crossover;  
                 }  
             } else {  
                 $colend = @items;  
             }  
             $r->print('<p><table class="LC_double_column"><tr><td class="LC_left_col">');  
             for (my $i=0; $i<$colend; $i++) {  
                 $r->print($output{$items[$i]});  
             }  
             $r->print('</td><td></td><td class="LC_right_col">');  
             if ($colend < @items) {  
                 for (my $i=$colend; $i<@items; $i++) {   
                     $r->print($output{$items[$i]});  
                 }  
             }  
             $r->print('</td></tr></table></p>');  
             $r->print(&print_footer($r,$phase,'process','Save',\@actions));  
         } else {  
             $r->print('<input type="hidden" name="phase" value="" />'.  
                       '<input type="hidden" name="numcols" value="'.  
                       $env{'form.numcols'}.'" />'."\n".  
                       '<span clas="LC_error">'.&mt('No settings chosen').  
                       '</span>');  
         }  
         $r->print('</form>');  
         $r->print(&Apache::loncommon::end_page());  
     } else {  
         if ($phase eq '') {  
             $phase = 'pickactions';  
         }          }
         my %helphash;  
         &print_header($r,$phase);  
         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 284  sub handler { Line 477  sub handler {
                     }                      }
                 }                  }
                 if ($custom_img_count > 0) {                  if ($custom_img_count > 0) {
                       &Apache::lonconfigsettings::print_header($r,$phase,$context);
                     my $switch_server = &check_switchserver($dom,$confname);                      my $switch_server = &check_switchserver($dom,$confname);
                     $r->print(                      $r->print(
     &mt('Domain configuration settings have yet to be saved for this domain via the web-based domain preferences interface.').'<br />'.      &mt('Domain configuration settings have yet to be saved for this domain via the web-based domain preferences interface.').'<br />'.
Line 293  sub handler { Line 487  sub handler {
                     if ($switch_server) {                      if ($switch_server) {
                         $r->print($switch_server.' '.&mt('to primary library server for domain: [_1]',$dom));                          $r->print($switch_server.' '.&mt('to primary library server for domain: [_1]',$dom));
                     }                      }
                       $r->print(&Apache::loncommon::end_page());
                     return OK;                      return OK;
                 }                  }
             }              }
         }          }
         $r->print('<h3>'.&mt('Functionality to display/modify').'</h3>');  
         $r->print('<script type="text/javascript">'."\n".          &Apache::lonconfigsettings::display_choices($r,$phase,$context,\@prefs_order,\%prefs);
               &Apache::loncommon::check_uncheck_jscript()."\n".  
               '</script>'."\n".'<p><input type="button" value="check all" '.  
               'onclick="javascript:checkAll(document.pickactions.actions)"'.  
               ' />&nbsp;&nbsp;'.  
               '<input type="button" value="uncheck all" '.  
               'onclick="javascript:uncheckAll(document.pickactions.actions)"'.  
               ' /></p><div class="LC_left_float">');  
         my ($numitems,$midpoint,$seconddiv,$count);   
         $numitems = @prefs_order;  
         $midpoint = int($numitems/2);  
         if ($numitems%2) {  
             $midpoint ++;  
         }  
         $count = 0;  
         foreach my $item (@prefs_order) {  
             $r->print('<h4><label><input type="checkbox" name="actions" value="'.$item.'" />&nbsp;'.$prefs{$item}->{'text'}.'</label></h4>');  
             $count ++;  
             if ((!$seconddiv) && ($count >= $midpoint)) {  
                 $r->print('</div>'."\n".'<div class="LC_left_float">'."\n");  
                 $seconddiv = 1;  
             }  
         }  
         $r->print('</div><div class="LC_clear_float_footer"></div><h3>'.  
                   &mt('Display options').'</h3>'."\n".  
                   '<p><span class="LC_nobreak">'.&mt('Display using: ')."\n".  
                   '<label><input type="radio" name="numcols" value="1" />'.  
                   &mt('one column').'</label>&nbsp;&nbsp;<label>'.  
                   '<input type="radio" name="numcols" value="2" />'.  
                   &mt('two columns').'</label></span></p>');  
         $r->print(&print_footer($r,$phase,'display','Go'));  
         $r->print('</form>');  
         $r->print(&Apache::loncommon::end_page());  
     }      }
     return OK;      return OK;
 }  }
   
 sub process_changes {  sub process_changes {
     my ($r,$dom,$confname,$action,$roles,%domconfig) = @_;      my ($r,$dom,$confname,$action,$roles,$values) = @_;
       my %domconfig;
       if (ref($values) eq 'HASH') {
           %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,%domconfig);
Line 344  sub process_changes { Line 511  sub process_changes {
         $output = &modify_rolecolors($r,$dom,$confname,$roles,          $output = &modify_rolecolors($r,$dom,$confname,$roles,
                                      %domconfig);                                       %domconfig);
     } elsif ($action eq 'quotas') {      } elsif ($action eq 'quotas') {
         $output = &modify_quotas($dom,%domconfig);          $output = &modify_quotas($dom,$action,%domconfig);
     } elsif ($action eq 'autoenroll') {      } elsif ($action eq 'autoenroll') {
         $output = &modify_autoenroll($dom,%domconfig);          $output = &modify_autoenroll($dom,%domconfig);
     } elsif ($action eq 'autoupdate') {      } elsif ($action eq 'autoupdate') {
         $output = &modify_autoupdate($dom,%domconfig);          $output = &modify_autoupdate($dom,%domconfig);
       } elsif ($action eq 'autocreate') {
           $output = &modify_autocreate($dom,%domconfig);
     } elsif ($action eq 'directorysrch') {      } elsif ($action eq 'directorysrch') {
         $output = &modify_directorysrch($dom,%domconfig);          $output = &modify_directorysrch($dom,%domconfig);
     } elsif ($action eq 'usercreation') {      } elsif ($action eq 'usercreation') {
Line 363  sub process_changes { Line 532  sub process_changes {
         $output = &modify_scantron($r,$dom,$confname,%domconfig);          $output = &modify_scantron($r,$dom,$confname,%domconfig);
     } elsif ($action eq 'coursecategories') {      } elsif ($action eq 'coursecategories') {
         $output = &modify_coursecategories($dom,%domconfig);          $output = &modify_coursecategories($dom,%domconfig);
       } elsif ($action eq 'serverstatuses') {
           $output = &modify_serverstatuses($dom,%domconfig);
       } elsif ($action eq 'requestcourses') {
           $output = &modify_quotas($dom,$action,%domconfig);
       } elsif ($action eq 'requestauthor') {
           $output = &modify_quotas($dom,$action,%domconfig);
       } elsif ($action eq 'helpsettings') {
           $output = &modify_helpsettings($r,$dom,$confname,%domconfig);
       } elsif ($action eq 'coursedefaults') {
           $output = &modify_coursedefaults($dom,%domconfig);
       } elsif ($action eq 'usersessions') {
           $output = &modify_usersessions($dom,%domconfig);
       } elsif ($action eq 'loadbalancing') {
           $output = &modify_loadbalancing($dom,%domconfig);
     }      }
     return $output;      return $output;
 }  }
Line 371  sub print_config_box { Line 554  sub print_config_box {
     my ($r,$dom,$confname,$phase,$action,$item,$settings) = @_;      my ($r,$dom,$confname,$phase,$action,$item,$settings) = @_;
     my $rowtotal = 0;      my $rowtotal = 0;
     my $output;      my $output;
   
     if ($action eq 'coursecategories') {      if ($action eq 'coursecategories') {
         $output = &coursecategories_javascript($settings);          $output = &coursecategories_javascript($settings);
     }        }
     $output .=       $output .= 
          '<table class="LC_nested_outer">           '<table class="LC_nested_outer">
           <tr>            <tr>
            <th align="left"><span class="LC_nobreak">'.&mt($item->{text}).             <th align="left" valign="middle"><span class="LC_nobreak">'.
            '&nbsp;</span></th></tr>';             &mt($item->{text}).'&nbsp;'.
 #              &Apache::loncommon::help_open_topic($item->{'help'}).'</span></th>'."\n".
 # FIXME - put the help link back in when the help files exist            '</tr>';
 #           <th>'.&mt($item->{text}).'&nbsp;'.  
 #           &Apache::loncommon::help_open_topic($item->{'help'}).'</th>  
 #          </tr>');  
     $rowtotal ++;      $rowtotal ++;
     if (($action eq 'autoupdate') || ($action eq 'rolecolors') ||       my $numheaders = 1;
         ($action eq 'usercreation') || ($action eq 'usermodification')) {      if (ref($item->{'header'}) eq 'ARRAY') {
         my $colspan = ($action eq 'rolecolors')?' colspan="2"':'';          $numheaders = scalar(@{$item->{'header'}});
       }
       if ($numheaders > 1) {
           my $colspan = '';
           my $rightcolspan = '';
           if (($action eq 'rolecolors') || ($action eq 'coursecategories') || 
               (($action eq 'login') && ($numheaders < 3))) {
               $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.'>'.$item->{'header'}->[0]->{'col1'}.'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
               <td class="LC_right_item">'.$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') {
             $output .= &print_autoupdate('top',$dom,$settings,\$rowtotal);              $output .= &print_autoupdate('top',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'usercreation') {          } elsif ($action eq 'usercreation') {
             $output .= &print_usercreation('top',$dom,$settings,\$rowtotal);              $output .= &print_usercreation('top',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'usermodification') {          } elsif ($action eq 'usermodification') {
             $output .= &print_usermodification('top',$dom,$settings,\$rowtotal);              $output .= &print_usermodification('top',$dom,$settings,\$rowtotal);
         } else {          } elsif ($action eq 'coursecategories') {
               $output .= &print_coursecategories('top',$dom,$item,$settings,\$rowtotal);
           } elsif ($action eq 'login') {
               if ($numheaders == 3) {
                   $colspan = ' colspan="2"';
                   $output .= &print_login('service',$dom,$confname,$phase,$settings,\$rowtotal);
               } else {
                   $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal);
               }
           } elsif ($action eq 'requestcourses') {
               $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
           } elsif ($action eq 'requestauthor') {
               $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
           } elsif ($action eq 'usersessions') {
               $output .= &print_usersessions('top',$dom,$settings,\$rowtotal); 
           } 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 414  sub print_config_box { Line 623  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.'>'.$item->{'header'}->[1]->{'col1'}.'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col1'}).'</td>';
               <td class="LC_right_item">'.$item->{'header'}->[1]->{'col2'}.'</td>          $output .= '
                 <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col2'}).'</td>
              </tr>';               </tr>';
             $rowtotal ++;              $rowtotal ++;
         if ($action eq 'autoupdate') {          if ($action eq 'autoupdate') {
             $output .= &print_autoupdate('bottom',$dom,$settings,\$rowtotal);              $output .= &print_autoupdate('middle',$dom,$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'}->[2]->{'col1'}).'</td>
                 <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>      </tr>'.
               &print_autoupdate('bottom',$dom,$settings,\$rowtotal);
               $rowtotal ++;
         } elsif ($action eq 'usercreation') {          } elsif ($action eq 'usercreation') {
             $output .= &print_usercreation('middle',$dom,$settings,\$rowtotal).'              $output .= &print_usercreation('middle',$dom,$settings,\$rowtotal).'
            </table>             </table>
Line 429  sub print_config_box { Line 650  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.'>'.$item->{'header'}->[2]->{'col1'}.'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item">'.$item->{'header'}->[2]->{'col2'}.'</td>             </tr>'.                <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>             </tr>'.
             &print_usercreation('bottom',$dom,$settings,\$rowtotal);              &print_usercreation('bottom',$dom,$settings,\$rowtotal);
             $rowtotal ++;              $rowtotal ++;
         } elsif ($action eq 'usermodification') {          } elsif ($action eq 'usermodification') {
             $output .= &print_usermodification('bottom',$dom,$settings,\$rowtotal);              $output .= &print_usermodification('middle',$dom,$settings,\$rowtotal).'
         } else {             </table>
             </td>
            </tr>
            <tr>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
                 <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>      </tr>'.
                          &print_usermodification('bottom',$dom,$settings,\$rowtotal);
               $rowtotal ++;
           } elsif ($action eq 'coursecategories') {
               $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
           } elsif ($action eq 'login') {
               if ($numheaders == 3) {
                   $output .= &print_login('page',$dom,$confname,$phase,$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'}->[2]->{'col1'}).'</td>
                 <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td>      </tr>'.
                          &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);
           } elsif ($action eq 'requestauthor') {
               $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);
           } elsif ($action eq 'usersessions') {
               $output .= &print_usersessions('middle',$dom,$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'}->[2]->{'col1'}).'</td>
                 <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>      </tr>'.
                          &print_usersessions('bottom',$dom,$settings,\$rowtotal);
               $rowtotal ++;
           } elsif ($action eq 'coursedefaults') {
               $output .= &print_coursedefaults('bottom',$dom,$settings,\$rowtotal);
           } elsif ($action eq 'rolecolors') {
             $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'              $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'
            </table>             </table>
           </td>            </td>
Line 444  sub print_config_box { Line 714  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.'>'.$item->{'header'}->[2]->{'col1'}.'</td>                <td class="LC_left_item"'.$colspan.' valign="top">'.
               <td class="LC_right_item">'.$item->{'header'}->[2]->{'col2'}.'</td>                 &mt($item->{'header'}->[2]->{'col1'}).'</td>
                 <td class="LC_right_item" valign="top">'.
                  &mt($item->{'header'}->[2]->{'col2'}).'</td>
              </tr>'.               </tr>'.
             &print_rolecolors($phase,'author',$dom,$confname,$settings,\$rowtotal).'              &print_rolecolors($phase,'author',$dom,$confname,$settings,\$rowtotal).'
            </table>             </table>
Line 455  sub print_config_box { Line 727  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.'>'.$item->{'header'}->[3]->{'col1'}.'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
               <td class="LC_right_item">'.$item->{'header'}->[3]->{'col2'}.'</td>                <td class="LC_right_item">'.&mt($item->{'header'}->[3]->{'col2'}).'</td>
              </tr>'.               </tr>'.
             &print_rolecolors($phase,'admin',$dom,$confname,$settings,\$rowtotal);              &print_rolecolors($phase,'admin',$dom,$confname,$settings,\$rowtotal);
             $rowtotal += 2;              $rowtotal += 2;
Line 469  sub print_config_box { Line 741  sub print_config_box {
              <tr class="LC_info_row">';               <tr class="LC_info_row">';
         if (($action eq 'login') || ($action eq 'directorysrch')) {          if (($action eq 'login') || ($action eq 'directorysrch')) {
             $output .= '                $output .= '  
               <td class="LC_left_item" colspan="2">'.$item->{'header'}->[0]->{'col1'}.'</td>';                <td class="LC_left_item" colspan="2">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
           } elsif ($action eq 'serverstatuses') {
               $output .= '
                 <td class="LC_left_item" valign="top">'.&mt($item->{'header'}->[0]->{'col1'}).
                 '<br />('.&mt('Automatic access for Dom. Coords.').')</td>';
   
         } else {          } else {
             $output .= '              $output .= '
               <td class="LC_left_item">'.$item->{'header'}->[0]->{'col1'}.'</td>';                <td class="LC_left_item" valign="top">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
         }          }
         my $colspan = ($action eq 'coursecategories')?' colspan="2"':'';          if (defined($item->{'header'}->[0]->{'col3'})) {
         $output .= '              $output .= '<td class="LC_left_item" valign="top">'.
               <td class="LC_right_item"'.$colspan.'>'.$item->{'header'}->[0]->{'col2'}.'</td>                         &mt($item->{'header'}->[0]->{'col2'});
              </tr>';              if ($action eq 'serverstatuses') {
                   $output .= '<br />(<tt>'.&mt('user1:domain1,user2:domain2 etc.').'</tt>)';
               } 
           } else {
               $output .= '<td class="LC_right_item" valign="top">'.
                          &mt($item->{'header'}->[0]->{'col2'});
           }
           $output .= '</td>';
           if ($item->{'header'}->[0]->{'col3'}) {
               if (defined($item->{'header'}->[0]->{'col4'})) {
                   $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') {
                   $output .= '<br />(<tt>'.&mt('IP1,IP2 etc.').'</tt>)';
               }
               $output .= '</td>';
           }
           if ($item->{'header'}->[0]->{'col4'}) {
               $output .= '<td class="LC_right_item" valign="top">'.
                          &mt($item->{'header'}->[0]->{'col4'});
           }
           $output .= '</tr>';
         $rowtotal ++;          $rowtotal ++;
         if ($action eq 'login') {          if ($action eq 'quotas') {
             $output .= &print_login($dom,$confname,$phase,$settings,\$rowtotal);              $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
         } elsif ($action eq 'quotas') {  
             $output .= &print_quotas($dom,$settings,\$rowtotal);  
         } elsif ($action eq 'autoenroll') {          } elsif ($action eq 'autoenroll') {
             $output .= &print_autoenroll($dom,$settings,\$rowtotal);              $output .= &print_autoenroll($dom,$settings,\$rowtotal);
           } elsif ($action eq 'autocreate') {
               $output .= &print_autocreate($dom,$settings,\$rowtotal);
         } elsif ($action eq 'directorysrch') {          } elsif ($action eq 'directorysrch') {
             $output .= &print_directorysrch($dom,$settings,\$rowtotal);              $output .= &print_directorysrch($dom,$settings,\$rowtotal);
         } elsif ($action eq 'contacts') {          } elsif ($action eq 'contacts') {
Line 493  sub print_config_box { Line 795  sub print_config_box {
             $output .= &print_defaults($dom,\$rowtotal);              $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 'coursecategories'){          } elsif ($action eq 'serverstatuses') {
             $output .= &print_coursecategories($dom,$item,$settings,\$rowtotal);              $output .= &print_serverstatuses($dom,$settings,\$rowtotal);
           } elsif ($action eq 'helpsettings') {
               $output .= &print_helpsettings($dom,$confname,$settings,\$rowtotal);
           } elsif ($action eq 'loadbalancing') {
               $output .= &print_loadbalancing($dom,$settings,\$rowtotal);
         }          }
     }      }
     $output .= '      $output .= '
Line 505  sub print_config_box { Line 811  sub print_config_box {
     return ($output,$rowtotal);      return ($output,$rowtotal);
 }  }
   
 sub print_header {  
     my ($r,$phase) = @_;  
     my $alert = &mt('You must select at least one functionality type to display.');   
     my $js = '  
 <script type="text/javascript">  
 function changePage(formname,newphase) {  
     formname.phase.value = newphase;  
     numchecked = 0;  
     if (formname == document.pickactions) {  
         if (formname.actions.length > 0) {  
             for (var i = 0; i<formname.actions.length; i++) {  
                 if (formname.actions[i].checked) {  
                     numchecked ++;  
                 }  
             }  
         } else {  
             if (formname.actions.checked) {  
                 numchecked ++;  
             }  
         }  
         if (numchecked > 0) {  
             formname.submit();  
         } else {  
             alert("'.$alert.'");  
             return;  
         }  
     }  
     formname.submit();  
 }'."\n";  
     if ($phase eq 'pickactions') {  
         $js .=   
             &Apache::lonhtmlcommon::set_form_elements({actions => 'checkbox',numcols => 'radio',})."\n".  
             &javascript_set_colnums();  
     } elsif ($phase eq 'display') {  
         $js .= &color_pick_js()."\n";  
     }  
     $js .= &Apache::loncommon::viewport_size_js().'  
 </script>  
 ';  
     my $additem;  
     if ($phase eq 'pickactions') {  
         my %loaditems = (  
                     'onload' => "javascript:getViewportDims(document.$phase.width,document.$phase.height);setDisplayColumns();setFormElements(document.pickactions);",  
                         );  
         $additem = {'add_entries' => \%loaditems,};  
     } else {  
         my %loaditems = (  
                     'onload' => "javascript:getViewportDims(document.$phase.width,document.$phase.height);",  
                         );  
         $additem = {'add_entries' => \%loaditems,};  
     }  
     $r->print(&Apache::loncommon::start_page('View/Modify Domain Settings',  
                                            $js,$additem));  
     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Domain Settings'));  
     $r->print('  
 <form name="parmform" action="">  
 <input type="hidden" name="pres_marker" />  
 <input type="hidden" name="pres_type" />  
 <input type="hidden" name="pres_value" />  
 </form>  
 ');  
     $r->print('<form method="post" name="'.$phase.'" action="/adm/domainprefs"'.  
               ' enctype="multipart/form-data">');  
     return;  
 }  
   
 sub print_footer {  
     my ($r,$phase,$newphase,$button_text,$actions) = @_;  
     $button_text = &mt($button_text);  
     $r->print('<input type="hidden" name="phase" value="" />'.  
               '<input type="hidden" name="width" value="'.  
               $env{'form.width'}.'" />'.  
               '<input type="hidden" name="height" value="'.  
               $env{'form.height'}.'" />');  
     if (($phase eq 'display') || ($phase eq 'process')) {  
         if (ref($actions) eq 'ARRAY') {  
             foreach my $item (@{$actions}) {  
                 $r->print('<input type="hidden" name="actions" value="'.$item.'" />')."\n";  
             }  
         }  
         $r->print('<input type="hidden" name="numcols" value="'.$env{'form.numcols'}.'" />');  
     }  
     my $dest='"javascript:changePage(document.'.$phase.','."'$newphase'".')"';  
     if ($phase eq 'process') {  
         $r->print('<p><a href='.$dest.'>'.$button_text.'</a></p>');  
     } else {  
         my $onclick;  
         if ($phase eq 'display') {  
             $onclick = '"javascript:changePage(document.'.$phase.','."'$newphase'".')"';  
         } else {  
             $onclick = '"javascript:changePage(document.'.$phase.','."'$newphase'".')"';  
         }   
         $r->print('<p><input type="button" name="store" value="'.  
                   $button_text.'" onclick='.$onclick.' /></p>');  
     }  
     if ($phase eq 'process') {  
         $r->print('</form>'.&Apache::loncommon::end_page());  
     }  
     return;  
 }  
   
 sub print_login {  sub print_login {
     my ($dom,$confname,$phase,$settings,$rowtotal) = @_;      my ($caller,$dom,$confname,$phase,$settings,$rowtotal) = @_;
       my ($css_class,$datatable);
     my %choices = &login_choices();      my %choices = &login_choices();
     my %defaultchecked = (   
                            'coursecatalog' => 'on',      if ($caller eq 'service') {
                            'adminmail'     => 'off',          my %servers = &Apache::lonnet::internet_dom_servers($dom);
                            'newuser'       => 'off',          my $choice = $choices{'disallowlogin'};
                          );          $css_class = ' class="LC_odd_row"';
     my @toggles = ('coursecatalog','adminmail','newuser');          $datatable .= '<tr'.$css_class.'><td>'.$choice.'</td>'.
     my (%checkedon,%checkedoff);                        '<td align="right"><table><tr><th>'.$choices{'hostid'}.'</th>'.
     foreach my $item (@toggles) {                        '<th>'.$choices{'server'}.'</th>'.
         if ($defaultchecked{$item} eq 'on') {                         '<th>'.$choices{'serverpath'}.'</th>'.
             $checkedon{$item} = ' checked="checked" ';                        '<th>'.$choices{'custompath'}.'</th>'.
             $checkedoff{$item} = ' ';                        '<th><span class="LC_nobreak">'.$choices{'exempt'}.'</span></th></tr>'."\n";
         } elsif ($defaultchecked{$item} eq 'off') {          my %disallowed;
             $checkedoff{$item} = ' checked="checked" ';          if (ref($settings) eq 'HASH') {
             $checkedon{$item} = ' ';              if (ref($settings->{'loginvia'}) eq 'HASH') {
                  %disallowed = %{$settings->{'loginvia'}};
               }
         }          }
     }          foreach my $lonhost (sort(keys(%servers))) {
     my $loginheader = 'image';              my $direct = 'selected="selected"';
     my @images = ('img','logo','domlogo','login');              if (ref($disallowed{$lonhost}) eq 'HASH') {
     my @logintext = ('textcol','bgcol');                  if ($disallowed{$lonhost}{'server'} ne '') {
     my @bgs = ('pgbg','mainbg','sidebg');                      $direct = '';
     my @links = ('link','alink','vlink');                  }
     my %designhash = &Apache::loncommon::get_domainconf($dom);              }
     my %defaultdesign = %Apache::loncommon::defaultdesign;              $datatable .= '<tr><td>'.$servers{$lonhost}.'</td>'.
     my (%is_custom,%designs);                            '<td><select name="'.$lonhost.'_server">'.
     my %defaults = (                            '<option value=""'.$direct.'>'.$choices{'directlogin'}.
                    font => $defaultdesign{'login.font'},                            '</option>';
                    );              foreach my $hostid (sort keys(%servers)) {
     foreach my $item (@images) {                  next if ($servers{$hostid} eq $servers{$lonhost});
         $defaults{$item} = $defaultdesign{'login.'.$item};                  my $selected = '';
     }                  if (ref($disallowed{$lonhost}) eq 'HASH') {
     foreach my $item (@bgs) {                      if ($hostid eq $disallowed{$lonhost}{'server'}) {
         $defaults{'bgs'}{$item} = $defaultdesign{'login.'.$item};                          $selected = 'selected="selected"';
     }                      }
     foreach my $item (@logintext) {                  }
         $defaults{'logintext'}{$item} = $defaultdesign{'login.'.$item};                  $datatable .= '<option value="'.$hostid.'"'.$selected.'>'.
     }                                $servers{$hostid}.'</option>';
     foreach my $item (@links) {              }
         $defaults{'links'}{$item} = $defaultdesign{'login.'.$item};              $datatable .= '</select></td>'.
     }                            '<td><select name="'.$lonhost.'_serverpath">';
     if (ref($settings) eq 'HASH') {              foreach my $path ('','/','/adm/login','/adm/roles','custom') {
                   my $pathname = $path;
                   if ($path eq 'custom') {
                       $pathname = &mt('Custom Path').' ->';
                   }
                   my $selected = '';
                   if (ref($disallowed{$lonhost}) eq 'HASH') {
                       if ($path eq $disallowed{$lonhost}{'serverpath'}) {
                           $selected = 'selected="selected"';
                       }
                   } elsif ($path eq '') {
                       $selected = 'selected="selected"';
                   }
                   $datatable .= '<option value="'.$path.'"'.$selected.'>'.$pathname.'</option>';
               }
               $datatable .= '</select></td>';
               my ($custom,$exempt);
               if (ref($disallowed{$lonhost}) eq 'HASH') {
                   $custom = $disallowed{$lonhost}{'custompath'};
                   $exempt = $disallowed{$lonhost}{'exempt'};
               }
               $datatable .= '<td><input type="text" name="'.$lonhost.'_custompath" size="6" value="'.$custom.'" /></td>'.
                             '<td><input type="text" name="'.$lonhost.'_exempt" size="8" value="'.$exempt.'" /></td>'.
                             '</tr>';
           }
           $datatable .= '</table></td></tr>';
           return $datatable;
       } elsif ($caller eq 'page') {
           my %defaultchecked = ( 
                                  'coursecatalog' => 'on',
                                  'adminmail'     => 'off',
                                  'newuser'       => 'off',
                                );
           my @toggles = ('coursecatalog','adminmail','newuser');
           my (%checkedon,%checkedoff);
         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 ($settings->{$item} ne '') {              $defaults{$item} = $defaultdesign{'login.'.$item};
                 $designs{$item} = $settings->{$item};              $defaults{'showlogo'}{$item} = 1;
                 $is_custom{$item} = 1;  
             }  
         }          }
         foreach my $item (@logintext) {          foreach my $item (@bgs) {
             if ($settings->{$item} ne '') {              $defaults{'bgs'}{$item} = $defaultdesign{'login.'.$item};
                 $designs{'logintext'}{$item} = $settings->{$item};  
                 $is_custom{$item} = 1;  
             }  
         }          }
         if ($settings->{'loginheader'} ne '') {          foreach my $item (@logintext) {
             $loginheader = $settings->{'loginheader'};              $defaults{'logintext'}{$item} = $defaultdesign{'login.'.$item};
         }          }
         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,$loginheader);  
     $datatable .= '</tr></table></td></tr>';  
     return $datatable;      return $datatable;
 }  }
   
 sub login_choices {  sub login_choices {
     my %choices =      my %choices =
         &Apache::lonlocal::texthash (          &Apache::lonlocal::texthash (
             coursecatalog => 'Display Course Catalog link?',              coursecatalog => 'Display Course/Community Catalog link?',
             adminmail => "Display Administrator's E-mail Address?",              adminmail     => "Display Administrator's E-mail Address?",
             newuser   => "Link to create a user account",              disallowlogin => "Login page requests redirected",
             img => "Header",              hostid        => "Server",
             logo => "Main Logo",              server        => "Redirect to:",
             domlogo => "Domain Logo",              serverpath    => "Path",
             login => "Log-in Header",               custompath    => "Custom", 
             textcol => "Text color",              exempt        => "Exempt IP(s)",
             bgcol   => "Box color",              directlogin   => "No redirect",
             bgs => "Background colors",              newuser       => "Link to create a user account",
             links => "Link colors",              img           => "Header",
             font => "Font color",              logo          => "Main Logo",
             pgbg => "Page",              domlogo       => "Domain Logo",
             mainbg => "Main panel",              login         => "Log-in Header", 
             sidebg => "Side panel",              textcol       => "Text color",
             link => "Link",              bgcol         => "Box color",
             alink => "Active link",              bgs           => "Background colors",
             vlink => "Visited link",              links         => "Link colors",
               font          => "Font color",
               pgbg          => "Header",
               mainbg        => "Page",
               sidebg        => "Login box",
               link          => "Link",
               alink         => "Active link",
               vlink         => "Visited link",
         );          );
     return %choices;      return %choices;
 }  }
Line 774  sub print_rolecolors { Line 1145  sub print_rolecolors {
     my %defaults = (      my %defaults = (
                    img => $defaultdesign{$role.'.img'},                     img => $defaultdesign{$role.'.img'},
                    font => $defaultdesign{$role.'.font'},                     font => $defaultdesign{$role.'.font'},
      fontmenu => $defaultdesign{$role.'.fontmenu'},
                    );                     );
     foreach my $item (@bgs) {      foreach my $item (@bgs) {
         $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item};          $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item};
Line 791  sub print_rolecolors { Line 1163  sub print_rolecolors {
                 $designs{'font'} = $settings->{$role}->{'font'};                  $designs{'font'} = $settings->{$role}->{'font'};
                 $is_custom{'font'} = 1;                  $is_custom{'font'} = 1;
             }              }
               if ($settings->{$role}->{'fontmenu'} ne '') {
                   $designs{'fontmenu'} = $settings->{$role}->{'fontmenu'};
                   $is_custom{'fontmenu'} = 1;
               }
             foreach my $item (@bgs) {              foreach my $item (@bgs) {
                 if ($settings->{$role}->{$item} ne '') {                  if ($settings->{$role}->{$item} ne '') {
                     $designs{'bgs'}{$item} = $settings->{$role}->{$item};                      $designs{'bgs'}{$item} = $settings->{$role}->{$item};
Line 809  sub print_rolecolors { Line 1185  sub print_rolecolors {
             $designs{img} = $designhash{$dom.'.'.$role.'.img'};              $designs{img} = $designhash{$dom.'.'.$role.'.img'};
             $is_custom{'img'} = 1;              $is_custom{'img'} = 1;
         }          }
           if ($designhash{$dom.'.'.$role.'.fontmenu'} ne '') {
               $designs{fontmenu} = $designhash{$dom.'.'.$role.'.fontmenu'};
               $is_custom{'fontmenu'} = 1; 
           }
         if ($designhash{$dom.'.'.$role.'.font'} ne '') {          if ($designhash{$dom.'.'.$role.'.font'} ne '') {
             $designs{font} = $designhash{$dom.'.'.$role.'.font'};              $designs{font} = $designhash{$dom.'.'.$role.'.font'};
             $is_custom{'font'} = 1;              $is_custom{'font'} = 1;
Line 835  sub print_rolecolors { Line 1215  sub print_rolecolors {
   
 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,$loginheader) = @_;          $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 844  sub display_color_options { Line 1225  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>'.      unless ($role eq 'login') { 
                   '</span></td></tr>';          $datatable .= '<tr'.$css_class.'>'.
                         '<td>'.$choices->{'fontmenu'}.'</td>';
           if (!$is_custom->{'fontmenu'}) {
               $datatable .=  '<td>'.&mt('Default in use:').'&nbsp;<span id="css_default_'.$role.'_font" style="color: '.$defaults->{'fontmenu'}.';">'.$defaults->{'fontmenu'}.'</span></td>';
           } else {
               $datatable .= '<td>&nbsp;</td>';
           }
    $current_color = $designs->{'fontmenu'} ? 
       $designs->{'fontmenu'} : $defaults->{'fontmenu'};
           $datatable .= '<td><span class="LC_nobreak">'.
                         '<input class="colorchooser" type="text" size="10" name="'
         .$role.'_fontmenu"'.
                         ' value="'.$current_color.'" />&nbsp;'.
                         '&nbsp;</td></tr>';
       }
     my $switchserver = &check_switchserver($dom,$confname);      my $switchserver = &check_switchserver($dom,$confname);
     foreach my $img (@{$images}) {      foreach my $img (@{$images}) {
  $itemcount ++;   $itemcount ++;
         $css_class = $itemcount%2?' class="LC_odd_row"':'';          $css_class = $itemcount%2?' class="LC_odd_row"':'';
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                       '<td>'.$choices->{$img}.'</td>';                        '<td>'.$choices->{$img};
         my ($imgfile,$img_import,$login_hdr_pick,$logincolors);          my ($imgfile,$img_import,$login_hdr_pick,$logincolors);
           if ($role eq 'login') {
               if ($img eq 'login') {
                   $login_hdr_pick =
                       &login_header_options($img,$role,$defaults,$is_custom,$choices);
                   $logincolors =
                       &login_text_colors($img,$role,$logintext,$phase,$choices,
                                               $designs);
               } elsif ($img ne 'domlogo') {
                   $datatable.= &logo_display_options($img,$defaults,$designs);
               }
           }
           $datatable .= '</td>';
         if ($designs->{$img} ne '') {          if ($designs->{$img} ne '') {
             $imgfile = $designs->{$img};              $imgfile = $designs->{$img};
     $img_import = ($imgfile =~ m{^/adm/});      $img_import = ($imgfile =~ m{^/adm/});
         } else {          } else {
             $imgfile = $defaults->{$img};              $imgfile = $defaults->{$img};
         }          }
         if ($img eq 'login') {  
             $login_hdr_pick = &login_header_options($img,$role,$defaults,$is_custom,$choices,  
                                                     $loginheader);  
             $logincolors =  
                 &login_text_colors($img,$role,$logintext,$phase,$choices,$designs);  
         }  
         if ($imgfile) {          if ($imgfile) {
             my ($showfile,$fullsize);              my ($showfile,$fullsize);
             if ($imgfile =~ m-^(/res/\Q$dom\E/\Q$confname\E/\Q$img\E)/([^/]+)$-) {              if ($imgfile =~ m-^(/res/\Q$dom\E/\Q$confname\E/\Q$img\E)/([^/]+)$-) {
Line 891  sub display_color_options { Line 1293  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 903  sub display_color_options { Line 1305  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 932  sub display_color_options { Line 1334  sub display_color_options {
                 }                  }
                 $datatable .= '<td>';                  $datatable .= '<td>';
                 if ($img eq 'login') {                  if ($img eq 'login') {
                     $datatable .= $login_hdr_pick;                          $datatable .= $login_hdr_pick;
                 }                  } 
                 $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 {
Line 947  sub display_color_options { Line 1349  sub display_color_options {
         if ($switchserver) {          if ($switchserver) {
             $datatable .= &mt('Upload to library server: [_1]',$switchserver);              $datatable .= &mt('Upload to library server: [_1]',$switchserver);
         } else {          } else {
             $datatable .='&nbsp;<input type="file" name="'.$role.'_'.$img.'" />';              if ($img ne 'login') { # suppress file selection for Log-in header
                   $datatable .='&nbsp;<input type="file" name="'.$role.'_'.$img.'" />';
               }
         }          }
         $datatable .= '</td></tr>';          $datatable .= '</td></tr>';
     }      }
Line 958  sub display_color_options { Line 1362  sub display_color_options {
     my $bgs_def;      my $bgs_def;
     foreach my $item (@{$bgs}) {      foreach my $item (@{$bgs}) {
         if (!$is_custom->{$item}) {          if (!$is_custom->{$item}) {
             $bgs_def .= '<td>'.$choices->{$item}.'&nbsp;<span id="css_default_'.$role.'_'.$item.'" style="background-color: '.$defaults->{'bgs'}{$item}.';">&nbsp;&nbsp;&nbsp;</span><br />'.$defaults->{'bgs'}{$item}.'</td>';              $bgs_def .= '<td><span class="LC_nobreak">'.$choices->{$item}.'</span>&nbsp;<span id="css_default_'.$role.'_'.$item.'" style="background-color: '.$defaults->{'bgs'}{$item}.';">&nbsp;&nbsp;&nbsp;</span><br />'.$defaults->{'bgs'}{$item}.'</td>';
         }          }
     }      }
     if ($bgs_def) {      if ($bgs_def) {
Line 968  sub display_color_options { Line 1372  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});  #        my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'bgs'}{$item});
         $datatable .= '<td align="center">'.$link;          $datatable .= '<td align="center">';
    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 996  sub display_color_options { Line 1403  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->{'link'}{$item} ? $designs->{'link'}{$item} : $defaults->{'links'}{$item};
                       &color_pick($phase,$role,$item,$choices->{$item},          $datatable .= '<td align="center">'."\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;
     return $datatable;      return $datatable;
 }  }
   
   sub logo_display_options {
       my ($img,$defaults,$designs) = @_;
       my $checkedon;
       if (ref($defaults) eq 'HASH') {
           if (ref($defaults->{'showlogo'}) eq 'HASH') {
               if ($defaults->{'showlogo'}{$img}) {
                   $checkedon = 'checked="checked" ';     
               }
           } 
       }
       if (ref($designs) eq 'HASH') {
           if (ref($designs->{'showlogo'}) eq 'HASH') {
               if (defined($designs->{'showlogo'}{$img})) {
                   if ($designs->{'showlogo'}{$img} == 0) {
                       $checkedon = '';
                   } elsif ($designs->{'showlogo'}{$img} == 1) {
                       $checkedon = 'checked="checked" ';
                   }
               }
           }
       }
       return '<br /><label>&nbsp;&nbsp;<input type="checkbox" name="'.
              'login_showlogo_'.$img.'" value="1" '.$checkedon.'/>'.
              &mt('show').'</label>'."\n";
   }
   
 sub login_header_options  {  sub login_header_options  {
     my ($img,$role,$defaults,$is_custom,$choices,$loginheader) = @_;      my ($img,$role,$defaults,$is_custom,$choices) = @_;
     my $image_checked = ' checked="checked" ';      my $output = '';
     my $text_checked = ' ';  
     if ($loginheader eq 'text') {  
         $image_checked = ' ';  
         $text_checked = ' checked="checked" ';  
     }  
     my $output = '<span class="LC_nobreak"><label><input type="radio" name="'.  
               'loginheader" value="image" '.$image_checked.'/>'.  
               &mt('use image').'</label>&nbsp;&nbsp;&nbsp;'.  
               '<label><input type="radio" name="loginheader" value="text"'.  
               $text_checked.'/>'.&mt('use text').'</label><br />'."\n";  
     if ((!$is_custom->{'textcol'}) || (!$is_custom->{'bgcol'})) {      if ((!$is_custom->{'textcol'}) || (!$is_custom->{'bgcol'})) {
         $output .= &mt('Text default(s)').':<br />';          $output .= &mt('Text default(s):').'<br />';
         if (!$is_custom->{'textcol'}) {          if (!$is_custom->{'textcol'}) {
             $output .= $choices->{'textcol'}.':&nbsp;'.$defaults->{'logintext'}{'textcol'}.              $output .= $choices->{'textcol'}.':&nbsp;'.$defaults->{'logintext'}{'textcol'}.
                        '&nbsp;&nbsp;&nbsp;';                         '&nbsp;&nbsp;&nbsp;';
Line 1059  sub login_text_colors { Line 1482  sub login_text_colors {
 sub image_changes {  sub image_changes {
     my ($is_custom,$alt_text,$img_import,$showfile,$fullsize,$role,$img,$imgfile,$logincolors) = @_;      my ($is_custom,$alt_text,$img_import,$showfile,$fullsize,$role,$img,$imgfile,$logincolors) = @_;
     my $output;      my $output;
     if (!$is_custom) {      if ($img eq 'login') {
         if ($img eq 'login') {              # suppress image for Log-in header
       } elsif (!$is_custom) {
           if ($img ne 'domlogo') {
             $output .= &mt('Default image:').'<br />';              $output .= &mt('Default image:').'<br />';
         } else {          } else {
             $output .= &mt('Default in use:').'<br />';              $output .= &mt('Default in use:').'<br />';
         }          }
     }      }
     if ($img_import) {      if ($img eq 'login') { # suppress image for Log-in header
         $output .= '<input type="hidden" name="'.$role.'_import_'.$img.'" value="'.$imgfile.'" />';          $output .= '<td>'.$logincolors;
     }  
     $output .= '<a href="'.$fullsize.'" target="_blank"><img src="'.  
                $showfile.'" alt="'.$alt_text.'" border="0" /></a></td>';  
     if ($is_custom) {  
         $output .= '<td>'.$logincolors.'<span class="LC_nobreak"><label>'.  
                    '<input type="checkbox" name="'.  
                    $role.'_del_'.$img.'" value="1" />'.&mt('Delete?').  
                    '</label>&nbsp;'.&mt('Replace:').'</span><br />';  
     } else {      } else {
         $output .= '<td valign="bottom">'.$logincolors.&mt('Upload:').'<br />';          if ($img_import) {
               $output .= '<input type="hidden" name="'.$role.'_import_'.$img.'" value="'.$imgfile.'" />';
           }
           $output .= '<a href="'.$fullsize.'" target="_blank"><img src="'.
                      $showfile.'" alt="'.$alt_text.'" border="0" /></a></td>';
           if ($is_custom) {
               $output .= '<td>'.$logincolors.'<span class="LC_nobreak"><label>'.
                          '<input type="checkbox" name="'.
                          $role.'_del_'.$img.'" value="1" />'.&mt('Delete?').
                          '</label>&nbsp;'.&mt('Replace:').'</span><br />';
           } else {
               $output .= '<td valign="bottom">'.$logincolors.&mt('Upload:').'<br />';
           }
     }      }
     return $output;      return $output;
 }  }
Line 1090  sub color_pick { Line 1519  sub color_pick {
     return $link;      return $link;
 }  }
   
 sub color_pick_js {  
     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();  
     my $output = <<"ENDCOL";  
     function pclose() {  
         parmwin=window.open("/adm/rat/empty.html","LONCAPAparms","height=350,width=350,scrollbars=no,menubar=no");  
         parmwin.close();  
     }  
   
     $pjump_def  
   
     function psub() {  
         pclose();  
         if (document.parmform.pres_marker.value!='') {  
             if (document.parmform.pres_type.value!='') {  
                 eval('document.display.'+  
                      document.parmform.pres_marker.value+  
                      '.value=document.parmform.pres_value.value;');  
             }  
         } else {  
             document.parmform.pres_value.value='';  
             document.parmform.pres_marker.value='';  
         }  
     }  
   
     function get_id (span_id) {  
  if (document.getElementById) {  
             return document.getElementById(span_id);  
         }  
  if (document.all) {  
             return document.all[span_id];  
         }   
  return false;  
     }  
   
     function colchg_span (span_id_str,new_color_item) {  
  var span_ref = get_id(span_id_str);  
  if (span_ref.style) { span_ref = span_ref.style; }  
  span_ref.background = new_color_item.value;  
  span_ref.backgroundColor = new_color_item.value;  
  span_ref.bgColor = new_color_item.value;  
     }  
   
 ENDCOL  
     return $output;  
 }  
   
 sub print_quotas {  sub print_quotas {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal,$action) = @_;
     my $datatable;      my $context;
       if ($action eq 'quotas') {
           $context = 'tools';
       } else {
           $context = $action;
       }
       my ($datatable,$defaultquota,@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;      my ($css_class,%titles);
       if ($context eq 'requestcourses') {
           @usertools = ('official','unofficial','community');
           @options =('norequest','approval','validate','autolimit');
           %validations = &Apache::lonnet::auto_courserequest_checks($dom);
           %titles = &courserequest_titles();
       } elsif ($context eq 'requestauthor') {
           @usertools = ('author');
           @options = ('norequest','approval','automatic');
           %titles = &authorrequest_titles(); 
       } else {
           @usertools = ('aboutme','blog','webdav','portfolio');
           %titles = &tool_titles();
       }
     if (ref($types) eq 'ARRAY') {      if (ref($types) eq 'ARRAY') {
         foreach my $type (@{$types}) {          foreach my $type (@{$types}) {
               my $currdefquota;
               unless (($context eq 'requestcourses') ||
                       ($context eq 'requestauthor')) {
                   if (ref($settings) eq 'HASH') {
                       if (ref($settings->{defaultquota}) eq 'HASH') {
                           $currdefquota = $settings->{defaultquota}->{$type}; 
                       } else {
                           $currdefquota = $settings->{$type};
                       }
                   }
               }
             if (defined($usertypes->{$type})) {              if (defined($usertypes->{$type})) {
                 $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>'.$usertypes->{$type}.'</td>'.                                '<td>'.$usertypes->{$type}.'</td>'.
                                 '<td class="LC_left_item">';
                   if ($context eq 'requestcourses') {
                       $datatable .= '<table><tr>';
                   }
                   my %cell;  
                   foreach my $item (@usertools) {
                       if ($context eq 'requestcourses') {
                           my ($curroption,$currlimit);
                           if (ref($settings) eq 'HASH') {
                               if (ref($settings->{$item}) eq 'HASH') {
                                   $curroption = $settings->{$item}->{$type};
                                   if ($curroption =~ /^autolimit=(\d*)$/) {
                                       $currlimit = $1; 
                                   }
                               }
                           }
                           if (!$curroption) {
                               $curroption = 'norequest';
                           }
                           $datatable .= '<th>'.$titles{$item}.'</th>';
                           foreach my $option (@options) {
                               my $val = $option;
                               if ($option eq 'norequest') {
                                   $val = 0;  
                               }
                               if ($option eq 'validate') {
                                   my $canvalidate = 0;
                                   if (ref($validations{$item}) eq 'HASH') { 
                                       if ($validations{$item}{$type}) {
                                           $canvalidate = 1;
                                       }
                                   }
                                   next if (!$canvalidate);
                               }
                               my $checked = '';
                               if ($option eq $curroption) {
                                   $checked = ' checked="checked"';
                               } elsif ($option eq 'autolimit') {
                                   if ($curroption =~ /^autolimit/) {
                                       $checked = ' checked="checked"';
                                   }                       
                               } 
                               $cell{$item} .= '<span class="LC_nobreak"><label>'.
                                     '<input type="radio" name="crsreq_'.$item.
                                     '_'.$type.'" value="'.$val.'"'.$checked.' />'.
                                     $titles{$option}.'</label>';
                               if ($option eq 'autolimit') {
                                   $cell{$item} .= '&nbsp;<input type="text" name="crsreq_'.
                                                   $item.'_limit_'.$type.'" size="1" '.
                                                   'value="'.$currlimit.'" />';
                               }
                               $cell{$item} .= '</span> ';
                               if ($option eq 'autolimit') {
                                   $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 {
                           my $checked = 'checked="checked" ';
                           if (ref($settings) eq 'HASH') {
                               if (ref($settings->{$item}) eq 'HASH') {
                                   if ($settings->{$item}->{$type} == 0) {
                                       $checked = '';
                                   } elsif ($settings->{$item}->{$type} == 1) {
                                       $checked =  'checked="checked" ';
                                   }
                               }
                           }
                           $datatable .= '<span class="LC_nobreak"><label>'.
                                         '<input type="checkbox" name="'.$context.'_'.$item.
                                         '" value="'.$type.'" '.$checked.'/>'.$titles{$item}.
                                         '</label></span>&nbsp; ';
                       }
                   }
                   if ($context eq 'requestcourses') {
                       $datatable .= '</tr><tr>';
                       foreach my $item (@usertools) {
                           $datatable .= '<td style="vertical-align: top">'.$cell{$item}.'</td>';  
                       }
                       $datatable .= '</tr></table>';
                   }
                   $datatable .= '</td>';
                   unless (($context eq 'requestcourses') ||
                           ($context eq 'requestauthor')) {
                       $datatable .= 
                               '<td class="LC_right_item"><span class="LC_nobreak">'.                                '<td class="LC_right_item"><span class="LC_nobreak">'.
                               '<input type="text" name="quota_'.$type.                                '<input type="text" name="quota_'.$type.
                               '" value="'.$settings->{$type}.                                '" value="'.$currdefquota.
                               '" size="5" /> Mb</span></td></tr>';                                '" size="5" /> Mb</span></td>';
                   }
                   $datatable .= '</tr>';
             }              }
         }          }
     }      }
     my $defaultquota = '20';      unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
     if (ref($settings) eq 'HASH') {          $defaultquota = '20';
         if (defined($settings->{'default'})) {          if (ref($settings) eq 'HASH') {
             $defaultquota = $settings->{'default'};              if (ref($settings->{'defaultquota'}) eq 'HASH') {
                   $defaultquota = $settings->{'defaultquota'}->{'default'};
               } elsif (defined($settings->{'default'})) {
                   $defaultquota = $settings->{'default'};
               }
         }          }
     }      }
     $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>'.$othertitle.'</td>'.                    '<td>'.$othertitle.'</td>'.
                   '<td class="LC_right_item"><span class="LC_nobreak">'.                    '<td class="LC_left_item">';
                   '<input type="text" name="defaultquota" value="'.      if ($context eq 'requestcourses') {
                   $defaultquota.'" size="5" /> Mb</span></td></tr>';          $datatable .= '<table><tr>';
       }
       my %defcell;
       foreach my $item (@usertools) {
           if ($context eq 'requestcourses') {
               my ($curroption,$currlimit);
               if (ref($settings) eq 'HASH') {
                   if (ref($settings->{$item}) eq 'HASH') {
                       $curroption = $settings->{$item}->{'default'};
                       if ($curroption =~ /^autolimit=(\d*)$/) {
                           $currlimit = $1;
                       }
                   }
               }
               if (!$curroption) {
                   $curroption = 'norequest';
               }
               $datatable .= '<th>'.$titles{$item}.'</th>';
               foreach my $option (@options) {
                   my $val = $option;
                   if ($option eq 'norequest') {
                       $val = 0;
                   }
                   if ($option eq 'validate') {
                       my $canvalidate = 0;
                       if (ref($validations{$item}) eq 'HASH') {
                           if ($validations{$item}{'default'}) {
                               $canvalidate = 1;
                           }
                       }
                       next if (!$canvalidate);
                   }
                   my $checked = '';
                   if ($option eq $curroption) {
                       $checked = ' checked="checked"';
                   } elsif ($option eq 'autolimit') {
                       if ($curroption =~ /^autolimit/) {
                           $checked = ' checked="checked"';
                       }
                   }
                   $defcell{$item} .= '<span class="LC_nobreak"><label>'.
                                     '<input type="radio" name="crsreq_'.$item.
                                     '_default" value="'.$val.'"'.$checked.' />'.
                                     $titles{$option}.'</label>';
                   if ($option eq 'autolimit') {
                       $defcell{$item} .= '&nbsp;<input type="text" name="crsreq_'.
                                          $item.'_limit_default" size="1" '.
                                          'value="'.$currlimit.'" />';
                   }
                   $defcell{$item} .= '</span> ';
                   if ($option eq 'autolimit') {
                       $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 {
               my $checked = 'checked="checked" ';
               if (ref($settings) eq 'HASH') {
                   if (ref($settings->{$item}) eq 'HASH') {
                       if ($settings->{$item}->{'default'} == 0) {
                           $checked = '';
                       } elsif ($settings->{$item}->{'default'} == 1) {
                           $checked = 'checked="checked" ';
                       }
                   }
               }
               $datatable .= '<span class="LC_nobreak"><label>'.
                             '<input type="checkbox" name="'.$context.'_'.$item.
                             '" value="default" '.$checked.'/>'.$titles{$item}.
                             '</label></span>&nbsp; ';
           }
       }
       if ($context eq 'requestcourses') {
           $datatable .= '</tr><tr>';
           foreach my $item (@usertools) {
               $datatable .= '<td style="vertical-align: top">'.$defcell{$item}.'</td>';
           }
           $datatable .= '</tr></table>';
       }
       $datatable .= '</td>';
       unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
           $datatable .= '<td class="LC_right_item"><span class="LC_nobreak">'.
                         '<input type="text" name="defaultquota" value="'.
                         $defaultquota.'" size="5" /> Mb</span></td>';
       }
       $datatable .= '</tr>';
       $typecount ++;
       $css_class = $typecount%2?' class="LC_odd_row"':'';
       $datatable .= '<tr'.$css_class.'>'.
                     '<td>'.&mt('LON-CAPA Advanced Users').' ';
       if ($context eq 'requestcourses') {
           $datatable .= &mt('(overrides affiliation, if set)').
                         '</td>'.
                         '<td class="LC_left_item">'.
                         '<table><tr>';
       } else {
           $datatable .= &mt('(overrides affiliation, if checked)').
                         '</td>'.
                         '<td class="LC_left_item" colspan="2">'.
                         '<br />';
       }
       my %advcell;
       foreach my $item (@usertools) {
           if ($context eq 'requestcourses') {
               my ($curroption,$currlimit);
               if (ref($settings) eq 'HASH') {
                   if (ref($settings->{$item}) eq 'HASH') {
                       $curroption = $settings->{$item}->{'_LC_adv'};
                       if ($curroption =~ /^autolimit=(\d*)$/) {
                           $currlimit = $1;
                       }
                   }
               }
               $datatable .= '<th>'.$titles{$item}.'</th>';
               my $checked = '';
               if ($curroption eq '') {
                   $checked = ' checked="checked"';
               }
               $advcell{$item} .= '<span class="LC_nobreak"><label>'.
                                  '<input type="radio" name="crsreq_'.$item.
                                  '__LC_adv" value=""'.$checked.' />'.
                                  &mt('No override set').'</label></span>&nbsp; ';
               foreach my $option (@options) {
                   my $val = $option;
                   if ($option eq 'norequest') {
                       $val = 0;
                   }
                   if ($option eq 'validate') {
                       my $canvalidate = 0;
                       if (ref($validations{$item}) eq 'HASH') {
                           if ($validations{$item}{'_LC_adv'}) {
                               $canvalidate = 1;
                           }
                       }
                       next if (!$canvalidate);
                   }
                   my $checked = '';
                   if ($val eq $curroption) {
                       $checked = ' checked="checked"';
                   } elsif ($option eq 'autolimit') {
                       if ($curroption =~ /^autolimit/) {
                           $checked = ' checked="checked"';
                       }
                   }
                   $advcell{$item} .= '<span class="LC_nobreak"><label>'.
                                     '<input type="radio" name="crsreq_'.$item.
                                     '__LC_adv" value="'.$val.'"'.$checked.' />'.
                                     $titles{$option}.'</label>';
                   if ($option eq 'autolimit') {
                       $advcell{$item} .= '&nbsp;<input type="text" name="crsreq_'.
                                          $item.'_limit__LC_adv" size="1" '.
                                          'value="'.$currlimit.'" />';
                   }
                   $advcell{$item} .= '</span> ';
                   if ($option eq 'autolimit') {
                       $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 {
               my $checked = 'checked="checked" ';
               if (ref($settings) eq 'HASH') {
                   if (ref($settings->{$item}) eq 'HASH') {
                       if ($settings->{$item}->{'_LC_adv'} == 0) {
                           $checked = '';
                       } elsif ($settings->{$item}->{'_LC_adv'} == 1) {
                           $checked = 'checked="checked" ';
                       }
                   }
               }
               $datatable .= '<span class="LC_nobreak"><label>'.
                             '<input type="checkbox" name="'.$context.'_'.$item.
                             '" value="_LC_adv" '.$checked.'/>'.$titles{$item}.
                             '</label></span>&nbsp; ';
           }
       }
       if ($context eq 'requestcourses') {
           $datatable .= '</tr><tr>';
           foreach my $item (@usertools) {
               $datatable .= '<td style="vertical-align: top">'.$advcell{$item}.'</td>';
           }
           $datatable .= '</tr></table>';
       }
       $datatable .= '</td></tr>';
     $$rowtotal += $typecount;      $$rowtotal += $typecount;
     return $datatable;      return $datatable;
 }  }
   
   sub print_requestmail {
       my ($dom,$action,$settings,$rowtotal) = @_;
       my ($now,$datatable,%dompersonnel,@domcoord,@currapproval,$rows);
       $now = time;
       $rows = 0;
       %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc'],$now,$now);
       foreach my $server (keys(%dompersonnel)) {
           foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {
               my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user);
               if (!grep(/^$uname:$udom$/,@domcoord)) {
                   push(@domcoord,$uname.':'.$udom);
               }
           }
       }
       if (ref($settings) eq 'HASH') {
           if (ref($settings->{'notify'}) eq 'HASH') {
               if ($settings->{'notify'}{'approval'} ne '') {
                  @currapproval = split(',',$settings->{'notify'}{'approval'});
               }
           }
       }
       if (@currapproval) {
           foreach my $dc (@currapproval) {
               unless (grep(/^\Q$dc\E$/,@domcoord)) {
                   push(@domcoord,$dc);
               }
           }
       }
       @domcoord = sort(@domcoord);
       my $numinrow = 4;
       my $numdc = @domcoord;
       my $css_class = 'class="LC_odd_row"';
       my $text;
       if ($action eq 'requestcourses') {
           $text = &mt('Receive notification of course requests requiring approval');
       } else {
           $text = &mt('Receive notification of authoring space requests requiring approval')
       }
       $datatable = '<tr '.$css_class.'>'.
                    ' <td>'.$text.'</td>'.
                    ' <td class="LC_left_item">';
       if (@domcoord > 0) {
           $datatable .= '<table>';
           for (my $i=0; $i<$numdc; $i++) {
               my $rem = $i%($numinrow);
               if ($rem == 0) {
                   if ($i > 0) {
                       $datatable .= '</tr>';
                   }
                   $datatable .= '<tr>';
                   $rows ++;
               }
               my $check = ' ';
               if (grep(/^\Q$domcoord[$i]\E$/,@currapproval)) {
                   $check = ' checked="checked" ';
               }
               my ($uname,$udom) = split(':',$domcoord[$i]);
               my $fullname = &Apache::loncommon::plainname($uname,$udom);
               if ($i == $numdc-1) {
                   my $colsleft = $numinrow-$rem;
                   if ($colsleft > 1) {
                       $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
                   } else {
                       $datatable .= '<td class="LC_left_item">';
                   }
               } else {
                   $datatable .= '<td class="LC_left_item">';
               }
               $datatable .= '<span class="LC_nobreak"><label>'.
                             '<input type="checkbox" name="reqapprovalnotify" '.
                             'value="'.$domcoord[$i].'"'.$check.'/>'.
                             $fullname.' ('.$uname.':'.$udom.')</label></span></td>';
           }
           $datatable .= '</tr></table>';
       } else {
           $datatable .= &mt('There are no active Domain Coordinators');
           $rows ++;
       }
       $datatable .='</td></tr>';
       $$rowtotal += $rows;
       return $datatable;
   }
   
 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),
     my ($defdom,$runon,$runoff);      my ($defdom,$runon,$runoff,$coownerson,$coownersoff);
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (exists($settings->{'run'})) {          if (exists($settings->{'run'})) {
             if ($settings->{'run'} eq '0') {              if ($settings->{'run'} eq '0') {
Line 1195  sub print_autoenroll { Line 2033  sub print_autoenroll {
                 $runon = ' ';                  $runon = ' ';
             }              }
         }          }
           if (exists($settings->{'co-owners'})) {
               if ($settings->{'co-owners'} eq '0') {
                   $coownersoff = ' checked="checked" ';
                   $coownerson = ' ';
               } else {
                   $coownerson = ' checked="checked" ';
                   $coownersoff = ' ';
               }
           } else {
               $coownersoff = ' checked="checked" ';
               $coownerson = ' ';
           }
         if (exists($settings->{'sender_domain'})) {          if (exists($settings->{'sender_domain'})) {
             $defdom = $settings->{'sender_domain'};              $defdom = $settings->{'sender_domain'};
         }          }
Line 1225  sub print_autoenroll { Line 2075  sub print_autoenroll {
                   &mt('username').':&nbsp;'.                    &mt('username').':&nbsp;'.
                   '<input type="text" name="sender_uname" value="'.                    '<input type="text" name="sender_uname" value="'.
                   $notif_sender.'" size="10" />&nbsp;&nbsp;'.&mt('domain').                    $notif_sender.'" size="10" />&nbsp;&nbsp;'.&mt('domain').
                   ':&nbsp;'.$domform.'</span></td></tr>';                    ':&nbsp;'.$domform.'</span></td></tr>'.
     $$rowtotal += 2;                    '<tr class="LC_odd_row">'.
                     '<td>'.&mt('Automatically assign co-ownership').'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                     '<input type="radio" name="autoassign_coowners"'.
                     $coownerson.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                     '<label><input type="radio" name="autoassign_coowners"'.
                     $coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.
                     '</tr>';
       $$rowtotal += 3;
     return $datatable;      return $datatable;
 }  }
   
Line 1268  sub print_autoupdate { Line 2126  sub print_autoupdate {
                   $classlistsoff.'value="0" />'.&mt('No').'</label></span></td>'.                    $classlistsoff.'value="0" />'.&mt('No').'</label></span></td>'.
                   '</tr>';                    '</tr>';
         $$rowtotal += 2;          $$rowtotal += 2;
       } elsif ($position eq 'middle') {
           my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
           my $numinrow = 3;
           my $locknamesettings;
           $datatable .= &insttypes_row($settings,$types,$usertypes,
                                        $dom,$numinrow,$othertitle,
                                       'lockablenames');
           $$rowtotal ++;
     } else {      } else {
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);          my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
         my @fields = ('lastname','firstname','middlename','gen',          my @fields = ('lastname','firstname','middlename','generation',
                       'permanentemail','id');                        'permanentemail','id');
         my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();          my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
         my $numrows = 0;          my $numrows = 0;
Line 1291  sub print_autoupdate { Line 2157  sub print_autoupdate {
     return $datatable;      return $datatable;
 }  }
   
   sub print_autocreate {
       my ($dom,$settings,$rowtotal) = @_;
       my (%createon,%createoff);
       my $curr_dc;
       my @types = ('xml','req');
       if (ref($settings) eq 'HASH') {
           foreach my $item (@types) {
               $createoff{$item} = ' checked="checked" ';
               $createon{$item} = ' ';
               if (exists($settings->{$item})) {
                   if ($settings->{$item}) {
                       $createon{$item} = ' checked="checked" ';
                       $createoff{$item} = ' ';
                   }
               }
           }
           $curr_dc = $settings->{'xmldc'};
       } else {
           foreach my $item (@types) {
               $createoff{$item} = ' checked="checked" ';
               $createon{$item} = ' ';
           }
       }
       $$rowtotal += 2;
       my $datatable='<tr class="LC_odd_row">'.
                     '<td>'.&mt('Create pending official courses from XML files').'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                     '<input type="radio" name="autocreate_xml"'.
                     $createon{'xml'}.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                     '<label><input type="radio" name="autocreate_xml"'.
                     $createoff{'xml'}.' value="0" />'.&mt('No').'</label></span>'.
                     '</td></tr><tr>'.
                     '<td>'.&mt('Create pending requests for official courses (if validated)').'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                     '<input type="radio" name="autocreate_req"'.
                     $createon{'req'}.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                     '<label><input type="radio" name="autocreate_req"'.
                     $createoff{'req'}.' value="0" />'.&mt('No').'</label></span>';
       my ($numdc,$dctable) = &active_dc_picker($dom,$curr_dc);
       if ($numdc > 1) {
           $datatable .= '</td></tr><tr class="LC_odd_row"><td>'.
                         &mt('Course creation processed as: (choose Dom. Coord.)').
                         '</td><td class="LC_left_item">'.$dctable.'</td></tr>';
           $$rowtotal ++ ;
       } else {
           $datatable .= $dctable.'</td></tr>';
       }
       return $datatable;
   }
   
 sub print_directorysrch {  sub print_directorysrch {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my $srchon = ' ';      my $srchon = ' ';
Line 1351  sub print_directorysrch { Line 2267  sub print_directorysrch {
     $$rowtotal += 2;      $$rowtotal += 2;
     if (ref($usertypes) eq 'HASH') {      if (ref($usertypes) eq 'HASH') {
         if (keys(%{$usertypes}) > 0) {          if (keys(%{$usertypes}) > 0) {
             $datatable .= &users_cansearch_row($settings,$types,$usertypes,$dom,              $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,
                                                $numinrow,$othertitle);                                           $numinrow,$othertitle,'cansearch');
             $cansrchrow = 1;              $cansrchrow = 1;
         }          }
     }      }
Line 1367  sub print_directorysrch { Line 2283  sub print_directorysrch {
     foreach my $title (@{$titleorder}) {      foreach my $title (@{$titleorder}) {
         if (defined($searchtitles->{$title})) {          if (defined($searchtitles->{$title})) {
             my $check = ' ';              my $check = ' ';
             if (ref($settings) eq 'HASH') {               if (ref($settings) eq 'HASH') {
                 if (ref($settings->{'searchby'}) eq 'ARRAY') {                  if (ref($settings->{'searchby'}) eq 'ARRAY') {
                     if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) {                      if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) {
                         $check = ' checked="checked" ';                          $check = ' checked="checked" ';
Line 1408  sub print_contacts { Line 2324  sub print_contacts {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my $datatable;      my $datatable;
     my @contacts = ('adminemail','supportemail');      my @contacts = ('adminemail','supportemail');
     my (%checked,%to,%otheremails);      my (%checked,%to,%otheremails,%bccemails);
     my @mailings = ('errormail','packagesmail','helpdeskmail');      my @mailings = ('errormail','packagesmail','lonstatusmail','helpdeskmail',
                       'requestsmail');
     foreach my $type (@mailings) {      foreach my $type (@mailings) {
         $otheremails{$type} = '';          $otheremails{$type} = '';
     }      }
       $bccemails{'helpdeskmail'} = '';
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         foreach my $item (@contacts) {          foreach my $item (@contacts) {
             if (exists($settings->{$item})) {              if (exists($settings->{$item})) {
Line 1428  sub print_contacts { Line 2346  sub print_contacts {
                         }                          }
                     }                      }
                     $otheremails{$type} = $settings->{$type}{'others'};                      $otheremails{$type} = $settings->{$type}{'others'};
                       if ($type eq 'helpdeskmail') {
                           $bccemails{$type} = $settings->{$type}{'bcc'};
                       }
                 }                  }
               } elsif ($type eq 'lonstatusmail') {
                   $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';
             }              }
         }          }
     } else {      } else {
Line 1436  sub print_contacts { Line 2359  sub print_contacts {
         $to{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'};          $to{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'};
         $checked{'errormail'}{'adminemail'} = ' checked="checked" ';          $checked{'errormail'}{'adminemail'} = ' checked="checked" ';
         $checked{'packagesmail'}{'adminemail'} = ' checked="checked" ';          $checked{'packagesmail'}{'adminemail'} = ' checked="checked" ';
         $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';           $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';
           $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" '; 
           $checked{'requestsmail'}{'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) {
         if ($rownum%2) {          $rownum ++;
             $css_class = '';          $css_class = $rownum%2?' class="LC_odd_row"':'';
         } else {  
             $css_class = ' 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) {
         if ($rownum%2) {          $rownum ++;
             $css_class = '';          $css_class = $rownum%2?' class="LC_odd_row"':'';
         } else {  
             $css_class = ' class="LC_odd_row" ';  
         }  
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                       '<td><span class="LC_nobreak">'.                        '<td><span class="LC_nobreak">'.
                       $titles->{$type}.': </span></td>'.                        $titles->{$type}.': </span></td>'.
Line 1474  sub print_contacts { Line 2392  sub print_contacts {
         }          }
         $datatable .= '</span><br />'.&mt('Others').':&nbsp;&nbsp;'.          $datatable .= '</span><br />'.&mt('Others').':&nbsp;&nbsp;'.
                       '<input type="text" name="'.$type.'_others" '.                        '<input type="text" name="'.$type.'_others" '.
                       'value="'.$otheremails{$type}.'"  />'.                        'value="'.$otheremails{$type}.'"  />';
                       '</td></tr>'."\n";          if ($type eq 'helpdeskmail') {
         $rownum ++;              $datatable .= '<br />'.&mt('Bcc:').('&nbsp;'x6).
                             '<input type="text" name="'.$type.'_bcc" '.
                             'value="'.$bccemails{$type}.'"  />';
           }
           $datatable .= '</td></tr>'."\n";
     }      }
     $$rowtotal += $rownum;      $$rowtotal += $rownum;
     return $datatable;      return $datatable;
 }  }
   
   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',);
   
       ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
                                                    \%choices,$itemcount);
       return $datatable;
   }
   
   sub radiobutton_prefs {
       my ($settings,$toggles,$defaultchecked,$choices,$itemcount) = @_;
       return unless ((ref($toggles) eq 'ARRAY') && (ref($defaultchecked) eq 'HASH') &&
                      (ref($choices) eq 'HASH'));
   
       my (%checkedon,%checkedoff,$datatable,$css_class);
   
       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 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 ++;
       }
       return ($datatable,$itemcount);
   }
   
   sub print_coursedefaults {
       my ($position,$dom,$settings,$rowtotal) = @_;
       my ($css_class,$datatable);
       my $itemcount = 1;
       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');
           @toggles = ('canuse_pdfforms',);
           ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
                                                    \%choices,$itemcount);
           $$rowtotal += $itemcount;
       } else {
           $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
           my %choices =
               &Apache::lonlocal::texthash (
                   anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',
           );
           my $currdefresponder;
           if (ref($settings) eq 'HASH') {
               $currdefresponder = $settings->{'anonsurvey_threshold'};
           }
           if (!$currdefresponder) {
               $currdefresponder = 10;
           } elsif ($currdefresponder < 1) {
               $currdefresponder = 1;
           }
           $datatable .=
                  '<tr'.$css_class.'><td><span class="LC_nobreak">'.$choices{'anonsurvey_threshold'}.
                   '</span></td>'.
                   '<td class="LC_right_item"><span class="LC_nobreak">'.
                   '<input type="text" name="anonsurvey_threshold"'.
                   ' value="'.$currdefresponder.'" size="5" /></span>'.
                   '</td></tr>';
       }
       return $datatable;
   }
   
   sub print_usersessions {
       my ($position,$dom,$settings,$rowtotal) = @_;
       my ($css_class,$datatable,%checked,%choices);
       my (%by_ip,%by_location,@intdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location);
   
       my @alldoms = &Apache::lonnet::all_domains();
       my %serverhomes = %Apache::lonnet::serverhomeIDs;
       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);
                       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;
       return $datatable;
   }
   
   sub build_location_hashes {
       my ($intdoms,$by_ip,$by_location) = @_;
       return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') &&
                     (ref($by_location) eq 'HASH')); 
       my %iphost = &Apache::lonnet::get_iphost();
       my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary');
       my $primary_ip = &Apache::lonnet::get_host_ip($primary_id);
       if (ref($iphost{$primary_ip}) eq 'ARRAY') {
           foreach my $id (@{$iphost{$primary_ip}}) {
               my $intdom = &Apache::lonnet::internet_dom($id);
               unless(grep(/^\Q$intdom\E$/,@{$intdoms})) {
                   push(@{$intdoms},$intdom);
               }
           }
       }
       foreach my $ip (keys(%iphost)) {
           if (ref($iphost{$ip}) eq 'ARRAY') {
               foreach my $id (@{$iphost{$ip}}) {
                   my $location = &Apache::lonnet::internet_dom($id);
                   if ($location) {
                       next if (grep(/^\Q$location\E$/,@{$intdoms}));
                       if (ref($by_ip->{$ip}) eq 'ARRAY') {
                           unless(grep(/^\Q$location\E$/,@{$by_ip->{$ip}})) {
                               push(@{$by_ip->{$ip}},$location);
                           }
                       } else {
                           $by_ip->{$ip} = [$location];
                       }
                   }
               }
           }
       }
       foreach my $ip (sort(keys(%{$by_ip}))) {
           if (ref($by_ip->{$ip}) eq 'ARRAY') {
               @{$by_ip->{$ip}} = sort(@{$by_ip->{$ip}});
               my $first = $by_ip->{$ip}->[0];
               if (ref($by_location->{$first}) eq 'ARRAY') {
                   unless (grep(/^\Q$ip\E$/,@{$by_location->{$first}})) {
                       push(@{$by_location->{$first}},$ip);
                   }
               } else {
                   $by_location->{$first} = [$ip];
               }
           }
       }
       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 = 6;
       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')) {
                   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),
                        );
       my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external');
       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 = ('default','homeserver');
       my %ruletitles = &offloadtype_text();
       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')) {
           $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',
       );
       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',
                    'adminemail'    => 'Default Server Admin E-mail address',                     'adminemail'   => 'Default Server Admin E-mail address',
                    'errormail'    => 'Error reports to be e-mailed to',                     'errormail'    => 'Error reports to be e-mailed to',
                    'packagesmail' => 'Package update alerts to be e-mailed to',                     'packagesmail' => 'Package update alerts to be e-mailed to',
                    '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)',
                      'requestsmail' => 'E-mail from course requests requiring approval',
                  );                   );
     my %short_titles = &Apache::lonlocal::texthash (      my %short_titles = &Apache::lonlocal::texthash (
                            adminemail   => 'Admin E-mail address',                             adminemail   => 'Admin E-mail address',
Line 1497  sub contact_titles { Line 3260  sub contact_titles {
     return (\%titles,\%short_titles);      return (\%titles,\%short_titles);
 }  }
   
   sub tool_titles {
       my %titles = &Apache::lonlocal::texthash (
                        aboutme    => 'Personal web page',
                        blog       => 'Blog',
                        webdav     => 'WebDAV',
                        portfolio  => 'Portfolio',
                        official   => 'Official courses (with institutional codes)',
                        unofficial => 'Unofficial courses',
                        community  => 'Communities',
                    );
       return %titles;
   }
   
   sub courserequest_titles {
       my %titles = &Apache::lonlocal::texthash (
                                      official   => 'Official',
                                      unofficial => 'Unofficial',
                                      community  => 'Communities',
                                      norequest  => 'Not allowed',
                                      approval   => 'Approval by Dom. Coord.',
                                      validate   => 'With validation',
                                      autolimit  => 'Numerical limit',
                                      unlimited  => '(blank for unlimited)',
                    );
       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 {
       my %conditions = &Apache::lonlocal::texthash (
          approval    => '(Processing of request subject to approval by Domain Coordinator).',
          validate   => '(Processing of request subject to instittutional validation).',
                    );
       return %conditions;
   }
   
   
 sub print_usercreation {  sub print_usercreation {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my $numinrow = 4;      my $numinrow = 4;
Line 1538  sub print_usercreation { Line 3346  sub print_usercreation {
             $rowcount ++;              $rowcount ++;
         }          }
     } elsif ($position eq 'middle') {      } elsif ($position eq 'middle') {
         my @creators = ('author','course','selfcreate');          my @creators = ('author','course','requestcrs','selfcreate');
         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();
Line 1615  sub print_usercreation { Line 3423  sub print_usercreation {
             }              }
             $datatable .= '</td></tr>';              $datatable .= '</td></tr>';
         }          }
           my ($othertitle,$usertypes,$types) =
               &Apache::loncommon::sorted_inst_types($dom);
           my $createsettings;
           if (ref($settings) eq 'HASH') {
               $createsettings = $settings->{cancreate};
           }
           if (ref($usertypes) eq 'HASH') {
               if (keys(%{$usertypes}) > 0) {
                   $datatable .= &insttypes_row($createsettings,$types,$usertypes,
                                                $dom,$numinrow,$othertitle,
                                                'statustocreate');
                   $$rowtotal ++;
                   $rownum ++;
               }
           }
           $datatable .= &captcha_choice('cancreate',$createsettings,$rownum);
     } 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 1666  sub print_usercreation { Line 3490  sub print_usercreation {
     return $datatable;      return $datatable;
 }  }
   
   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 (e-mail as username)');
       } 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 1676  sub user_formats_row { Line 3558  sub user_formats_row {
                );                 );
     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.'>'.
               '<td><span class="LC_nobreak">'.                '<td><span class="LC_nobreak">';
               &mt("Format rules to check for $text{$type}: ").      if ($type eq 'email') {
               '</span></td>'.          $output .= &mt("Formats disallowed for $text{$type}: ");
               '<td class="LC_left_item" colspan="2"><table>';      } else {
           $output .= &mt("Format rules to check for $text{$type}: ");
       }
       $output .= '</span></td>'.
                  '<td class="LC_left_item" colspan="2"><table>';
     my $rem;      my $rem;
     if (ref($ruleorder) eq 'ARRAY') {      if (ref($ruleorder) eq 'ARRAY') {
         for (my $i=0; $i<@{$ruleorder}; $i++) {          for (my $i=0; $i<@{$ruleorder}; $i++) {
Line 1723  sub usercreation_types { Line 3609  sub usercreation_types {
     my %lt = &Apache::lonlocal::texthash (      my %lt = &Apache::lonlocal::texthash (
                     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',
                     selfcreate => 'User creates own account',                       selfcreate => 'User creates own account', 
                     any        => 'Any',                      any        => 'Any',
                     official   => 'Institutional only ',                      official   => 'Institutional only ',
                     unofficial => 'Non-institutional only',                      unofficial => 'Non-institutional only',
                     email      => 'Email address',                      email      => 'E-mail address',
                     login      => 'Institutional Login',                      login      => 'Institutional Login',
                     sso        => 'SSO',                       sso        => 'SSO', 
                     none       => 'None',                      none       => 'None',
Line 1767  sub print_usermodification { Line 3654  sub print_usermodification {
             $$rowtotal ++;              $$rowtotal ++;
             $rowcount ++;              $rowcount ++;
         }          }
     } else {      } elsif ($position eq 'middle') {
         $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 1776  sub print_usermodification { Line 3663  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 ($dom,$rowtotal) = @_;
     my @items = ('auth_def','auth_arg_def','lang_def');      my @items = ('auth_def','auth_arg_def','lang_def','timezone_def',
                    'datelocale_def','portal_def');
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
     my $titles = &defaults_titles();      my $titles = &defaults_titles($dom);
     my $rownum = 0;      my $rownum = 0;
     my ($datatable,$css_class);      my ($datatable,$css_class);
     foreach my $item (@items) {      foreach my $item (@items) {
Line 1814  sub print_defaults { Line 3716  sub print_defaults {
                               '" value="'.$auth.'"'.$checked.'/>'.                                '" value="'.$auth.'"'.$checked.'/>'.
                               $authnames{$shortauth{$auth}}.'</label>&nbsp;&nbsp;';                                $authnames{$shortauth{$auth}}.'</label>&nbsp;&nbsp;';
             }              }
         } else {          } 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);
           } elsif ($item eq 'lang_def') {
               my %langchoices = &get_languages_hash();
               $langchoices{''} = 'No language preference';
               %langchoices = &Apache::lonlocal::texthash(%langchoices);
               $datatable .= &Apache::loncommon::select_form($domdefaults{$item},$item,
                                                             \%langchoices);
           } else {
               my $size;
               if ($item eq 'portal_def') {
                   $size = ' size="25"';
               }
             $datatable .= '<input type="text" name="'.$item.'" value="'.              $datatable .= '<input type="text" name="'.$item.'" value="'.
                           $domdefaults{$item}.'" />';                            $domdefaults{$item}.'"'.$size.' />';
         }          }
         $datatable .= '</td></tr>';          $datatable .= '</td></tr>';
         $rownum ++;          $rownum ++;
Line 1825  sub print_defaults { Line 3743  sub print_defaults {
     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',
                      '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);
 }  }
   
 sub print_scantronformat {  sub print_scantronformat {
     my ($r,$dom,$confname,$settings,$rowtotal) = @_;      my ($r,$dom,$confname,$settings,$rowtotal) = @_;
     my $itemcount = 1;      my $itemcount = 1;
     my ($datatable,$css_class,$scantronurl,$is_custom,%error,%scantronurls);      my ($datatable,$css_class,$scantronurl,$is_custom,%error,%scantronurls,
           %confhash);
     my $switchserver = &check_switchserver($dom,$confname);      my $switchserver = &check_switchserver($dom,$confname);
     my %lt = &Apache::lonlocal::texthash (      my %lt = &Apache::lonlocal::texthash (
                 default => 'Default scantron format file error',                  default => 'Default bubblesheet format file error',
                 custom  => 'Custom scantron format file error',                  custom  => 'Custom bubblesheet format file error',
              );               );
     my %scantronfiles = (      my %scantronfiles = (
         default => 'default.tab',          default => 'default.tab',
Line 1864  sub print_scantronformat { Line 3808  sub print_scantronformat {
                     );                      );
                     my %md5chk;                      my %md5chk;
                     foreach my $type (keys(%legacyfile)) {                      foreach my $type (keys(%legacyfile)) {
                         $md5chk{$type} = split(/ /,`md5sum $legacyfile{$type}`);                          ($md5chk{$type}) = split(/ /,`md5sum $legacyfile{$type}`);
                         chop($md5chk{$type});                          chomp($md5chk{$type});
                     }                      }
                     if ($md5chk{'default'} ne $md5chk{'custom'}) {                      if ($md5chk{'default'} ne $md5chk{'custom'}) {
                         foreach my $type (keys(%legacyfile)) {                          foreach my $type (keys(%legacyfile)) {
                             ($scantronurls{$type},$error{$type}) =                               ($scantronurls{$type},my $error) = 
                                 &legacy_scantronformat($r,$dom,$confname,                                  &legacy_scantronformat($r,$dom,$confname,
                                                  $type,$legacyfile{$type},                                                   $type,$legacyfile{$type},
                                                  $scantronurls{$type},                                                   $scantronurls{$type},
                                                  $scantronfiles{$type});                                                   $scantronfiles{$type});
                               if ($error ne '') {
                                   $error{$type} = $error;
                               }
                           }
                           if (keys(%error) == 0) {
                               $is_custom = 1;
                               $confhash{'scantron'}{'scantronformat'} = 
                                   $scantronurls{'custom'};
                               my $putresult = 
                                   &Apache::lonnet::put_dom('configuration',
                                                            \%confhash,$dom);
                               if ($putresult ne 'ok') {
                                   $error{'custom'} = 
                                       '<span class="LC_error">'.
                                       &mt('An error occurred updating the domain configuration: [_1]',$putresult).'</span>';
                               }
                         }                          }
                     } else {                      } else {
                         ($scantronurls{'default'},$error{'default'}) =                          ($scantronurls{'default'},my $error) =
                             &legacy_scantronformat($r,$dom,$confname,                              &legacy_scantronformat($r,$dom,$confname,
                                           'default',$legacyfile{'default'},                                            'default',$legacyfile{'default'},
                                           $scantronurls{'default'},                                            $scantronurls{'default'},
                                           $scantronfiles{'default'});                                            $scantronfiles{'default'});
                           if ($error eq '') {
                               $confhash{'scantron'}{'scantronformat'} = ''; 
                               my $putresult =
                                   &Apache::lonnet::put_dom('configuration',
                                                            \%confhash,$dom);
                               if ($putresult ne 'ok') {
                                   $error{'default'} =
                                       '<span class="LC_error">'.
                                       &mt('An error occurred updating the domain configuration: [_1]',$putresult).'</span>';
                               }
                           } else {
                               $error{'default'} = $error;
                           }
                     }                      }
                 }                  }
             }              }
         } else {          } else {
             $error{'default'} = &mt("Unable to copy default scantron formatfile to domain's RES space: [_1]",$switchserver);              $error{'default'} = &mt("Unable to copy default bubblesheet formatfile to domain's RES space: [_1]",$switchserver);
         }          }
     }      }
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
Line 1901  sub print_scantronformat { Line 3874  sub print_scantronformat {
             $scantronurl = $scantronurls{'default'};              $scantronurl = $scantronurls{'default'};
         }          }
     } else {      } else {
         $scantronurl = $scantronurls{'default'};          if ($is_custom) {
               $scantronurl = $scantronurls{'custom'};
           } else {
               $scantronurl = $scantronurls{'default'};
           }
     }      }
     $css_class = $itemcount%2?' class="LC_odd_row"':'';      $css_class = $itemcount%2?' class="LC_odd_row"':'';
     $datatable .= '<tr'.$css_class.'>';      $datatable .= '<tr'.$css_class.'>';
     if (!$is_custom) {      if (!$is_custom) {
         $datatable .= '<td>'.&mt('Default in use:').'<br />';          $datatable .= '<td>'.&mt('Default in use:').'<br />'.
                         '<span class="LC_nobreak">';
         if ($scantronurl) {          if ($scantronurl) {
             $datatable .= '<a href="'.$scantronurl.'" target="_blank">'.              $datatable .= '<a href="'.$scantronurl.'" target="_blank">'.
                           &mt('Default scantron format file').'</a>';                            &mt('Default bubblesheet format file').'</a>';
         } else {          } else {
             $datatable = &mt('File unavailable for display');              $datatable = &mt('File unavailable for display');
         }          }
         $datatable .= '</td><td valign="bottom">'.&mt('Upload:').'<br />';          $datatable .= '</span></td>';
           if (keys(%error) == 0) { 
               $datatable .= '<td valign="bottom">';
               if (!$switchserver) {
                   $datatable .= &mt('Upload:').'<br />';
               }
           } else {
               my $errorstr;
               foreach my $key (sort(keys(%error))) {
                   $errorstr .= $lt{$key}.': '.$error{$key}.'<br />';
               }
               $datatable .= '<td>'.$errorstr;
           }
     } else {      } else {
         if (keys(%error) > 0) {          if (keys(%error) > 0) {
             my $errorstr;              my $errorstr;
             foreach my $key (sort(keys(%error))) {              foreach my $key (sort(keys(%error))) {
                 $errorstr .= $lt{$key}.': '.$error{$key}.'<br />';                  $errorstr .= $lt{$key}.': '.$error{$key}.'<br />';
             }               } 
             $datatable .= '<td>'.$errorstr.'</td><td>';              $datatable .= '<td>'.$errorstr.'</td><td>&nbsp;';
         } elsif ($scantronurl) {          } elsif ($scantronurl) {
             $datatable .= '<td><a href="'.$scantronurl.'" target="_blank">'                          .&mt('Custom scantron format file').'</a>'              $datatable .= '<td><span class="LC_nobreak">'.
                           .'<span class="LC_nobreak"><label>'                            '<a href="'.$scantronurl.'" target="_blank">'.
                           .'<input type="checkbox" name="scantronformat_del"'                            &mt('Custom bubblesheet format file').'</a><label>'.
                           .'" value="1" />'.&mt('Delete?').'</label></td>'                            '<input type="checkbox" name="scantronformat_del"'.
                           .'<td>'.&mt('Replace:').'</span><br />';                            '" value="1" />'.&mt('Delete?').'</label></span></td>'.
                             '<td><span class="LC_nobreak">&nbsp;'.
                             &mt('Replace:').'</span><br />';
         }          }
     }      }
     if (keys(%error) == 0) {      if (keys(%error) == 0) {
         if ($switchserver) {          if ($switchserver) {
             $datatable .= &mt('Upload to library server: [_1]',$switchserver);              $datatable .= &mt('Upload to library server: [_1]',$switchserver);
         } else {          } else {
             $datatable .='&nbsp;<input type="file" name="scantronformat" />';              $datatable .='<span class="LC_nobreak">&nbsp;'.
                            '<input type="file" name="scantronformat" /></span>';
         }          }
     }      }
     $datatable .= '</td></tr>';      $datatable .= '</td></tr>';
Line 1950  sub legacy_scantronformat { Line 3943  sub legacy_scantronformat {
             &publishlogo($r,'copy',$legacyfile,$dom,$confname,'scantron',              &publishlogo($r,'copy',$legacyfile,$dom,$confname,'scantron',
                          '','',$newfile);                           '','',$newfile);
         if ($result ne 'ok') {          if ($result ne 'ok') {
             $error = &mt("An error occurred publishing the [_1] scantron format file in RES space. Error was: [_2].",$newfile,$result);              $error = &mt("An error occurred publishing the [_1] bubblesheet format file in RES space. Error was: [_2].",$newfile,$result);
         }          }
     }      }
     return ($url,$error);      return ($url,$error);
 }  }
   
 sub print_coursecategories {  sub print_coursecategories {
     my ($dom,$hdritem,$settings,$rowtotal) = @_;      my ($position,$dom,$hdritem,$settings,$rowtotal) = @_;
     my ($datatable,$css_class);      my $datatable;
     my $itemcount = 1;      if ($position eq 'top') {
     if (ref($settings) eq 'HASH') {          my $toggle_cats_crs = ' ';
         my (@cats,@trails,%allitems,%idx,@jsarray);          my $toggle_cats_dom = ' checked="checked" ';
         &extract_categories($settings,\@cats,\@trails,\%allitems,\%idx,\@jsarray);          my $can_cat_crs = ' ';
         my $maxdepth = scalar(@cats);          my $can_cat_dom = ' checked="checked" ';
         my $colattrib = '';          my $toggle_catscomm_comm = ' ';
         if ($maxdepth > 2) {          my $toggle_catscomm_dom = ' checked="checked" ';
             $colattrib = ' colspan="2" ';          my $can_catcomm_comm = ' ';
         }          my $can_catcomm_dom = ' checked="checked" ';
         my @path;  
         if (@cats > 0) {          if (ref($settings) eq 'HASH') {
             if (ref($cats[0]) eq 'ARRAY') {              if ($settings->{'togglecats'} eq 'crs') {
                 my $numtop = @{$cats[0]};                  $toggle_cats_crs = $toggle_cats_dom;
                 my $maxnum = $numtop;                  $toggle_cats_dom = ' ';
                 if ((!grep(/^instcode$/,@{$cats[0]})) || ($settings->{'instcode::0'} eq '')) {              }
                     $maxnum ++;              if ($settings->{'categorize'} eq 'crs') {
                 }                  $can_cat_crs = $can_cat_dom;
                 my $lastidx;                  $can_cat_dom = ' ';
                 for (my $i=0; $i<$numtop; $i++) {              }
                     my $parent = $cats[0][$i];              if ($settings->{'togglecatscomm'} eq 'comm') {
                   $toggle_catscomm_comm = $toggle_catscomm_dom;
                   $toggle_catscomm_dom = ' ';
               }
               if ($settings->{'categorizecomm'} eq 'comm') {
                   $can_catcomm_comm = $can_catcomm_dom;
                   $can_catcomm_dom = ' ';
               }
           }
           my %title = &Apache::lonlocal::texthash (
                        togglecats     => 'Show/Hide a course in catalog',
                        togglecatscomm => 'Show/Hide a community in catalog',
                        categorize     => 'Assign a category to a course',
                        categorizecomm => 'Assign a category to a community',
                       );
           my %level = &Apache::lonlocal::texthash (
                        dom  => 'Set in Domain',
                        crs  => 'Set in Course',
                        comm => 'Set in Community',
                       );
           $datatable = '<tr class="LC_odd_row">'.
                     '<td>'.$title{'togglecats'}.'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                     '<input type="radio" name="togglecats"'.
                     $toggle_cats_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.
                     '<label><input type="radio" name="togglecats"'.
                     $toggle_cats_crs.' value="crs" />'.$level{'crs'}.'</label></span></td>'.
                     '</tr><tr>'.
                     '<td>'.$title{'categorize'}.'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak">'.
                     '<label><input type="radio" name="categorize"'.
                     $can_cat_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.
                     '<label><input type="radio" name="categorize"'.
                     $can_cat_crs.'value="crs" />'.$level{'crs'}.'</label></span></td>'.
                     '</tr><tr class="LC_odd_row">'.
                     '<td>'.$title{'togglecatscomm'}.'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                     '<input type="radio" name="togglecatscomm"'.
                     $toggle_catscomm_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.
                     '<label><input type="radio" name="togglecatscomm"'.
                     $toggle_catscomm_comm.' value="comm" />'.$level{'comm'}.'</label></span></td>'.
                     '</tr><tr>'.
                     '<td>'.$title{'categorizecomm'}.'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak">'.
                     '<label><input type="radio" name="categorizecomm"'.
                     $can_catcomm_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.
                     '<label><input type="radio" name="categorizecomm"'.
                     $can_catcomm_comm.'value="comm" />'.$level{'comm'}.'</label></span></td>'.
                     '</tr>';
           $$rowtotal += 4;
       } else {
           my $css_class;
           my $itemcount = 1;
           my $cathash; 
           if (ref($settings) eq 'HASH') {
               $cathash = $settings->{'cats'};
           }
           if (ref($cathash) eq 'HASH') {
               my (@cats,@trails,%allitems,%idx,@jsarray);
               &Apache::loncommon::extract_categories($cathash,\@cats,\@trails,
                                                      \%allitems,\%idx,\@jsarray);
               my $maxdepth = scalar(@cats);
               my $colattrib = '';
               if ($maxdepth > 2) {
                   $colattrib = ' colspan="2" ';
               }
               my @path;
               if (@cats > 0) {
                   if (ref($cats[0]) eq 'ARRAY') {
                       my $numtop = @{$cats[0]};
                       my $maxnum = $numtop;
                       my %default_names = (
                             instcode    => &mt('Official courses'),
                             communities => &mt('Communities'),
                       );
   
                       if ((!grep(/^instcode$/,@{$cats[0]})) || 
                           ($cathash->{'instcode::0'} eq '') ||
                           (!grep(/^communities$/,@{$cats[0]})) || 
                           ($cathash->{'communities::0'} eq '')) {
                           $maxnum ++;
                       }
                       my $lastidx;
                       for (my $i=0; $i<$numtop; $i++) {
                           my $parent = $cats[0][$i];
                           $css_class = $itemcount%2?' class="LC_odd_row"':'';
                           my $item = &escape($parent).'::0';
                           my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$item','$idx{$item}'".');"';
                           $lastidx = $idx{$item};
                           $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
                                         .'<select name="'.$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>';
                           }
                           $datatable .= '</select></td><td>';
                           if ($parent eq 'instcode' || $parent eq 'communities') {
                               $datatable .=  '<span class="LC_nobreak">'
                                              .$default_names{$parent}.'</span>';
                               if ($parent eq 'instcode') {
                                   $datatable .= '<br /><span class="LC_nobreak">('
                                                 .&mt('with institutional codes')
                                                 .')</span></td><td'.$colattrib.'>';
                               } else {
                                   $datatable .= '<table><tr><td>';
                               }
                               $datatable .= '<span class="LC_nobreak">'
                                             .'<label><input type="radio" name="'
                                             .$parent.'" value="1" checked="checked" />'
                                             .&mt('Display').'</label>';
                               if ($parent eq 'instcode') {
                                   $datatable .= '&nbsp;';
                               } else {
                                   $datatable .= '</span></td></tr><tr><td>'
                                                 .'<span class="LC_nobreak">';
                               }
                               $datatable .= '<label><input type="radio" name="'
                                             .$parent.'" value="0" />'
                                             .&mt('Do not display').'</label></span>';
                               if ($parent eq 'communities') {
                                   $datatable .= '</td></tr></table>';
                               }
                               $datatable .= '</td>';
                           } else {
                               $datatable .= $parent
                                             .'&nbsp;<label><input type="checkbox" name="deletecategory" '
                                             .'value="'.$item.'" />'.&mt('Delete').'</label></span></td>';
                           }
                           my $depth = 1;
                           push(@path,$parent);
                           $datatable .= &build_category_rows($itemcount,\@cats,$depth,$parent,\@path,\%idx);
                           pop(@path);
                           $datatable .= '</tr><tr><td colspan="'.$maxdepth.'" class="LC_row_separator"></td></tr>';
                           $itemcount ++;
                       }
                     $css_class = $itemcount%2?' class="LC_odd_row"':'';                      $css_class = $itemcount%2?' class="LC_odd_row"':'';
                     my $item = &escape($parent).'::0';                      my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','addcategory_pos','$lastidx'".');"';
                     my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$item','$idx{$item}'".');"';                      $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak"><select name="addcategory_pos"'.$chgstr.'>';
                     $lastidx = $idx{$item};  
                     $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'  
                                   .'<select name="'.$item.'"'.$chgstr.'>';  
                     for (my $k=0; $k<=$maxnum; $k++) {                      for (my $k=0; $k<=$maxnum; $k++) {
                         my $vpos = $k+1;                          my $vpos = $k+1;
                         my $selstr;                          my $selstr;
                         if ($k == $i) {                          if ($k == $numtop) {
                             $selstr = ' selected="selected" ';                              $selstr = ' selected="selected" ';
                         }                          }
                         $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';                          $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                     }                      }
                     $datatable .= '</select></td><td>';                      $datatable .= '</select></span></td><td colspan="2">'.&mt('Add category:').'&nbsp;'
                     if ($parent eq 'instcode') {                                    .'<input type="text" size="20" name="addcategory_name" value="" /></td>'
                         $datatable .=  '<span class="LC_nobreak">'.&mt('Official courses')                                    .'</tr>'."\n";
                                        .'</span><br /><span class="LC_nobreak">('  
                                        .&mt('with institutional codes').')</span></td>'  
                                        .'<td'.$colattrib.'><span class="LC_nobreak"><label><input type="radio" name="instcode" value="1" checked="checked" />'  
                                         .&mt('Display').'</label>&nbsp;'  
                                         .'<label><input type="radio" name="instcode" value="0" />'  
                                         .&mt('Do not display').'</label></span></td>';  
                     } else {  
                         $datatable .= $parent  
                                       .'&nbsp;<label><input type="checkbox" name="deletecategory" '  
                                       .'value="'.$item.'" />'.&mt('Delete').'</label></span></td>';  
                     }  
                     my $depth = 1;  
                     push(@path,$parent);  
                     $datatable .= &build_category_rows($itemcount,\@cats,$depth,$parent,\@path,\%idx);  
                     pop(@path);  
                     $datatable .= '</tr><tr><td colspan="'.$maxdepth.'" class="LC_row_separator"></td></tr>';  
                     $itemcount ++;                      $itemcount ++;
                 }                      foreach my $default ('instcode','communities') {
                 $css_class = $itemcount%2?' class="LC_odd_row"':'';                          if ((!grep(/^\Q$default\E$/,@{$cats[0]})) || ($cathash->{$default.'::0'} eq '')) {
                 my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','addcategory_pos','$lastidx'".');"';                              $css_class = $itemcount%2?' class="LC_odd_row"':'';
                 $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak"><select name="addcategory_pos"'.$chgstr.'>';                              my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','$lastidx'".');"';
                 for (my $k=0; $k<=$maxnum; $k++) {                              $datatable .= '<tr><td colspan="'.$maxdepth.'" class="LC_row_separator"></td></tr><tr '.$css_class.'><td>'.
                     my $vpos = $k+1;                                            '<span class="LC_nobreak"><select name="'.$default.'_pos"'.$chgstr.'>';
                     my $selstr;                              for (my $k=0; $k<=$maxnum; $k++) {
                     if ($k == $numtop) {                                  my $vpos = $k+1;
                         $selstr = ' selected="selected" ';                                  my $selstr;
                     }                                  if ($k == $maxnum) {
                     $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';                                      $selstr = ' selected="selected" ';
                 }                                  }
                 $datatable .= '</select></span></td><td colspan="2">'.&mt('New:').'&nbsp;'                                  $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                               .'<input type="text" size="20" name="addcategory_name" value="" /></td>'                              }
                               .'</tr>'."\n";                              $datatable .= '</select></span></td>'.
                 $itemcount ++;                                            '<td><span class="LC_nobreak">'.
                 if ((!grep(/^instcode$/,@{$cats[0]})) || ($settings->{'instcode::0'} eq '')) {                                            $default_names{$default}.'</span>';
                     $css_class = $itemcount%2?' class="LC_odd_row"':'';                              if ($default eq 'instcode') {
                     my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','instcode_pos','$lastidx'".');"';                                  $datatable .= '<br /><span class="LC_nobreak">(' 
                     $datatable .= '<tr><td colspan="'.$maxdepth.'" class="LC_row_separator"></td></tr><tr '.$css_class.'><td>'.                                                .&mt('with institutional codes').')</span>';
                                   '<span class="LC_nobreak"><select name="instcode_pos"'.$chgstr.'>';                              }
                     for (my $k=0; $k<=$maxnum; $k++) {                              $datatable .= '</td>'
                         my $vpos = $k+1;                                            .'<td><span class="LC_nobreak"><label><input type="radio" name="'.$default.'" value="1" />'
                         my $selstr;                                            .&mt('Display').'</label>&nbsp;'
                         if ($k == $maxnum) {                                            .'<label><input type="radio" name="'.$default.'" value="0" checked="checked"/>'
                             $selstr = ' selected="selected" ';                                            .&mt('Do not display').'</label></span></td></tr>';
                         }                          }
                         $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';  
                     }                      }
                     $datatable .= '</select></span></td><td><span class="LC_nobreak">'  
                                   .&mt('Official courses').'</span>'.'<br /><span class="LC_nobreak">('  
                                   .&mt('with institutional codes').')</span></td>'  
                                   .'<td><span class="LC_nobreak"><label><input type="radio" name="instcode" value="1" />'  
                                   .&mt('Display').'</label>&nbsp;'  
                                   .'<label><input type="radio" name="instcode" value="0" checked="checked"/>'  
                                   .&mt('Do not display').'</label></span></td></tr>';  
                 }                  }
               } else {
                   $datatable .= &initialize_categories($itemcount);
             }              }
         } else {          } else {
             $datatable .= &initialize_categories($itemcount);              $datatable .= '<td class="LC_right_item">'.$hdritem->{'header'}->[0]->{'col2'}.'</td>'
                             .&initialize_categories($itemcount);
         }          }
     } else {          $$rowtotal += $itemcount;
         $datatable .= '<td class="LC_right_item">'.$hdritem->{'header'}->[0]->{'col2'}.'</td>'  
                       .&initialize_categories($itemcount);  
     }      }
     $$rowtotal += $itemcount;  
     return $datatable;      return $datatable;
 }  }
   
   sub print_serverstatuses {
       my ($dom,$settings,$rowtotal) = @_;
       my $datatable;
       my @pages = &serverstatus_pages();
       my (%namedaccess,%machineaccess);
       foreach my $type (@pages) {
           $namedaccess{$type} = '';
           $machineaccess{$type}= '';
       }
       if (ref($settings) eq 'HASH') {
           foreach my $type (@pages) {
               if (exists($settings->{$type})) {
                   if (ref($settings->{$type}) eq 'HASH') {
                       foreach my $key (keys(%{$settings->{$type}})) {
                           if ($key eq 'namedusers') {
                               $namedaccess{$type} = $settings->{$type}->{$key};
                           } elsif ($key eq 'machines') {
                               $machineaccess{$type} = $settings->{$type}->{$key};
                           }
                       }
                   }
               }
           }
       }
       my $titles= &LONCAPA::lonauthcgi::serverstatus_titles();
       my $rownum = 0;
       my $css_class;
       foreach my $type (@pages) {
           $rownum ++;
           $css_class = $rownum%2?' class="LC_odd_row"':'';
           $datatable .= '<tr'.$css_class.'>'.
                         '<td><span class="LC_nobreak">'.
                         $titles->{$type}.'</span></td>'.
                         '<td class="LC_left_item">'.
                         '<input type="text" name="'.$type.'_namedusers" '.
                         'value="'.$namedaccess{$type}.'" size="30" /></td>'.
                         '<td class="LC_right_item">'.
                         '<span class="LC_nobreak">'.
                         '<input type="text" name="'.$type.'_machines" '.
                         'value="'.$machineaccess{$type}.'" size="10" />'.
                         '</td></tr>'."\n";
       }
       $$rowtotal += $rownum;
       return $datatable;
   }
   
   sub serverstatus_pages {
       return ('userstatus','lonstatus','loncron','server-status','codeversions',
               'clusterstatus','metadata_keywords','metadata_harvest',
               'takeoffline','takeonline','showenv','toggledebug','ping','domconf');
   }
   
 sub coursecategories_javascript {  sub coursecategories_javascript {
     my ($settings) = @_;      my ($settings) = @_;
     my ($output,$jstext);      my ($output,$jstext,$cathash);
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
           $cathash = $settings->{'cats'};
       }
       if (ref($cathash) eq 'HASH') {
         my (@cats,@jsarray,%idx);          my (@cats,@jsarray,%idx);
         &gather_categories($settings,\@cats,\%idx,\@jsarray);          &Apache::loncommon::gather_categories($cathash,\@cats,\%idx,\@jsarray);
         if (@jsarray > 0) {          if (@jsarray > 0) {
             $jstext = '    var categories = Array('.scalar(@jsarray).');'."\n";              $jstext = '    var categories = Array('.scalar(@jsarray).');'."\n";
             for (my $i=0; $i<@jsarray; $i++) {              for (my $i=0; $i<@jsarray; $i++) {
Line 2081  sub coursecategories_javascript { Line 4240  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 $communities_reserved = &mt('The name: "communities" is a reserved 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[
 function reorderCats(form,parent,item,idx) {  function reorderCats(form,parent,item,idx) {
     var changedVal;      var changedVal;
 $jstext  $jstext
Line 2139  $jstext Line 4302  $jstext
     }      }
     return;      return;
 }  }
   
   function categoryCheck(form) {
       if (form.elements['addcategory_name'].value == 'instcode') {
           alert('$instcode_reserved\\n$choose_again');
           return false;
       }
       if (form.elements['addcategory_name'].value == 'communities') {
           alert('$communities_reserved\\n$choose_again');
           return false;
       }
       return true;
   }
   
   // ]]>
 </script>  </script>
   
 ENDSCRIPT  ENDSCRIPT
Line 2147  ENDSCRIPT Line 4324  ENDSCRIPT
   
 sub initialize_categories {  sub initialize_categories {
     my ($itemcount) = @_;      my ($itemcount) = @_;
     my $datatable;      my ($datatable,$css_class,$chgstr);
     my $css_class = $itemcount%2?' class="LC_odd_row"':'';      my %default_names = (
     my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','instcode_pos','0'".');"';                        instcode    => 'Official courses (with institutional codes)',
                         communities => 'Communities',
     $datatable = '<tr '.$css_class.'><td><span class="LC_nobreak">'                          );
                  .'<select name="instcode_pos"><option value="0" selected="selected">1</option>'      my $select0 = ' selected="selected"';
                  .'<option value="1">2</option></select>&nbsp;'      my $select1 = '';
                  .&mt('Official courses (with institutional codes)')      foreach my $default ('instcode','communities') {
                  .'</span></td><td><span class="LC_nobreak">'          $css_class = $itemcount%2?' class="LC_odd_row"':'';
                  .'<label><input type="radio" name="instcode" value="1" checked="checked" />'          $chgstr = ' onchange="javascript:reorderCats(this.form,'."'',$default"."_pos','0'".');"';
                  .&mt('Display').'</label>&nbsp;<label>'          if ($default eq 'communities') {
                  .'<input type="radio" name="instcode" value="0" />'.&mt('Do not display')              $select1 = $select0;
               $select0 = '';
           }
           $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
                        .'<select name="'.$default.'_pos">'
                        .'<option value="0"'.$select0.'>1</option>'
                        .'<option value="1"'.$select1.'>2</option>'
                        .'<option value="2">3</option></select>&nbsp;'
                        .$default_names{$default}
                        .'</span></td><td><span class="LC_nobreak">'
                        .'<label><input type="radio" name="'.$default.'" value="1" checked="checked" />'
                        .&mt('Display').'</label>&nbsp;<label>'
                        .'<input type="radio" name="'.$default.'" value="0" />'.&mt('Do not display')
                  .'</label></span></td></tr>';                   .'</label></span></td></tr>';
     $itemcount ++;          $itemcount ++;
       }
     $css_class = $itemcount%2?' class="LC_odd_row"':'';      $css_class = $itemcount%2?' class="LC_odd_row"':'';
     $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','addcategory_pos','0'".');"';      $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','addcategory_pos','0'".');"';
     $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'      $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
                   .'<select name="addcategory_pos"'.$chgstr/'><option value="0">1</option>'                    .'<select name="addcategory_pos"'.$chgstr.'>'
                   .'<option value="1" selected="selected">2</option></select>&nbsp;'                    .'<option value="0">1</option>'
                     .'<option value="1">2</option>'
                     .'<option value="2" selected="selected">3</option></select>&nbsp;'
                   .&mt('Add category').'</td><td>'.&mt('Name:')                    .&mt('Add category').'</td><td>'.&mt('Name:')
                   .'&nbsp;<input type="text" size="20" name="addcategory_name" value="" /></td></tr>';                    .'&nbsp;<input type="text" size="20" name="addcategory_name" value="" /></td></tr>';
     return $datatable;      return $datatable;
Line 2222  sub build_category_rows { Line 4414  sub build_category_rows {
                             pop(@{$path});                              pop(@{$path});
                         }                          }
                     } else {                      } else {
                         $text .= &mt('New:').'&nbsp;</span><input type="textbox" size="20" name="addcategory_name_';                          $text .= &mt('Add subcategory:').'&nbsp;</span><input type="textbox" size="20" name="addcategory_name_';
                         if ($j == $numchildren) {                          if ($j == $numchildren) {
                             $text .= $name;                              $text .= $name;
                         } else {                          } else {
Line 2254  sub build_category_rows { Line 4446  sub build_category_rows {
 }  }
   
 sub modifiable_userdata_row {  sub modifiable_userdata_row {
     my ($context,$role,$settings,$numinrow,$rowcount) = @_;      my ($context,$role,$settings,$numinrow,$rowcount,$usertypes) = @_;
     my $rolename;      my $rolename;
     if ($role eq 'cr') {      if ($context eq 'selfcreate') {
         $rolename = &mt('Custom role');          if (ref($usertypes) eq 'HASH') {
               $rolename = $usertypes->{$role};
           } else {
               $rolename = $role;
           }
     } else {      } else {
         $rolename = &Apache::lonnet::plaintext($role);          if ($role eq 'cr') {
               $rolename = &mt('Custom role');
           } else {
               $rolename = &Apache::lonnet::plaintext($role);
           }
     }      }
     my @fields = ('lastname','firstname','middlename','generation',      my @fields = ('lastname','firstname','middlename','generation',
                   'permanentemail','id');                    'permanentemail','id');
Line 2318  sub modifiable_userdata_row { Line 4518  sub modifiable_userdata_row {
     return $output;      return $output;
 }  }
   
 sub users_cansearch_row {  sub insttypes_row {
     my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle) = @_;      my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context) = @_;
       my %lt = &Apache::lonlocal::texthash (
                         cansearch => 'Users allowed to search',
                         statustocreate => 'Institutional affiliation(s) able to create own account (login/SSO)',
                         lockablenames => 'User preference to lock name',
                );
       my $showdom;
       if ($context eq 'cansearch') {
           $showdom = ' ('.$dom.')';
       }
       my $class = 'LC_left_item';
       if ($context eq 'statustocreate') {
           $class = 'LC_right_item';
       }
     my $output =  '<tr class="LC_odd_row">'.      my $output =  '<tr class="LC_odd_row">'.
                   '<td>'.&mt('Users allowed to search').' ('.$dom.')'.                    '<td>'.$lt{$context}.$showdom.
                   '</td><td class="LC_left_item" colspan="2"><table>';                    '</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 2335  sub users_cansearch_row { Line 4548  sub users_cansearch_row {
                     $output .= '<tr>';                      $output .= '<tr>';
                 }                  }
                 my $check = ' ';                  my $check = ' ';
                 if (ref($settings->{'cansearch'}) eq 'ARRAY') {                  if (ref($settings) eq 'HASH') {
                     if (grep(/^\Q$types->[$i]\E$/,@{$settings->{'cansearch'}})) {                      if (ref($settings->{$context}) eq 'ARRAY') {
                           if (grep(/^\Q$types->[$i]\E$/,@{$settings->{$context}})) {
                               $check = ' checked="checked" ';
                           }
                       } elsif ($context eq 'statustocreate') {
                         $check = ' checked="checked" ';                          $check = ' checked="checked" ';
                     }                      }
                 }                  }
                 $output .= '<td class="LC_left_item">'.                  $output .= '<td class="LC_left_item">'.
                            '<span class="LC_nobreak"><label>'.                             '<span class="LC_nobreak"><label>'.
                            '<input type="checkbox" name="cansearch" '.                             '<input type="checkbox" name="'.$context.'" '.
                            'value="'.$types->[$i].'"'.$check.'/>'.                             'value="'.$types->[$i].'"'.$check.'/>'.
                            $usertypes->{$types->[$i]}.'</label></span></td>';                             $usertypes->{$types->[$i]}.'</label></span></td>';
             }              }
         }          }
          
         $rem = @{$types}%($numinrow);          $rem = @{$types}%($numinrow);
     }      }
     my $colsleft = $numinrow - $rem;      my $colsleft = $numinrow - $rem;
       if (($rem == 0) && (@{$types} > 0)) {
           $output .= '<tr>';
       }
     if ($colsleft > 1) {      if ($colsleft > 1) {
         $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">';          $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
     } else {      } else {
         $output .= '<td class="LC_left_item">';          $output .= '<td class="LC_left_item">';
     }      }
     my $defcheck = ' ';      my $defcheck = ' ';
     if (ref($settings->{'cansearch'}) eq 'ARRAY') {      if (ref($settings) eq 'HASH') {  
         if (grep(/^default$/,@{$settings->{'cansearch'}})) {          if (ref($settings->{$context}) eq 'ARRAY') {
               if (grep(/^default$/,@{$settings->{$context}})) {
                   $defcheck = ' checked="checked" ';
               }
           } elsif ($context eq 'statustocreate') {
             $defcheck = ' checked="checked" ';              $defcheck = ' checked="checked" ';
         }          }
     }      }
     $output .= '<span class="LC_nobreak"><label>'.      $output .= '<span class="LC_nobreak"><label>'.
                '<input type="checkbox" name="cansearch" '.                 '<input type="checkbox" name="'.$context.'" '.
                'value="default"'.$defcheck.'/>'.                 'value="default"'.$defcheck.'/>'.
                $othertitle.'</label></span></td>'.                 $othertitle.'</label></span></td>'.
                '</tr></table></td></tr>';                 '</tr></table></td></tr>';
Line 2442  sub usertype_update_row { Line 4665  sub usertype_update_row {
   
 sub modify_login {  sub modify_login {
     my ($r,$dom,$confname,%domconfig) = @_;      my ($r,$dom,$confname,%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');                 newuser => 'Link for visitors to create a user account',
     my @offon = ('off','on');                 loginheader => 'Log-in box header');
     my %loginhash;      @offon = ('off','on');
       if (ref($domconfig{login}) eq 'HASH') {
           if (ref($domconfig{login}{loginvia}) eq 'HASH') {
               foreach my $lonhost (keys(%{$domconfig{login}{loginvia}})) {
                   $curr_loginvia{$lonhost} = $domconfig{login}{loginvia}{$lonhost};
               }
           }
       }
     ($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','newuser');
Line 2460  sub modify_login { Line 4690  sub modify_login {
         $colchgtext = &display_colorchgs($dom,\%colchanges,['login'],          $colchgtext = &display_colorchgs($dom,\%colchanges,['login'],
                                          \%loginhash);                                           \%loginhash);
     }      }
   
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my @loginvia_attribs = ('serverpath','custompath','exempt');
       if (keys(%servers) > 1) {
           foreach my $lonhost (keys(%servers)) {
               next if ($env{'form.'.$lonhost.'_server'} eq $lonhost);
               if (ref($curr_loginvia{$lonhost}) eq 'HASH') {
                   if ($env{'form.'.$lonhost.'_server'} eq $curr_loginvia{$lonhost}{'server'}) {
                       $loginhash{login}{loginvia}{$lonhost}{'server'} = $curr_loginvia{$lonhost}{'server'};
                   } elsif ($curr_loginvia{$lonhost}{'server'} ne '') {
                       if (defined($servers{$env{'form.'.$lonhost.'_server'}})) {
                           $loginhash{login}{loginvia}{$lonhost}{'server'} = $env{'form.'.$lonhost.'_server'};
                           $changes{'loginvia'}{$lonhost} = 1;
                       } else {
                           $loginhash{login}{loginvia}{$lonhost}{'server'} = '';
                           $changes{'loginvia'}{$lonhost} = 1;
                       }
                   } else {
                       if (defined($servers{$env{'form.'.$lonhost.'_server'}})) {
                           $loginhash{login}{loginvia}{$lonhost}{'server'} = $env{'form.'.$lonhost.'_server'};
                           $changes{'loginvia'}{$lonhost} = 1;
                       }
                   }
                   if ($loginhash{login}{loginvia}{$lonhost}{'server'} eq '') {
                       foreach my $item (@loginvia_attribs) {
                           $loginhash{login}{loginvia}{$lonhost}{$item} = '';
                       }
                   } else {
                       foreach my $item (@loginvia_attribs) {
                           my $new = $env{'form.'.$lonhost.'_'.$item};
                           if (($item eq 'serverpath') && ($new eq 'custom')) {
                               $env{'form.'.$lonhost.'_custompath'} =~ s/\s+//g;
                               if ($env{'form.'.$lonhost.'_custompath'} eq '') {
                                   $new = '/';
                               }
                           }
                           if (($item eq 'custompath') && 
                               ($env{'form.'.$lonhost.'_serverpath'} ne 'custom')) {
                               $new = '';
                           }
                           if ($new ne $curr_loginvia{$lonhost}{$item}) {
                               $changes{'loginvia'}{$lonhost} = 1;
                           }
                           if ($item eq 'exempt') {
                               $new =~ s/^\s+//;
                               $new =~ s/\s+$//;
                               my @poss_ips = split(/\s*[,:]\s*/,$new);
                               my @okips;
                               foreach my $ip (@poss_ips) {
                                   if ($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
                                       if (($1 <= 255) && ($2 <= 255) && ($3 <= 255) && ($4 <= 255)) {
                                           push(@okips,$ip); 
                                       }
                                   }
                               }
                               if (@okips > 0) {
                                   $new = join(',',@okips); 
                               } else {
                                   $new = ''; 
                               }
                           }
                           $loginhash{login}{loginvia}{$lonhost}{$item} = $new;
                       }
                   }
               } else {
                   if (defined($servers{$env{'form.'.$lonhost.'_server'}})) {
                       $loginhash{login}{loginvia}{$lonhost}{'server'} = $env{'form.'.$lonhost.'_server'};
                       $changes{'loginvia'}{$lonhost} = 1;
                       foreach my $item (@loginvia_attribs) {
                           my $new = $env{'form.'.$lonhost.'_'.$item};
                           if (($item eq 'serverpath') && ($new eq 'custom')) {
                               if ($env{'form.'.$lonhost.'_custompath'} eq '') {
                                   $new = '/';
                               }
                           }
                           if (($item eq 'custompath') && 
                               ($env{'form.'.$lonhost.'_serverpath'} ne 'custom')) {
                               $new = '';
                           }
                           $loginhash{login}{loginvia}{$lonhost}{$item} = $new;
                       }
                   }
               }
           }
       }
   
       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') {
Line 2469  sub modify_login { Line 4875  sub modify_login {
                     'adminmail'     => 'off',                      'adminmail'     => 'off',
                     'newuser'       => 'off',                      'newuser'       => 'off',
         );          );
         foreach my $item (@toggles) {          if (ref($domconfig{'login'}) eq 'HASH') {
             if ($defaultchecked{$item} eq 'on') {               foreach my $item (@toggles) {
                 if (($domconfig{'login'}{$item} eq '0') &&                  if ($defaultchecked{$item} eq 'on') { 
                     ($env{'form.'.$item} eq '1')) {                      if (($domconfig{'login'}{$item} eq '0') &&
                     $changes{$item} = 1;                          ($env{'form.'.$item} eq '1')) {
                 } elsif (($domconfig{'login'}{$item} eq '' ||                          $changes{$item} = 1;
                           $domconfig{'login'}{$item} eq '1') &&                      } elsif (($domconfig{'login'}{$item} eq '' ||
                          ($env{'form.'.$item} eq '0')) {                                $domconfig{'login'}{$item} eq '1') &&
                     $changes{$item} = 1;                               ($env{'form.'.$item} eq '0')) {
                 }                          $changes{$item} = 1;
             } elsif ($defaultchecked{$item} eq 'off') {                      }
                 if (($domconfig{'login'}{$item} eq '1') &&                  } elsif ($defaultchecked{$item} eq 'off') {
                     ($env{'form.'.$item} eq '0')) {                      if (($domconfig{'login'}{$item} eq '1') &&
                     $changes{$item} = 1;                          ($env{'form.'.$item} eq '0')) {
                 } elsif (($domconfig{'login'}{$item} eq '' ||                          $changes{$item} = 1;
                           $domconfig{'login'}{$item} eq '0') &&                      } elsif (($domconfig{'login'}{$item} eq '' ||
                          ($env{'form.'.$item} eq '1')) {                                $domconfig{'login'}{$item} eq '0') &&
                     $changes{$item} = 1;                               ($env{'form.'.$item} eq '1')) {
                           $changes{$item} = 1;
                       }
                 }                  }
             }              }
         }          }
         if (($domconfig{'login'}{'loginheader'} eq 'text') &&   
             ($env{'form.loginheader'} eq 'image')) {  
             $changes{'loginheader'} = 1;  
         } elsif (($domconfig{'login'}{'loginheader'} eq '' ||  
                   $domconfig{'login'}{'loginheader'} eq 'image') &&  
                  ($env{'form.loginheader'} eq 'text')) {  
             $changes{'loginheader'} = 1;  
         }  
         if (keys(%changes) > 0 || $colchgtext) {          if (keys(%changes) > 0 || $colchgtext) {
             &Apache::loncommon::devalidate_domconfig_cache($dom);              &Apache::loncommon::devalidate_domconfig_cache($dom);
             $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 'loginheader') {                  if ($item eq 'loginvia') {
                     $resulttext .= '<li>'.&mt("$title{$item} set to $env{'form.loginheader'}").'</li>';                      if (ref($changes{$item}) eq 'HASH') {
                           $resulttext .= '<li>'.&mt('Log-in page availability:').'<ul>';
                           foreach my $lonhost (sort(keys(%{$changes{$item}}))) {
                               if (defined($servers{$loginhash{login}{loginvia}{$lonhost}{'server'}})) {
                                   if (ref($loginhash{login}{loginvia}{$lonhost}) eq 'HASH') {
                                       my $protocol = $Apache::lonnet::protocol{$env{'form.'.$lonhost.'_server'}};
                                       $protocol = 'http' if ($protocol ne 'https');
                                       my $target = $protocol.'://'.$servers{$env{'form.'.$lonhost.'_server'}};
   
                                       if ($loginhash{login}{loginvia}{$lonhost}{'serverpath'} eq 'custom') {
                                           $target .= $loginhash{login}{loginvia}{$lonhost}{'custompath'};
                                       } else {
                                           $target .= $loginhash{login}{loginvia}{$lonhost}{'serverpath'}; 
                                       }
                                       $resulttext .= '<li>'.&mt('Server: [_1] log-in page redirects to [_2].',$servers{$lonhost},'<a href="'.$target.'">'.$target.'</a>');
                                       if ($loginhash{login}{loginvia}{$lonhost}{'exempt'} ne '') {
                                           $resulttext .= '&nbsp;'.&mt('No redirection for clients from following IPs:').'&nbsp;'.$loginhash{login}{loginvia}{$lonhost}{'exempt'};
                                       }
                                       $resulttext .= '</li>';
                                   } else {
                                       $resulttext .= '<li>'.&mt('Server: [_1] has standard log-in page.',$lonhost).'</li>';
                                   }
                               } else {
                                   $resulttext .= '<li>'.&mt('Server: [_1] has standard log-in page.',$servers{$lonhost}).'</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]',$pubkey).'</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 2529  sub color_font_choices { Line 5018  sub color_font_choices {
             img => "Header",              img => "Header",
             bgs => "Background colors",              bgs => "Background colors",
             links => "Link colors",              links => "Link colors",
               images => "Images",
             font => "Font color",              font => "Font color",
               fontmenu => "Font Menu",
             pgbg => "Page",              pgbg => "Page",
             tabbg => "Header",              tabbg => "Header",
             sidebg => "Border",              sidebg => "Border",
Line 2544  sub modify_rolecolors { Line 5035  sub modify_rolecolors {
     my ($r,$dom,$confname,$roles,%domconfig) = @_;      my ($r,$dom,$confname,$roles,%domconfig) = @_;
     my ($resulttext,%rolehash);      my ($resulttext,%rolehash);
     $rolehash{'rolecolors'} = {};      $rolehash{'rolecolors'} = {};
       if (ref($domconfig{'rolecolors'}) ne 'HASH') {
           if ($domconfig{'rolecolors'} eq '') {
               $domconfig{'rolecolors'} = {};
           }
       }
     my ($errors,%changes) = &modify_colors($r,$dom,$confname,$roles,      my ($errors,%changes) = &modify_colors($r,$dom,$confname,$roles,
                          $domconfig{'rolecolors'},$rolehash{'rolecolors'});                           $domconfig{'rolecolors'},$rolehash{'rolecolors'});
     my $putresult = &Apache::lonnet::put_dom('configuration',\%rolehash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%rolehash,
Line 2582  sub modify_colors { Line 5078  sub modify_colors {
             @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');
Line 2601  sub modify_colors { Line 5098  sub modify_colors {
             $domconfig->{$role} = {};              $domconfig->{$role} = {};
         }          }
         foreach my $img (@images) {          foreach my $img (@images) {
               if (($role eq 'login') && (($img eq 'img') || ($img eq 'logo'))) {  
                   if (defined($env{'form.login_showlogo_'.$img})) {
                       $confhash->{$role}{'showlogo'}{$img} = 1;
                   } else { 
                       $confhash->{$role}{'showlogo'}{$img} = 0;
                   }
               } 
     if ( ! $env{'form.'.$role.'_'.$img.'.filename'}       if ( ! $env{'form.'.$role.'_'.$img.'.filename'} 
  && !defined($domconfig->{$role}{$img})   && !defined($domconfig->{$role}{$img})
  && !$env{'form.'.$role.'_del_'.$img}   && !$env{'form.'.$role.'_del_'.$img}
Line 2675  sub modify_colors { Line 5179  sub modify_colors {
                             $changes{$role}{'images'}{$img} = 1;                              $changes{$role}{'images'}{$img} = 1;
                         }                           } 
                     }                      }
                 }                        if (($role eq 'login') && (($img eq 'logo') || ($img eq 'img'))) {
                           if (ref($domconfig->{'login'}{'showlogo'}) eq 'HASH') {
                               if ($confhash->{$role}{'showlogo'}{$img} ne 
                                   $domconfig->{$role}{'showlogo'}{$img}) {
                                   $changes{$role}{'showlogo'}{$img} = 1; 
                               }
                           } else {
                               if ($confhash->{$role}{'showlogo'}{$img} == 0) {
                                   $changes{$role}{'showlogo'}{$img} = 1;
                               }
                           }
                       }
                   }
                 if ($domconfig->{$role}{'font'} ne '') {                  if ($domconfig->{$role}{'font'} ne '') {
                     if ($confhash->{$role}{'font'} ne $domconfig->{$role}{'font'}) {                      if ($confhash->{$role}{'font'} ne $domconfig->{$role}{'font'}) {
                         $changes{$role}{'font'} = 1;                          $changes{$role}{'font'} = 1;
Line 2685  sub modify_colors { Line 5201  sub modify_colors {
                         $changes{$role}{'font'} = 1;                          $changes{$role}{'font'} = 1;
                     }                      }
                 }                  }
                   if ($role ne 'login') {
                       if ($domconfig->{$role}{'fontmenu'} ne '') {
                           if ($confhash->{$role}{'fontmenu'} ne $domconfig->{$role}{'fontmenu'}) {
                               $changes{$role}{'fontmenu'} = 1;
                           }
                       } else {
                           if ($confhash->{$role}{'fontmenu'}) {
                               $changes{$role}{'fontmenu'} = 1;
                           }
                       }
                   }
                 foreach my $item (@bgs) {                  foreach my $item (@bgs) {
                     if ($domconfig->{$role}{$item} ne '') {                      if ($domconfig->{$role}{$item} ne '') {
                         if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) {                          if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) {
Line 2767  sub default_change_checker { Line 5294  sub default_change_checker {
             $confhash->{$role}{$img} = '';              $confhash->{$role}{$img} = '';
             $changes->{$role}{'images'}{$img} = 1;              $changes->{$role}{'images'}{$img} = 1;
         }          }
           if ($role eq 'login') {
               if ($confhash->{$role}{'showlogo'}{$img} == 0) {
                   $changes->{$role}{'showlogo'}{$img} = 1;
               }
           }
     }      }
     if ($confhash->{$role}{'font'}) {      if ($confhash->{$role}{'font'}) {
         $changes->{$role}{'font'} = 1;          $changes->{$role}{'font'} = 1;
Line 2798  sub display_colorchgs { Line 5330  sub display_colorchgs {
                         $resulttext .= '<li>'.&mt($choices{$key}).':<ul>';                          $resulttext .= '<li>'.&mt($choices{$key}).':<ul>';
                     }                      }
                     foreach my $item (sort(keys(%{$changes->{$role}{$key}}))) {                      foreach my $item (sort(keys(%{$changes->{$role}{$key}}))) {
                         if ($confhash->{$role}{$item} eq '') {                          if (($role eq 'login') && ($key eq 'showlogo')) {
                               if ($confhash->{$role}{$key}{$item}) {
                                   $resulttext .= '<li>'.&mt("$choices{$item} set to be displayed").'</li>';
                               } else {
                                   $resulttext .= '<li>'.&mt("$choices{$item} set to not be displayed").'</li>';
                               }
                           } elsif ($confhash->{$role}{$item} eq '') {
                             $resulttext .= '<li>'.&mt("$choices{$item} set to default").'</li>';                              $resulttext .= '<li>'.&mt("$choices{$item} set to default").'</li>';
                         } else {                          } else {
                             my $newitem = $confhash->{$role}{$item};                              my $newitem = $confhash->{$role}{$item};
Line 2899  sub publishlogo { Line 5437  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 2954  $env{'user.name'}.':'.$env{'user.domain' Line 5494  $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 2977  $env{'user.name'}.':'.$env{'user.domain' Line 5516  $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 2996  $env{'user.name'}.':'.$env{'user.domain' Line 5542  $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 3062  sub write_metadata { Line 5615  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 3098  sub check_switchserver { Line 5700  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 javascript_set_colnums {  sub modify_quotas {
     return <<END;      my ($dom,$action,%domconfig) = @_;
 function setDisplayColumns() {      my ($context,@usertools,@options,%validations,%titles,%confhash,%toolshash,
     if (document.pickactions.width.value > 1100) {          %limithash,$toolregexp,%conditions,$resulttext,%changes);
         document.pickactions.numcols[1].checked = true;      if ($action eq 'quotas') {
           $context = 'tools'; 
       } else {
           $context = $action;
       }
       if ($context eq 'requestcourses') {
           @usertools = ('official','unofficial','community');
           @options =('norequest','approval','validate','autolimit');
           %validations = &Apache::lonnet::auto_courserequest_checks($dom);
           %titles = &courserequest_titles();
           $toolregexp = join('|',@usertools);
           %conditions = &courserequest_conditions();
       } elsif ($context eq 'requestauthor') {
           @usertools = ('author');
           %titles = &authorrequest_titles();
     } else {      } else {
         document.pickactions.numcols[0].checked = true;          @usertools = ('aboutme','blog','webdav','portfolio');
           %titles = &tool_titles();
     }      }
 }      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
 END  
 }  
   
 sub modify_quotas {  
     my ($dom,%domconfig) = @_;  
     my ($resulttext,%changes);  
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);      my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
     my %formhash;  
     foreach my $key (keys(%env)) {      foreach my $key (keys(%env)) {
         if ($key =~ /^form\.quota_(.+)$/) {          if ($context eq 'requestcourses') {
             $formhash{$1} = $env{$key};              if ($key =~ /^form\.crsreq_($toolregexp)_(.+)$/) {
                   my $item = $1;
                   my $type = $2;
                   if ($type =~ /^limit_(.+)/) {
                       $limithash{$item}{$1} = $env{$key};
                   } else {
                       $confhash{$item}{$type} = $env{$key};
                   }
               }
           } elsif ($context eq 'requestauthor') {
               if ($key =~ /^\Qform.authorreq_\E(.+)$/) {
                   $confhash{$1} = $env{$key};
               }
           } else {
               if ($key =~ /^form\.quota_(.+)$/) {
                   $confhash{'defaultquota'}{$1} = $env{$key};
               }
               if ($key =~ /^form\.\Q$context\E_(.+)$/) {
                   @{$toolshash{$1}} = &Apache::loncommon::get_env_multiple($key);
               }
         }          }
     }      }
     $formhash{'default'} = $env{'form.defaultquota'};      if (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
     if (ref($domconfig{'quotas'}) eq 'HASH') {          my @approvalnotify = &Apache::loncommon::get_env_multiple('form.reqapprovalnotify');
         foreach my $key (keys(%{$domconfig{'quotas'}})) {          @approvalnotify = sort(@approvalnotify);
             if (exists($formhash{$key})) {          $confhash{'notify'}{'approval'} = join(',',@approvalnotify);
                 if ($formhash{$key} ne $domconfig{'quotas'}{$key}) {          if (ref($domconfig{$action}) eq 'HASH') {
                     $changes{$key} = 1;              if (ref($domconfig{$action}{'notify'}) eq 'HASH') {
                   if ($domconfig{$action}{'notify'}{'approval'} ne $confhash{'notify'}{'approval'}) {
                       $changes{'notify'}{'approval'} = 1;
                   }
               } else {
                   if ($confhash{'notify'}{'approval'}) {
                       $changes{'notify'}{'approval'} = 1;
                   }
               }
           } else {
               if ($confhash{'notify'}{'approval'}) {
                   $changes{'notify'}{'approval'} = 1;
               }
           }
       } else {
           $confhash{'defaultquota'}{'default'} = $env{'form.defaultquota'};
       }
       foreach my $item (@usertools) {
           foreach my $type (@{$types},'default','_LC_adv') {
               my $unset; 
               if ($context eq 'requestcourses') {
                   $unset = '0';
                   if ($type eq '_LC_adv') {
                       $unset = '';
                   }
                   if ($confhash{$item}{$type} eq 'autolimit') {
                       $confhash{$item}{$type} .= '=';
                       unless ($limithash{$item}{$type} =~ /\D/) {
                           $confhash{$item}{$type} .= $limithash{$item}{$type};
                       }
                   }
               } elsif ($context eq 'requestauthor') {
                   $unset = '0';
                   if ($type eq '_LC_adv') {
                       $unset = '';
                 }                  }
             } else {              } else {
                 $formhash{$key} = $domconfig{'quotas'}{$key};                  if (grep(/^\Q$type\E$/,@{$toolshash{$item}})) {
                       $confhash{$item}{$type} = 1;
                   } else {
                       $confhash{$item}{$type} = 0;
                   }
               }
               if (ref($domconfig{$action}) 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}) {
                           $changes{$item}{$type} = 1;
                       }
                   } else {
                       if ($context eq 'requestcourses') {
                           if ($confhash{$item}{$type} ne $unset) {
                               $changes{$item}{$type} = 1;
                           }
                       } else {
                           if (!$confhash{$item}{$type}) {
                               $changes{$item}{$type} = 1;
                           }
                       }
                   }
               } else {
                   if ($context eq 'requestcourses') {
                       if ($confhash{$item}{$type} ne $unset) {
                           $changes{$item}{$type} = 1;
                       }
                   } elsif ($context eq 'requestauthor') {
                       if ($confhash{$type} ne $unset) {
                           $changes{$type} = 1;
                       }
                   } else {
                       if (!$confhash{$item}{$type}) {
                           $changes{$item}{$type} = 1;
                       }
                   }
             }              }
         }          }
     }      }
     foreach my $key (keys(%formhash)) {      unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
         if ($formhash{$key} ne '') {          if (ref($domconfig{'quotas'}) eq 'HASH') {
             if (!exists($domconfig{'quotas'}{$key})) {              if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') {
                 $changes{$key} = 1;                  foreach my $key (keys(%{$domconfig{'quotas'}{'defaultquota'}})) {
                       if (exists($confhash{'defaultquota'}{$key})) {
                           if ($confhash{'defaultquota'}{$key} ne $domconfig{'quotas'}{'defaultquota'}{$key}) {
                               $changes{'defaultquota'}{$key} = 1;
                           }
                       } else {
                           $confhash{'defaultquota'}{$key} = $domconfig{'quotas'}{'defaultquota'}{$key};
                       }
                   }
               } else {
                   foreach my $key (keys(%{$domconfig{'quotas'}})) {
                       if (exists($confhash{'defaultquota'}{$key})) {
                           if ($confhash{'defaultquota'}{$key} ne $domconfig{'quotas'}{$key}) {
                               $changes{'defaultquota'}{$key} = 1;
                           }
                       } else {
                           $confhash{'defaultquota'}{$key} = $domconfig{'quotas'}{$key};
                       }
                   }
               }
           }
           if (ref($confhash{'defaultquota'}) eq 'HASH') {
               foreach my $key (keys(%{$confhash{'defaultquota'}})) {
                   if (ref($domconfig{'quotas'}) eq 'HASH') {
                       if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') {
                           if (!exists($domconfig{'quotas'}{'defaultquota'}{$key})) {
                               $changes{'defaultquota'}{$key} = 1;
                           }
                       } else {
                           if (!exists($domconfig{'quotas'}{$key})) {
                               $changes{'defaultquota'}{$key} = 1;
                           }
                       }
                   } else {
                       $changes{'defaultquota'}{$key} = 1;
                   }
             }              }
         }          }
     }      }
   
       if ($context eq 'requestauthor') {
           $domdefaults{'requestauthor'} = \%confhash;
       } else {
           foreach my $key (keys(%confhash)) {
               $domdefaults{$key} = $confhash{$key};
           }
       }
   
     my %quotahash = (      my %quotahash = (
                       quotas => {%formhash},                        $action => { %confhash }
                     );                      );
     my $putresult = &Apache::lonnet::put_dom('configuration',\%quotahash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%quotahash,
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
               my $cachetime = 24*60*60;
               &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
   
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             foreach my $type (@{$types},'default') {              unless (($context eq 'requestcourses') || 
                 if (defined($changes{$type})) {                       ($context eq 'requestauthor')) {
                     my $typetitle = $usertypes->{$type};                  if (ref($changes{'defaultquota'}) eq 'HASH') {
                     if ($type eq 'default') {                      $resulttext .= '<li>'.&mt('Portfolio default quotas').'<ul>';
                         $typetitle = $othertitle;                      foreach my $type (@{$types},'default') {
                           if (defined($changes{'defaultquota'}{$type})) {
                               my $typetitle = $usertypes->{$type};
                               if ($type eq 'default') {
                                   $typetitle = $othertitle;
                               }
                               $resulttext .= '<li>'.&mt('[_1] set to [_2] Mb',$typetitle,$confhash{'defaultquota'}{$type}).'</li>';
                           }
                       }
                       $resulttext .= '</ul></li>';
                   }
               }
               my %newenv;
               foreach my $item (@usertools) {
                   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 = 
                           &Apache::lonnet::usertools_access($env{'user.name'},
                                                             $env{'user.domain'},
                                                             $item,'reload',$context);
                       if (($context eq 'requestcourses') || 
                           ($context eq 'requestauthor')) {
                           if ($env{'environment.canrequest.'.$item} ne $newacc) {
                               $newenv{'environment.canrequest.'.$item} = $newacc;
                           }
                       } else {
                           if ($env{'environment.availabletools.'.$item} ne $newacc) { 
                               $newenv{'environment.availabletools.'.$item} = $newacc;
                           }
                       }
                       unless ($context eq 'requestauthor') {
                           $resulttext .= '<li>'.$titles{$item}.'<ul>';
                       }
                       foreach my $type (@{$types},'default','_LC_adv') {
                           if ($haschgs{$type}) {
                               my $typetitle = $usertypes->{$type};
                               if ($type eq 'default') {
                                   $typetitle = $othertitle;
                               } elsif ($type eq '_LC_adv') {
                                   $typetitle = 'LON-CAPA Advanced Users'; 
                               }
                               if ($inconf{$type}) {
                                   if ($context eq 'requestcourses') {
                                       my $cond;
                                       if ($inconf{$type} =~ /^autolimit=(\d*)$/) {
                                           if ($1 eq '') {
                                               $cond = &mt('(Automatic processing of any request).');
                                           } else {
                                               $cond = &mt('(Automatic processing of requests up to limit of [quant,_1,request] per user).',$1);
                                           }
                                       } else { 
                                           $cond = $conditions{$inconf{$type}};
                                       }
                                       $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 {
                                       $resulttext .= '<li>'.&mt('Set to be available to [_1]',$typetitle).'</li>';
                                   }
                               } else {
                                   if ($type eq '_LC_adv') {
                                       if ($inconf{$type} eq '0') {
                                           $resulttext .= '<li>'.&mt('Set to be unavailable to [_1]',$typetitle).'</li>';
                                       } else { 
                                           $resulttext .= '<li>'.&mt('No override set for [_1]',$typetitle).'</li>';
                                       }
                                   } else {
                                       $resulttext .= '<li>'.&mt('Set to be unavailable to [_1]',$typetitle).'</li>';
                                   }
                               }
                           }
                       }
                       unless ($context eq 'requestauthor') {
                           $resulttext .= '</ul></li>';
                       }
                   }
               }
               if (($action eq 'requestcourses') || ($action eq 'requestauthor')) {
                   if (ref($changes{'notify'}) eq 'HASH') {
                       if ($changes{'notify'}{'approval'}) {
                           if (ref($confhash{'notify'}) eq 'HASH') {
                               if ($confhash{'notify'}{'approval'}) {
                                   $resulttext .= '<li>'.&mt('Notification of requests requiring approval will be sent to: ').$confhash{'notify'}{'approval'}.'</li>';
                               } else {
                                   $resulttext .= '<li>'.&mt('No Domain Coordinators will receive notification of requests requiring approval.').'</li>';
                               }
                           }
                     }                      }
                     $resulttext .= '<li>'.&mt('[_1] set to [_2] Mb',$typetitle,$formhash{$type}).'</li>';  
                 }                  }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
               if (keys(%newenv)) {
                   &Apache::lonnet::appenv(\%newenv);
               }
         } else {          } else {
             $resulttext = &mt('No changes made to default quotas');              if ($context eq 'requestcourses') {
                   $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 {
                   $resulttext = &mt('No changes made to availability of personal information pages, blogs, portfolios or default quotas');
               }
         }          }
     } else {      } else {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
Line 3183  sub modify_autoenroll { Line 6039  sub modify_autoenroll {
     }      }
     my $autorun = &Apache::lonnet::auto_run(undef,$dom),      my $autorun = &Apache::lonnet::auto_run(undef,$dom),
     my %title = ( run => 'Auto-enrollment active',      my %title = ( run => 'Auto-enrollment active',
                   sender => 'Sender for notification messages');                    sender => 'Sender for notification messages',
                     coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)');
     my @offon = ('off','on');      my @offon = ('off','on');
     my $sender_uname = $env{'form.sender_uname'};      my $sender_uname = $env{'form.sender_uname'};
     my $sender_domain = $env{'form.sender_domain'};      my $sender_domain = $env{'form.sender_domain'};
Line 3192  sub modify_autoenroll { Line 6049  sub modify_autoenroll {
     } elsif ($sender_uname eq '') {      } elsif ($sender_uname eq '') {
         $sender_domain = '';          $sender_domain = '';
     }      }
       my $coowners = $env{'form.autoassign_coowners'};
     my %autoenrollhash =  (      my %autoenrollhash =  (
                        autoenroll => { run => $env{'form.autoenroll_run'},                         autoenroll => { 'run' => $env{'form.autoenroll_run'},
                                        sender_uname => $sender_uname,                                         'sender_uname' => $sender_uname,
                                        sender_domain => $sender_domain,                                         'sender_domain' => $sender_domain,
                                          'co-owners' => $coowners,
                                 }                                  }
                      );                       );
     my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,
Line 3217  sub modify_autoenroll { Line 6075  sub modify_autoenroll {
         if ($currautoenroll{'sender_domain'} ne $sender_domain) {          if ($currautoenroll{'sender_domain'} ne $sender_domain) {
             $changes{'sender'} = 1;              $changes{'sender'} = 1;
         }          }
           if ($currautoenroll{'co-owners'} ne '') {
               if ($currautoenroll{'co-owners'} ne $coowners) {
                   $changes{'coowners'} = 1;
               }
           } elsif ($coowners) {
               $changes{'coowners'} = 1;
           }      
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if ($changes{'run'}) {              if ($changes{'run'}) {
Line 3229  sub modify_autoenroll { Line 6094  sub modify_autoenroll {
                     $resulttext .= '<li>'.&mt("$title{'sender'} set to [_1]",$sender_uname.':'.$sender_domain).'</li>';                      $resulttext .= '<li>'.&mt("$title{'sender'} set to [_1]",$sender_uname.':'.$sender_domain).'</li>';
                 }                  }
             }              }
               if ($changes{'coowners'}) {
                   $resulttext .= '<li>'.&mt("$title{'coowners'} set to $offon[$env{'form.autoassign_coowners'}]").'</li>';
                   &Apache::loncommon::devalidate_domconfig_cache($dom);
               }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
             $resulttext = &mt('No changes made to auto-enrollment settings');              $resulttext = &mt('No changes made to auto-enrollment settings');
Line 3260  sub modify_autoupdate { Line 6129  sub modify_autoupdate {
                         lastname => 'Last Name',                          lastname => 'Last Name',
                         firstname => 'First Name',                          firstname => 'First Name',
                         middlename => 'Middle Name',                          middlename => 'Middle Name',
                         gen => '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');
     }      }
     foreach my $key (keys(%env)) {      foreach my $key (keys(%env)) {
         if ($key =~ /^form\.updateable_(.+)_([^_]+)$/) {          if ($key =~ /^form\.updateable_(.+)_([^_]+)$/) {
             push(@{$fields{$1}},$2);              my ($usertype,$item) = ($1,$2);
               if (grep(/^\Q$item\E$/,keys(%fieldtitles))) {
                   if ($usertype eq 'default') {   
                       push(@{$fields{$1}},$2);
                   } elsif (ref($types) eq 'ARRAY') {
                       if (grep(/^\Q$usertype\E$/,@{$types})) {
                           push(@{$fields{$1}},$2);
                       }
                   }
               }
           }
       }
       my @lockablenames = &Apache::loncommon::get_env_multiple('form.lockablenames');
       @lockablenames = sort(@lockablenames);
       if (ref($currautoupdate{'lockablenames'}) eq 'ARRAY') {
           my @changed = &Apache::loncommon::compare_arrays($currautoupdate{'lockablenames'},\@lockablenames);
           if (@changed) {
               $changes{'lockablenames'} = 1;
           }
       } else {
           if (@lockablenames) {
               $changes{'lockablenames'} = 1;
         }          }
     }      }
     my %updatehash = (      my %updatehash = (
                       autoupdate => { run => $env{'form.autoupdate_run'},                        autoupdate => { run => $env{'form.autoupdate_run'},
                                       classlists => $env{'form.classlists'},                                        classlists => $env{'form.classlists'},
                                       fields => {%fields},                                        fields => {%fields},
                                         lockablenames => \@lockablenames,
                                     }                                      }
                      );                       );
     foreach my $key (keys(%currautoupdate)) {      foreach my $key (keys(%currautoupdate)) {
Line 3292  sub modify_autoupdate { Line 6183  sub modify_autoupdate {
                         foreach my $type (@{$currautoupdate{$key}{$item}}) {                          foreach my $type (@{$currautoupdate{$key}{$item}}) {
                             if (!exists($fields{$item})) {                              if (!exists($fields{$item})) {
                                 $change = 1;                                  $change = 1;
                                   last;
                             } elsif (ref($fields{$item}) eq 'ARRAY') {                              } elsif (ref($fields{$item}) eq 'ARRAY') {
                                 if (!grep(/^\Q$type\E$/,@{$fields{$item}})) {                                  if (!grep(/^\Q$type\E$/,@{$fields{$item}})) {
                                     $change = 1;                                      $change = 1;
                                       last;
                                 }                                  }
                             }                              }
                         }                          }
Line 3304  sub modify_autoupdate { Line 6197  sub modify_autoupdate {
                     }                       } 
                 }                  }
             }              }
           } elsif ($key eq 'lockablenames') {
               if (ref($currautoupdate{$key}) eq 'ARRAY') {
                   my @changed = &Apache::loncommon::compare_arrays($currautoupdate{'lockablenames'},\@lockablenames);
                   if (@changed) {
                       $changes{'lockablenames'} = 1;
                   }
               } else {
                   if (@lockablenames) {
                       $changes{'lockablenames'} = 1;
                   }
               }
           }
       }
       unless (grep(/^\Qlockablenames\E$/,keys(%currautoupdate))) {
           if (@lockablenames) {
               $changes{'lockablenames'} = 1;
         }          }
     }      }
     foreach my $item (@{$types},'default') {      foreach my $item (@{$types},'default') {
         if (defined($fields{$item})) {          if (defined($fields{$item})) {
             if (ref($currautoupdate{'fields'}) eq 'HASH') {              if (ref($currautoupdate{'fields'}) eq 'HASH') {
                 if (!exists($currautoupdate{'fields'}{$item})) {                  if (ref($currautoupdate{'fields'}{$item}) eq 'ARRAY') {
                       my $change = 0;
                       if (ref($fields{$item}) eq 'ARRAY') {
                           foreach my $type (@{$fields{$item}}) {
                               if (!grep(/^\Q$type\E$/,@{$currautoupdate{'fields'}{$item}})) {
                                   $change = 1;
                                   last;
                               }
                           }
                       }
                       if ($change) {
                           push(@{$changes{'fields'}},$item);
                       }
                   } else {
                     push(@{$changes{'fields'}},$item);                      push(@{$changes{'fields'}},$item);
                 }                  }
             } else {              } else {
Line 3323  sub modify_autoupdate { Line 6245  sub modify_autoupdate {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             foreach my $key (sort(keys(%changes))) {              foreach my $key (sort(keys(%changes))) {
                 if (ref($changes{$key}) eq 'ARRAY') {                  if ($key eq 'lockablenames') {
                       $resulttext .= '<li>';
                       if (@lockablenames) {
                           $usertypes->{'default'} = $othertitle;
                           $resulttext .= &mt("User preference to disable replacement of user's name with institutional data (by auto-update), available for the following affiliations:").' '.
                                      join(', ', map { $usertypes->{$_}; } @lockablenames).'</li>';
                       } else {
                           $resulttext .= &mt("User preference to disable replacement of user's name with institutional data (by auto-update) is unavailable.");
                       }
                       $resulttext .= '</li>';
                   } elsif (ref($changes{$key}) eq 'ARRAY') {
                     foreach my $item (@{$changes{$key}}) {                      foreach my $item (@{$changes{$key}}) {
                         my @newvalues;                          my @newvalues;
                         foreach my $type (@{$fields{$item}}) {                          foreach my $type (@{$fields{$item}}) {
Line 3362  sub modify_autoupdate { Line 6294  sub modify_autoupdate {
     return $resulttext;      return $resulttext;
 }  }
   
   sub modify_autocreate {
       my ($dom,%domconfig) = @_;
       my ($resulttext,%changes,%currautocreate,%newvals,%autocreatehash);
       if (ref($domconfig{'autocreate'}) eq 'HASH') {
           foreach my $key (keys(%{$domconfig{'autocreate'}})) {
               $currautocreate{$key} = $domconfig{'autocreate'}{$key};
           }
       }
       my %title= ( xml => 'Auto-creation of courses in XML course description files',
                    req => 'Auto-creation of validated requests for official courses',
                    xmldc => 'Identity of course creator of courses from XML files',
                  );
       my @types = ('xml','req');
       foreach my $item (@types) {
           $newvals{$item} = $env{'form.autocreate_'.$item};
           $newvals{$item} =~ s/\D//g;
           $newvals{$item} = 0 if ($newvals{$item} eq '');
       }
       $newvals{'xmldc'} = $env{'form.autocreate_xmldc'};
       my %domcoords = &get_active_dcs($dom);
       unless (exists($domcoords{$newvals{'xmldc'}})) {
           $newvals{'xmldc'} = '';
       } 
       %autocreatehash =  (
                           autocreate => { xml => $newvals{'xml'},
                                           req => $newvals{'req'},
                                         }
                          );
       if ($newvals{'xmldc'} ne '') {
           $autocreatehash{'autocreate'}{'xmldc'} = $newvals{'xmldc'};
       }
       my $putresult = &Apache::lonnet::put_dom('configuration',\%autocreatehash,
                                                $dom);
       if ($putresult eq 'ok') {
           my @items = @types;
           if ($newvals{'xml'}) {
               push(@items,'xmldc');
           }
           foreach my $item (@items) {
               if (exists($currautocreate{$item})) {
                   if ($currautocreate{$item} ne $newvals{$item}) {
                       $changes{$item} = 1;
                   }
               } elsif ($newvals{$item}) {
                   $changes{$item} = 1;
               }
           }
           if (keys(%changes) > 0) {
               my @offon = ('off','on'); 
               $resulttext = &mt('Changes made:').'<ul>';
               foreach my $item (@types) {
                   if ($changes{$item}) {
                       my $newtxt = $offon[$newvals{$item}];
                       $resulttext .= '<li>'.
                                      &mt("$title{$item} set to [_1]$newtxt [_2]",
                                          '<b>','</b>').
                                      '</li>';
                   }
               }
               if ($changes{'xmldc'}) {
                   my ($dcname,$dcdom) = split(':',$newvals{'xmldc'});
                   my $newtxt = &Apache::loncommon::plainname($dcname,$dcdom);
                   $resulttext .= '<li>'.&mt("$title{'xmldc'} set to [_1]",'<b>'.$newtxt.'</b>').'</li>'; 
               }
               $resulttext .= '</ul>';
           } else {
               $resulttext = &mt('No changes made to auto-creation settings');
           }
       } else {
           $resulttext = '<span class="LC_error">'.
               &mt('An error occurred: [_1]',$putresult).'</span>';
       }
       return $resulttext;
   }
   
 sub modify_directorysrch {  sub modify_directorysrch {
     my ($dom,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%changes);      my ($resulttext,%changes);
Line 3495  sub modify_directorysrch { Line 6502  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 3523  sub modify_directorysrch { Line 6534  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 3544  sub modify_contacts { Line 6555  sub modify_contacts {
             $currsetting{$key} = $domconfig{'contacts'}{$key};              $currsetting{$key} = $domconfig{'contacts'}{$key};
         }          }
     }      }
     my (%others,%to);      my (%others,%to,%bcc);
     my @contacts = ('supportemail','adminemail');      my @contacts = ('supportemail','adminemail');
     my @mailings = ('errormail','packagesmail','helpdeskmail');      my @mailings = ('errormail','packagesmail','helpdeskmail','lonstatusmail',
                       'requestsmail');
     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 3559  sub modify_contacts { Line 6571  sub modify_contacts {
         }            }  
         $others{$type} = $env{'form.'.$type.'_others'};          $others{$type} = $env{'form.'.$type.'_others'};
         $contacts_hash{contacts}{$type}{'others'} = $others{$type};          $contacts_hash{contacts}{$type}{'others'} = $others{$type};
           if ($type eq 'helpdeskmail') {
               $bcc{$type} = $env{'form.'.$type.'_bcc'};
               $contacts_hash{contacts}{$type}{'bcc'} = $bcc{$type};
           }
     }      }
     foreach my $item (@contacts) {      foreach my $item (@contacts) {
         $to{$item} = $env{'form.'.$item};          $to{$item} = $env{'form.'.$item};
Line 3583  sub modify_contacts { Line 6599  sub modify_contacts {
             if ($others{$type} ne $currsetting{$type}{'others'}) {              if ($others{$type} ne $currsetting{$type}{'others'}) {
                 push(@{$changes{$type}},'others');                  push(@{$changes{$type}},'others');
             }              }
               if ($type eq 'helpdeskmail') {   
                   if ($bcc{$type} ne $currsetting{$type}{'bcc'}) {
                       push(@{$changes{$type}},'bcc'); 
                   }
               }
         }          }
     } else {      } else {
         my %default;          my %default;
Line 3591  sub modify_contacts { Line 6612  sub modify_contacts {
         $default{'errormail'} = 'adminemail';          $default{'errormail'} = 'adminemail';
         $default{'packagesmail'} = 'adminemail';          $default{'packagesmail'} = 'adminemail';
         $default{'helpdeskmail'} = 'supportemail';          $default{'helpdeskmail'} = 'supportemail';
           $default{'lonstatusmail'} = 'adminemail';
           $default{'requestsmail'} = '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;
Line 3603  sub modify_contacts { Line 6626  sub modify_contacts {
             }              }
             if ($others{$type} ne '') {              if ($others{$type} ne '') {
                 push(@{$changes{$type}},'others');                  push(@{$changes{$type}},'others');
             }               }
               if ($type eq 'helpdeskmail') {
                   if ($bcc{$type} ne '') {
                       push(@{$changes{$type}},'bcc');
                   }
               }
         }          }
     }      }
     my $putresult = &Apache::lonnet::put_dom('configuration',\%contacts_hash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%contacts_hash,
Line 3631  sub modify_contacts { Line 6659  sub modify_contacts {
                         push(@text,$others{$type});                          push(@text,$others{$type});
                     }                      }
                     $resulttext .= '<span class="LC_cusr_emph">'.                      $resulttext .= '<span class="LC_cusr_emph">'.
                                    join(', ',@text).'</span></li>';                                     join(', ',@text).'</span>';
                       if ($type eq 'helpdeskmail') {
                           if ($bcc{$type} ne '') {
                               $resulttext .= '&nbsp;'.&mt('with Bcc to').': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';
                           }
                       }
                       $resulttext .= '</li>';
                 }                  }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
Line 3657  sub modify_usercreation { Line 6691  sub modify_usercreation {
     my @username_rule = &Apache::loncommon::get_env_multiple('form.username_rule');      my @username_rule = &Apache::loncommon::get_env_multiple('form.username_rule');
     my @id_rule = &Apache::loncommon::get_env_multiple('form.id_rule');      my @id_rule = &Apache::loncommon::get_env_multiple('form.id_rule');
     my @email_rule = &Apache::loncommon::get_env_multiple('form.email_rule');      my @email_rule = &Apache::loncommon::get_env_multiple('form.email_rule');
     my @contexts = ('author','course','selfcreate');      my @contexts = ('author','course','requestcrs','selfcreate');
     foreach my $item(@contexts) {      foreach my $item(@contexts) {
         if ($item eq 'selfcreate') {          if ($item eq 'selfcreate') {
             @{$cancreate{$item}} = &Apache::loncommon::get_env_multiple('form.can_createuser_'.$item);              @{$cancreate{$item}} = &Apache::loncommon::get_env_multiple('form.can_createuser_'.$item);
Line 3673  sub modify_usercreation { Line 6707  sub modify_usercreation {
             $cancreate{$item} = $env{'form.can_createuser_'.$item};              $cancreate{$item} = $env{'form.can_createuser_'.$item};
         }          }
     }      }
       my ($othertitle,$usertypes,$types) = 
           &Apache::loncommon::sorted_inst_types($dom);
       if (ref($types) eq 'ARRAY') {
           if (@{$types} > 0) {
               @{$cancreate{'statustocreate'}} = 
                   &Apache::loncommon::get_env_multiple('form.statustocreate');
           } else {
               @{$cancreate{'statustocreate'}} = ();
           }
           push(@contexts,'statustocreate');
       }
       &process_captcha('cancreate',\%changes,\%cancreate,\%curr_usercreation);
     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') {              if (($item eq 'selfcreate') || ($item eq 'statustocreate')) {
                 if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') {                   if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') {
                     foreach my $curr (@{$curr_usercreation{'cancreate'}{$item}}) {                      foreach my $curr (@{$curr_usercreation{'cancreate'}{$item}}) {
                         if (!grep(/^$curr$/,@{$cancreate{$item}})) {                          if (ref($cancreate{$item}) eq 'ARRAY') {
                             if (!grep(/^$item$/,@{$changes{'cancreate'}})) {                              if (!grep(/^$curr$/,@{$cancreate{$item}})) {
                                 push(@{$changes{'cancreate'}},$item);                                  if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                       push(@{$changes{'cancreate'}},$item);
                                   }
                             }                              }
                         }                          }
                     }                      }
Line 3852  sub modify_usercreation { Line 6900  sub modify_usercreation {
             if (ref($changes{'cancreate'}) eq 'ARRAY') {              if (ref($changes{'cancreate'}) eq 'ARRAY') {
                 my %lt = &usercreation_types();                  my %lt = &usercreation_types();
                 foreach my $type (@{$changes{'cancreate'}}) {                  foreach my $type (@{$changes{'cancreate'}}) {
                     my $chgtext =  $lt{$type}.', ';                      my $chgtext;
                       unless (($type eq 'statustocreate') || ($type eq 'captcha') || ($type eq 'recaptchakeys')) {
                           $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('creation of a new user account is not permitted.');
                         } else {                          } else {
                             $chgtext .= &mt('creation of a new account is permitted for:<ul>');                              $chgtext .= &mt('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>';
                             }                              }
                             $chgtext .= '</ul>';                              $chgtext .= '</ul>';
                               if (ref($cancreate{$type}) eq 'ARRAY') {
                                   if (grep(/^(login|sso)$/,@{$cancreate{$type}})) {
                                       if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {
                                           if (@{$cancreate{'statustocreate'}} == 0) {
                                               $chgtext .= '<br /><span class="LC_warning">'.&mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").'</span>';
                                           }
                                       }
                                   }
                               }
                           }
                       } elsif ($type eq 'statustocreate') {
                           if ((ref($cancreate{'selfcreate'}) eq 'ARRAY') &&
                               (ref($cancreate{'statustocreate'}) eq 'ARRAY')) {
                               if (@{$cancreate{'selfcreate'}} > 0) {
                                   if (@{$cancreate{'statustocreate'}} == 0) {
   
                                       $chgtext .= &mt("Institutional affiliations permitted to create accounts set to 'None'.");
                                       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>';
                                       } 
                                   } elsif (ref($usertypes) eq 'HASH') {
                                       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):');
                                       } else {
                                           $chgtext .= &mt('Institutional affiliations permitted to create accounts with institutional authentication were set as follows:');
                                       }
                                       $chgtext .= '<ul>';
                                       foreach my $case (@{$cancreate{$type}}) {
                                           if ($case eq 'default') {
                                               $chgtext .= '<li>'.$othertitle.'</li>';
                                           } else {
                                               $chgtext .= '<li>'.$usertypes->{$case}.'</li>';
                                           }
                                       }
                                       $chgtext .= '</ul>';
                                       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>';
                                       }
                                   }
                               } else {
                                   if (@{$cancreate{$type}} == 0) {
                                       $chgtext .= &mt("Institutional affiliations permitted to create accounts were set to 'none'.");
                                   } else {
                                       $chgtext .= &mt('Although institutional affiliations permitted to create accounts were changed, self creation of accounts is not currently permitted for any authentication types.');
                                   }
                               }
                           }
                       } elsif ($type eq 'captcha') {
                           if ($cancreate{$type} eq 'notused') {
                               $chgtext .= &mt('No CAPTCHA validation in use for self-creation screen.');
                           } else {
                               my %captchas = &captcha_phrases();
                               if ($captchas{$cancreate{$type}}) {
                                   $chgtext .= &mt("Validation for self-creation screen set to $captchas{$cancreate{$type}}.");
                               } else {
                                   $chgtext .= &mt('Validation for self-creation screen set to unknown type.'); 
                               }
                         }                          }
                       } elsif ($type eq 'recaptchakeys') {
                           my ($privkey,$pubkey);
                           if (ref($cancreate{$type}) eq 'HASH') {
                               $pubkey = $cancreate{$type}{'public'};
                               $privkey = $cancreate{$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>';
                     } else {                      } else {
                         if ($cancreate{$type} eq 'none') {                          if ($cancreate{$type} eq 'none') {
                             $chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.');                              $chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.');
Line 3962  sub modify_usercreation { Line 7088  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);
Line 3970  sub modify_usermodification { Line 7149  sub modify_usermodification {
             $curr_usermodification{$key} = $domconfig{'usermodification'}{$key};              $curr_usermodification{$key} = $domconfig{'usermodification'}{$key};
         }          }
     }      }
     my @contexts = ('author','course');      my @contexts = ('author','course','selfcreate');
     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 3981  sub modify_usermodification { Line 7161  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;      my %modifyhash;
     foreach my $context (@contexts) {      foreach my $context (@contexts) {
Line 4028  sub modify_usermodification { Line 7214  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 ($role eq 'cr') {                              if ($context eq 'selfcreate') {
                                 $rolename = &mt('Custom');                                  $rolename = $role;
                                   if (ref($usertypes) eq 'HASH') {
                                       if ($usertypes->{$role} ne '') {
                                           $rolename = $usertypes->{$role};
                                       }
                                   }
                             } else {                              } else {
                                 $rolename = &Apache::lonnet::plaintext($role);                                  if ($role eq 'cr') {
                                       $rolename = &mt('Custom');
                                   } else {
                                       $rolename = &Apache::lonnet::plaintext($role);
                                   }
                             }                              }
                             my @modifiable;                              my @modifiable;
                             $resulttext .= '<li><span class="LC_cusr_emph">'.&mt('Target user with [_1] role',$rolename).'</span> - '.&mt('modifiable fields: ');                              if ($context eq 'selfcreate') {
                                   $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 4066  sub modify_defaults { Line 7265  sub modify_defaults {
     my ($dom,$r) = @_;      my ($dom,$r) = @_;
     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);
     my @items = ('auth_def','auth_arg_def','lang_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 4080  sub modify_defaults { Line 7279  sub modify_defaults {
             if ($newvalues{$item} ne '') {              if ($newvalues{$item} ne '') {
                 if ($newvalues{$item} =~ /^(\w+)/) {                  if ($newvalues{$item} =~ /^(\w+)/) {
                     my $langcode = $1;                      my $langcode = $1;
                     if (code2language($langcode) eq '') {                      if ($langcode ne 'x_chef') {
                         push(@errors,$item);                          if (code2language($langcode) eq '') {
                               push(@errors,$item);
                           }
                     }                      }
                 } else {                  } else {
                     push(@errors,$item);                      push(@errors,$item);
                 }                  }
             }              }
           } elsif ($item eq 'timezone_def') {
               if ($newvalues{$item} ne '') {
                   if (!DateTime::TimeZone->is_valid_name($newvalues{$item})) {
                       push(@errors,$item);   
                   }
               }
           } elsif ($item eq 'datelocale_def') {
               if ($newvalues{$item} ne '') {
                   my @datelocale_ids = DateTime::Locale->ids();
                   if (!grep(/^\Q$newvalues{$item}\E$/,@datelocale_ids)) {
                       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};
         } elsif ($domdefaults{$item} ne $newvalues{$item}) {          } elsif ($domdefaults{$item} ne $newvalues{$item}) {
             $changes{$item} = 1;              $changes{$item} = 1;
         }          }
           $domdefaults{$item} = $newvalues{$item};
     }      }
     my %defaults_hash = (      my %defaults_hash = (
                          defaults => { auth_def => $newvalues{'auth_def'},                           defaults => \%newvalues,
                                        auth_arg_def => $newvalues{'auth_arg_def'},                          );
                                        lang_def => $newvalues{'lang_def'},  
                                      }  
                        );  
     my $title = &defaults_titles();      my $title = &defaults_titles();
     my $putresult = &Apache::lonnet::put_dom('configuration',\%defaults_hash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%defaults_hash,
                                              $dom);                                               $dom);
Line 4128  sub modify_defaults { Line 7346  sub modify_defaults {
             $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,              &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
                                           $defaults_hash{'defaults'},$cachetime);              if ($changes{'auth_def'} || $changes{'auth_arg_def'} || $changes{'lang_def'} || $changes{'datelocale_def'}) {
             my $sysmail = $r->dir_config('lonSysEMail');                  my $sysmail = $r->dir_config('lonSysEMail');
             &Apache::lonmsg::sendemail($sysmail,"LON-CAPA Domain Settings Change - $dom",$mailmsgtext);                  &Apache::lonmsg::sendemail($sysmail,"LON-CAPA Domain Settings Change - $dom",$mailmsgtext);
               }
         } else {          } else {
             $resulttext = &mt('No changes made to default authentication/language settings');              $resulttext = &mt('No changes made to default authentication/language/timezone settings');
         }          }
     } else {      } else {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
Line 4161  sub modify_scantron { Line 7380  sub modify_scantron {
         my $error;          my $error;
         if ($configuserok eq 'ok') {          if ($configuserok eq 'ok') {
             if ($switchserver) {              if ($switchserver) {
                 $error = &mt("Upload of scantron format file is not permitted to this server: [_1]",$switchserver);                  $error = &mt("Upload of bubblesheet format file is not permitted to this server: [_1]",$switchserver);
             } else {              } else {
                 if ($author_ok eq 'ok') {                  if ($author_ok eq 'ok') {
                     my ($result,$scantronurl) =                      my ($result,$scantronurl) =
Line 4201  sub modify_scantron { Line 7420  sub modify_scantron {
                 if (ref($confhash{'scantron'}) eq 'HASH') {                  if (ref($confhash{'scantron'}) eq 'HASH') {
                     $resulttext = &mt('Changes made:').'<ul>';                      $resulttext = &mt('Changes made:').'<ul>';
                     if ($confhash{'scantron'}{'scantronformat'} eq '') {                      if ($confhash{'scantron'}{'scantronformat'} eq '') {
                         $resulttext .= '<li>'.&mt('[_1] scantron format file removed; [_2] file will be used for courses in this domain.',$custom,$default).'</li>';                          $resulttext .= '<li>'.&mt('[_1] bubblesheet format file removed; [_2] file will be used for courses in this domain.',$custom,$default).'</li>';
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('Custom scantron format file ([_1]) uploaded for use with courses in this domain.',$custom).'</li>';                          $resulttext .= '<li>'.&mt('Custom bubblesheet format file ([_1]) uploaded for use with courses in this domain.',$custom).'</li>';
                     }                      }
                     $resulttext .= '</ul>';                      $resulttext .= '</ul>';
                 } else {                  } else {
                     $resulttext = &mt('Changes made to scantron format file.');                      $resulttext = &mt('Changes made to bubblesheet format file.');
                 }                  }
                 $resulttext .= '</ul>';                  $resulttext .= '</ul>';
                 &Apache::loncommon::devalidate_domconfig_cache($dom);                  &Apache::loncommon::devalidate_domconfig_cache($dom);
             } else {              } else {
                 $resulttext = &mt('No changes made to scantron format file');                  $resulttext = &mt('No changes made to bubblesheet format file');
             }              }
         } 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 scantron format file');           $resulttext = &mt('No changes made to bubblesheet format file'); 
     }      }
     if ($errors) {      if ($errors) {
         $resulttext .= &mt('The following errors occurred: ').'<ul>'.          $resulttext .= &mt('The following errors occurred: ').'<ul>'.
Line 4230  sub modify_scantron { Line 7449  sub modify_scantron {
   
 sub modify_coursecategories {  sub modify_coursecategories {
     my ($dom,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%deletions,%reorderings,%needreordering,%adds,$errors);      my ($resulttext,%deletions,%reorderings,%needreordering,%adds,%changes,$errors,
           $cathash);
     my @deletecategory = &Apache::loncommon::get_env_multiple('form.deletecategory');      my @deletecategory = &Apache::loncommon::get_env_multiple('form.deletecategory');
     if (($domconfig{'coursecategories'}{'instcode::0'} ne '')  && ($env{'form.instcode'} == 0)) {  
         push (@deletecategory,'instcode::0');  
     }  
     my (@predelcats,@predeltrails,%predelallitems);  
     if (ref($domconfig{'coursecategories'}) eq 'HASH') {      if (ref($domconfig{'coursecategories'}) eq 'HASH') {
           $cathash = $domconfig{'coursecategories'}{'cats'};
           if ($domconfig{'coursecategories'}{'togglecats'} ne $env{'form.togglecats'}) {
               $changes{'togglecats'} = 1;
               $domconfig{'coursecategories'}{'togglecats'} = $env{'form.togglecats'};
           }
           if ($domconfig{'coursecategories'}{'categorize'} ne $env{'form.categorize'}) {
               $changes{'categorize'} = 1;
               $domconfig{'coursecategories'}{'categorize'} = $env{'form.categorize'};
           }
           if ($domconfig{'coursecategories'}{'togglecatscomm'} ne $env{'form.togglecatscomm'}) {
               $changes{'togglecatscomm'} = 1;
               $domconfig{'coursecategories'}{'togglecatscomm'} = $env{'form.togglecatscomm'};
           }
           if ($domconfig{'coursecategories'}{'categorizecomm'} ne $env{'form.categorizecomm'}) {
               $changes{'categorizecomm'} = 1;
               $domconfig{'coursecategories'}{'categorizecomm'} = $env{'form.categorizecomm'};
           }
       } else {
           $changes{'togglecats'} = 1;
           $changes{'categorize'} = 1;
           $changes{'togglecatscomm'} = 1;
           $changes{'categorizecomm'} = 1;
           $domconfig{'coursecategories'} = {
                                                togglecats => $env{'form.togglecats'},
                                                categorize => $env{'form.categorize'},
                                                togglecatscomm => $env{'form.togglecatscomm'},
                                                categorizecomm => $env{'form.categorizecomm'},
                                            };
       }
       if (ref($cathash) eq 'HASH') {
           if (($domconfig{'coursecategories'}{'cats'}{'instcode::0'} ne '')  && ($env{'form.instcode'} == 0)) {
               push (@deletecategory,'instcode::0');
           }
           if (($domconfig{'coursecategories'}{'cats'}{'communities::0'} ne '')  && ($env{'form.communities'} == 0)) {
               push(@deletecategory,'communities::0');
           }
       }
       my (@predelcats,@predeltrails,%predelallitems,%sort_by_deltrail);
       if (ref($cathash) eq 'HASH') {
         if (@deletecategory > 0) {          if (@deletecategory > 0) {
             #FIXME Need to remove category from all courses using a deleted category               #FIXME Need to remove category from all courses using a deleted category 
             &extract_categories($domconfig{'coursecategories'},\@predelcats,\@predeltrails,\%predelallitems);              &Apache::loncommon::extract_categories($cathash,\@predelcats,\@predeltrails,\%predelallitems);
             foreach my $item (@deletecategory) {              foreach my $item (@deletecategory) {
                 if ($domconfig{'coursecategories'}{$item} ne '') {                  if ($domconfig{'coursecategories'}{'cats'}{$item} ne '') {
                     delete($domconfig{'coursecategories'}{$item});                      delete($domconfig{'coursecategories'}{'cats'}{$item});
                     $deletions{$item} = 1;                      $deletions{$item} = 1;
                     &recurse_cat_deletes($item,$domconfig{'coursecategories'},                      &recurse_cat_deletes($item,$cathash,\%deletions);
                                          \%deletions);  
                 }                  }
             }              }
         }          }
         foreach my $item (keys(%{$domconfig{'coursecategories'}})) {          foreach my $item (keys(%{$cathash})) {
             my ($cat,$container,$depth) = map { &unescape($_); } split(/:/,$item);              my ($cat,$container,$depth) = map { &unescape($_); } split(/:/,$item);
             if ($domconfig{'coursecategories'}{$item} ne $env{'form.'.$item}) {              if ($cathash->{$item} ne $env{'form.'.$item}) {
                 $reorderings{$item} = 1;                  $reorderings{$item} = 1;
                 $domconfig{'coursecategories'}{$item} = $env{'form.'.$item};                  $domconfig{'coursecategories'}{'cats'}{$item} = $env{'form.'.$item};
             }              }
             if ($env{'form.addcategory_name_'.$item} ne '') {              if ($env{'form.addcategory_name_'.$item} ne '') {
                 my $newcat = $env{'form.addcategory_name_'.$item};                  my $newcat = $env{'form.addcategory_name_'.$item};
                 my $newdepth = $depth+1;                  my $newdepth = $depth+1;
                 my $newitem = &escape($newcat).':'.&escape($cat).':'.$newdepth;                  my $newitem = &escape($newcat).':'.&escape($cat).':'.$newdepth;
                 $domconfig{'coursecategories'}{$newitem} = $env{'form.addcategory_pos_'.$item};                  $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.addcategory_pos_'.$item};
                 $adds{$newitem} = 1;                   $adds{$newitem} = 1; 
             }              }
             if ($env{'form.subcat_'.$item} ne '') {              if ($env{'form.subcat_'.$item} ne '') {
                 my $newcat = $env{'form.subcat_'.$item};                  my $newcat = $env{'form.subcat_'.$item};
                 my $newdepth = $depth+1;                  my $newdepth = $depth+1;
                 my $newitem = &escape($newcat).':'.&escape($cat).':'.$newdepth;                  my $newitem = &escape($newcat).':'.&escape($cat).':'.$newdepth;
                 $domconfig{'coursecategories'}{$newitem} = 0;                  $domconfig{'coursecategories'}{'cats'}{$newitem} = 0;
                 $adds{$newitem} = 1;                  $adds{$newitem} = 1;
             }              }
         }          }
     }      }
     if ($env{'form.instcode'} eq '1') {      if ($env{'form.instcode'} eq '1') {
         if (ref($domconfig{'coursecategories'}) eq 'HASH') {          if (ref($cathash) eq 'HASH') {
             my $newitem = 'instcode::0';              my $newitem = 'instcode::0';
             if ($domconfig{'coursecategories'}{$newitem} eq '') {                if ($cathash->{$newitem} eq '') {  
                 $domconfig{'coursecategories'}{$newitem} = $env{'form.instcode_pos'};                  $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.instcode_pos'};
                 $adds{$newitem} = 1;                  $adds{$newitem} = 1;
             }              }
         } else {          } else {
             my $newitem = 'instcode::0';              my $newitem = 'instcode::0';
             $domconfig{'coursecategories'}{$newitem} = $env{'form.instcode_pos'};              $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.instcode_pos'};
               $adds{$newitem} = 1;
           }
       }
       if ($env{'form.communities'} eq '1') {
           if (ref($cathash) eq 'HASH') {
               my $newitem = 'communities::0';
               if ($cathash->{$newitem} eq '') {
                   $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.communities_pos'};
                   $adds{$newitem} = 1;
               }
           } else {
               my $newitem = 'communities::0';
               $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.communities_pos'};
             $adds{$newitem} = 1;              $adds{$newitem} = 1;
         }          }
     }      }
     if ($env{'form.addcategory_name'} ne '') {      if ($env{'form.addcategory_name'} ne '') {
         my $newitem = &escape($env{'form.addcategory_name'}).'::0';          if (($env{'form.addcategory_name'} ne 'instcode') &&
         $domconfig{'coursecategories'}{$newitem} = $env{'form.addcategory_pos'};              ($env{'form.addcategory_name'} ne 'communities')) {
         $adds{$newitem} = 1;              my $newitem = &escape($env{'form.addcategory_name'}).'::0';
               $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.addcategory_pos'};
               $adds{$newitem} = 1;
           }
     }      }
       my $putresult;
     if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {      if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {
         my %sort_by_deltrail;  
         if (keys(%deletions) > 0) {          if (keys(%deletions) > 0) {
             foreach my $key (keys(%deletions)) {              foreach my $key (keys(%deletions)) {
                 if ($predelallitems{$key} ne '') {                  if ($predelallitems{$key} ne '') {
Line 4299  sub modify_coursecategories { Line 7569  sub modify_coursecategories {
             }              }
         }          }
         my (@chkcats,@chktrails,%chkallitems);          my (@chkcats,@chktrails,%chkallitems);
         &extract_categories($domconfig{'coursecategories'},\@chkcats,\@chktrails,\%chkallitems);          &Apache::loncommon::extract_categories($domconfig{'coursecategories'}{'cats'},\@chkcats,\@chktrails,\%chkallitems);
         if (ref($chkcats[0]) eq 'ARRAY') {          if (ref($chkcats[0]) eq 'ARRAY') {
             my $depth = 0;              my $depth = 0;
             my $chg = 0;              my $chg = 0;
Line 4311  sub modify_coursecategories { Line 7581  sub modify_coursecategories {
                 } else {                  } else {
                     $item = &escape($name).'::0';                      $item = &escape($name).'::0';
                     if ($chg) {                      if ($chg) {
                         $domconfig{'coursecategories'}{$item} -= $chg;                          $domconfig{'coursecategories'}{'cats'}{$item} -= $chg;
                     }                      }
                     $depth ++;                       $depth ++; 
                     &recurse_check(\@chkcats,$domconfig{'coursecategories'},$depth,$name);                      &recurse_check(\@chkcats,$domconfig{'coursecategories'}{'cats'},$depth,$name);
                     $depth --;                      $depth --;
                 }                  }
             }              }
         }          }
         my $putresult = &Apache::lonnet::put_dom('configuration',\%domconfig,$dom);      }
         my (@cats,@trails,%allitems);      if ((keys(%changes) > 0) || (keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {
         &extract_categories($domconfig{'coursecategories'},\@cats,\@trails,\%allitems);          $putresult = &Apache::lonnet::put_dom('configuration',\%domconfig,$dom);
         if ($putresult eq 'ok') {          if ($putresult eq 'ok') {
               my %title = (
                            togglecats     => 'Show/Hide a course in catalog',
                            categorize     => 'Assign a category to a course',
                            togglecatscomm => 'Show/Hide a community in catalog',
                            categorizecomm => 'Assign a category to a community',
                           );
               my %level = (
                            dom  => 'set in Domain ("Modify Course/Community")',
                            crs  => 'set in Course ("Course Configuration")',
                            comm => 'set in Community ("Community Configuration")',
                           );
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if (keys(%deletions) > 0) {              if ($changes{'togglecats'}) {
                 $resulttext .= '<li>'.&mt('Deleted categories:').'<ul>';                  $resulttext .= '<li>'.&mt("$title{'togglecats'} $level{$env{'form.togglecats'}}").'</li>'; 
                 foreach my $predeltrail (sort {$a <=> $b } (keys(%sort_by_deltrail))) {               }
                     $resulttext .= '<li>'.$predeltrails[$predeltrail].'</li>';              if ($changes{'categorize'}) {
                   $resulttext .= '<li>'.&mt("$title{'categorize'} $level{$env{'form.categorize'}}").'</li>';
               }
               if ($changes{'togglecatscomm'}) {
                   $resulttext .= '<li>'.&mt("$title{'togglecatscomm'} $level{$env{'form.togglecatscomm'}}").'</li>';
               }
               if ($changes{'categorizecomm'}) {
                   $resulttext .= '<li>'.&mt("$title{'categorizecomm'} $level{$env{'form.categorizecomm'}}").'</li>';
               }
               if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {
                   my $cathash;
                   if (ref($domconfig{'coursecategories'}) eq 'HASH') {
                       $cathash = $domconfig{'coursecategories'}{'cats'};
                   } else {
                       $cathash = {};
                   } 
                   my (@cats,@trails,%allitems);
                       &Apache::loncommon::extract_categories($cathash,\@cats,\@trails,\%allitems);
                   if (keys(%deletions) > 0) {
                       $resulttext .= '<li>'.&mt('Deleted categories:').'<ul>';
                       foreach my $predeltrail (sort {$a <=> $b } (keys(%sort_by_deltrail))) { 
                           $resulttext .= '<li>'.$predeltrails[$predeltrail].'</li>';
                       }
                       $resulttext .= '</ul></li>';
                   }
                   if (keys(%reorderings) > 0) {
                       my %sort_by_trail;
                       $resulttext .= '<li>'.&mt('Reordered categories:').'<ul>';
                       foreach my $key (keys(%reorderings)) {
                           if ($allitems{$key} ne '') {
                               $sort_by_trail{$allitems{$key}} = $trails[$allitems{$key}];
                           }
                       }
                       foreach my $trail (sort {$a <=> $b } (keys(%sort_by_trail))) {
                           $resulttext .= '<li>'.$trails[$trail].'</li>';
                       }
                       $resulttext .= '</ul></li>';
                   }
                   if (keys(%adds) > 0) {
                       my %sort_by_trail;
                       $resulttext .= '<li>'.&mt('Added categories:').'<ul>';
                       foreach my $key (keys(%adds)) {
                           if ($allitems{$key} ne '') {
                               $sort_by_trail{$allitems{$key}} = $trails[$allitems{$key}];
                           }
                       }
                       foreach my $trail (sort {$a <=> $b } (keys(%sort_by_trail))) {
                           $resulttext .= '<li>'.$trails[$trail].'</li>';
                       }
                       $resulttext .= '</ul></li>';
                 }                  }
                 $resulttext .= '</ul></li>';  
             }              }
             if (keys(%reorderings) > 0) {              $resulttext .= '</ul>';
                 my %sort_by_trail;          } else {
                 $resulttext .= '<li>'.&mt('Reordered categories:').'<ul>';              $resulttext = '<span class="LC_error">'.
                 foreach my $key (keys(%reorderings)) {                            &mt('An error occurred: [_1]',$putresult).'</span>';
                     if ($allitems{$key} ne '') {          }
                         $sort_by_trail{$allitems{$key}} = $trails[$allitems{$key}];      } else {
           $resulttext = &mt('No changes made to course and community categories');
       }
       return $resulttext;
   }
   
   sub modify_serverstatuses {
       my ($dom,%domconfig) = @_;
       my ($resulttext,%changes,%currserverstatus,%newserverstatus);
       if (ref($domconfig{'serverstatuses'}) eq 'HASH') {
           %currserverstatus = %{$domconfig{'serverstatuses'}};
       }
       my @pages = &serverstatus_pages();
       foreach my $type (@pages) {
           $newserverstatus{$type}{'namedusers'} = '';
           $newserverstatus{$type}{'machines'} = '';
           if (defined($env{'form.'.$type.'_namedusers'})) {
               my @users = split(/,/,$env{'form.'.$type.'_namedusers'});
               my @okusers;
               foreach my $user (@users) {
                   my ($uname,$udom) = split(/:/,$user);
                   if (($udom =~ /^$match_domain$/) &&   
                       (&Apache::lonnet::domain($udom)) &&
                       ($uname =~ /^$match_username$/)) {
                       if (!grep(/^\Q$user\E/,@okusers)) {
                           push(@okusers,$user);
                     }                      }
                 }                  }
                 foreach my $trail (sort {$a <=> $b } (keys(%sort_by_trail))) {              }
                     $resulttext .= '<li>'.$trails[$trail].'</li>';              if (@okusers > 0) {
                    @okusers = sort(@okusers);
                    $newserverstatus{$type}{'namedusers'} = join(',',@okusers);
               }
           }
           if (defined($env{'form.'.$type.'_machines'})) {
               my @machines = split(/,/,$env{'form.'.$type.'_machines'});
               my @okmachines;
               foreach my $ip (@machines) {
                   my @parts = split(/\./,$ip);
                   next if (@parts < 4);
                   my $badip = 0;
                   for (my $i=0; $i<4; $i++) {
                       if (!(($parts[$i] >= 0) && ($parts[$i] <= 255))) {
                           $badip = 1;
                           last;
                       }
                   }
                   if (!$badip) {
                       push(@okmachines,$ip);     
                 }                  }
                 $resulttext .= '</ul></li>';  
             }              }
             if (keys(%adds) > 0) {              @okmachines = sort(@okmachines);
                 my %sort_by_trail;              $newserverstatus{$type}{'machines'} = join(',',@okmachines);
                 $resulttext .= '<li>'.&mt('Added categories:').'<ul>';          }
                 foreach my $key (keys(%adds)) {      }
                     if ($allitems{$key} ne '') {      my %serverstatushash =  (
                         $sort_by_trail{$allitems{$key}} = $trails[$allitems{$key}];                                  serverstatuses => \%newserverstatus,
                               );
       foreach my $type (@pages) {
           foreach my $setting ('namedusers','machines') {
               my (@current,@new);
               if (ref($currserverstatus{$type}) eq 'HASH') {
                   if ($currserverstatus{$type}{$setting} ne '') { 
                       @current = split(/,/,$currserverstatus{$type}{$setting});
                   }
               }
               if ($newserverstatus{$type}{$setting} ne '') {
                   @new = split(/,/,$newserverstatus{$type}{$setting});
               }
               if (@current > 0) {
                   if (@new > 0) {
                       foreach my $item (@current) {
                           if (!grep(/^\Q$item\E$/,@new)) {
                               $changes{$type}{$setting} = 1;
                               last;
                           }
                     }                      }
                       foreach my $item (@new) {
                           if (!grep(/^\Q$item\E$/,@current)) {
                               $changes{$type}{$setting} = 1;
                               last;
                           }
                       }
                   } else {
                       $changes{$type}{$setting} = 1;
                 }                  }
                 foreach my $trail (sort {$a <=> $b } (keys(%sort_by_trail))) {              } elsif (@new > 0) {
                     $resulttext .= '<li>'.$trails[$trail].'</li>';                  $changes{$type}{$setting} = 1;
               }
           }
       }
       if (keys(%changes) > 0) {
           my $titles= &LONCAPA::lonauthcgi::serverstatus_titles();
           my $putresult = &Apache::lonnet::put_dom('configuration',
                                                    \%serverstatushash,$dom);
           if ($putresult eq 'ok') {
               $resulttext .= &mt('Changes made:').'<ul>';
               foreach my $type (@pages) {
                   if (ref($changes{$type}) eq 'HASH') {
                       $resulttext .= '<li>'.$titles->{$type}.'<ul>';
                       if ($changes{$type}{'namedusers'}) {
                           if ($newserverstatus{$type}{'namedusers'} eq '') {
                               $resulttext .= '<li>'.&mt("Access terminated for all specific (named) users").'</li>'."\n";
                           } else {
                               $resulttext .= '<li>'.&mt("Access available for the following specified users: ").$newserverstatus{$type}{'namedusers'}.'</li>'."\n";
                           }
                       }
                       if ($changes{$type}{'machines'}) {
                           if ($newserverstatus{$type}{'machines'} eq '') {
                               $resulttext .= '<li>'.&mt("Access terminated for all specific IP addresses").'</li>'."\n";
                           } else {
                               $resulttext .= '<li>'.&mt("Access available for the following specified IP addresses: ").$newserverstatus{$type}{'machines'}.'</li>'."\n";
                           }
   
                       }
                       $resulttext .= '</ul></li>';
                 }                  }
                 $resulttext .= '</ul></li>';  
             }              }
             $resulttext .= '</ul>';              $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 saving access settings for server status pages: [_1].',$putresult).'</span>';
   
           }
       } else {
           $resulttext = &mt('No changes made to access to server status pages');
       }
       return $resulttext;
   }
   
   sub modify_helpsettings {
       my ($r,$dom,$confname,%domconfig) = @_;
       my ($resulttext,$errors,%changes,%helphash);
       my %defaultchecked = ('submitbugs' => 'on');
       my @offon = ('off','on');
       my @toggles = ('submitbugs');
       if (ref($domconfig{'helpsettings'}) eq 'HASH') {
           foreach my $item (@toggles) {
               if ($defaultchecked{$item} eq 'on') { 
                   if ($domconfig{'helpsettings'}{$item} eq '') {
                       if ($env{'form.'.$item} eq '0') {
                           $changes{$item} = 1;
                       }
                   } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {
                       $changes{$item} = 1;
                   }
               } elsif ($defaultchecked{$item} eq 'off') {
                   if ($domconfig{'helpsettings'}{$item} eq '') {
                       if ($env{'form.'.$item} eq '1') {
                           $changes{$item} = 1;
                       }
                   } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {
                       $changes{$item} = 1;
                   }
               }
               if (($env{'form.'.$item} eq '0') || ($env{'form.'.$item} eq '1')) { 
                   $helphash{'helpsettings'}{$item} = $env{'form.'.$item};
               }
           }
       }
       my $putresult;
       if (keys(%changes) > 0) {
           $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom);
           if ($putresult eq 'ok') {
               $resulttext = &mt('Changes made:').'<ul>';
               foreach my $item (sort(keys(%changes))) {
                   if ($item eq 'submitbugs') {
                       $resulttext .= '<li>'.&mt('Display link to: [_1] set to "'.$offon[$env{'form.'.$item}].'".',
                                                 &Apache::loncommon::modal_link('http://bugs.loncapa.org',
                                                 &mt('LON-CAPA bug tracker'),600,500)).'</li>';
                   }
               }
               $resulttext .= '</ul>';
           } else {
               $resulttext = &mt('No changes made to help settings');
               $errors .= '<li><span class="LC_error">'.
                          &mt('An error occurred storing the settings: [_1]',
                              $putresult).'</span></li>';
           }
       }
       if ($errors) {
           $resulttext .= '<br />'.&mt('The following errors occurred: ').'<ul>'.
                          $errors.'</ul>';
       }
       return $resulttext;
   }
   
   sub modify_coursedefaults {
       my ($dom,%domconfig) = @_;
       my ($resulttext,$errors,%changes,%defaultshash);
       my %defaultchecked = ('canuse_pdfforms' => 'off');
       my @offon = ('off','on');
       my @toggles = ('canuse_pdfforms');
   
       $defaultshash{'coursedefaults'} = {};
   
       if (ref($domconfig{'coursedefaults'}) ne 'HASH') {
           if ($domconfig{'coursedefaults'} eq '') {
               $domconfig{'coursedefaults'} = {};
           }
       }
   
       if (ref($domconfig{'coursedefaults'}) eq 'HASH') {
           foreach my $item (@toggles) {
               if ($defaultchecked{$item} eq 'on') {
                   if (($domconfig{'coursedefaults'}{$item} eq '') &&
                       ($env{'form.'.$item} eq '0')) {
                       $changes{$item} = 1;
                   } elsif ($domconfig{'coursdefaults'}{$item} ne $env{'form.'.$item}) {
                       $changes{$item} = 1;
                   }
               } elsif ($defaultchecked{$item} eq 'off') {
                   if (($domconfig{'coursedefaults'}{$item} eq '') &&
                       ($env{'form.'.$item} eq '1')) {
                       $changes{$item} = 1;
                   } elsif ($domconfig{'coursedefaults'}{$item} ne $env{'form.'.$item}) {
                       $changes{$item} = 1;
                   }
               }
               $defaultshash{'coursedefaults'}{$item} = $env{'form.'.$item};
           }
           my $currdefresponder = $domconfig{'coursedefaults'}{'anonsurvey_threshold'};
           my $newdefresponder = $env{'form.anonsurvey_threshold'};
           $newdefresponder =~ s/\D//g;
           if ($newdefresponder eq '' || $newdefresponder < 1) {
               $newdefresponder = 1;
           }
           $defaultshash{'coursedefaults'}{'anonsurvey_threshold'} = $newdefresponder;
           if ($currdefresponder ne $newdefresponder) {
               unless ($currdefresponder eq '' && $newdefresponder == 10) {
                   $changes{'anonsurvey_threshold'} = 1;
               }
           }
       }
       my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                                $dom);
       if ($putresult eq 'ok') {
           if (keys(%changes) > 0) {
               if ($changes{'canuse_pdfforms'}) {
                   my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
                   $domdefaults{'canuse_pdfforms'}=$defaultshash{'coursedefaults'}{'canuse_pdfforms'};
                   my $cachetime = 24*60*60;
                   &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               }
               $resulttext = &mt('Changes made:').'<ul>';
               foreach my $item (sort(keys(%changes))) {
                   if ($item eq 'canuse_pdfforms') {
                       if ($env{'form.'.$item} eq '1') {
                           $resulttext .= '<li>'.&mt("Course/Community users can create/upload PDF forms set to 'on'").'</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('Course/Community users can create/upload PDF forms set to "off"').'</li>';
                       }
                   } 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 .= '</ul>';
           } else {
               $resulttext = &mt('No changes made to course defaults');
           }
       } else {
           $resulttext = '<span class="LC_error">'.
               &mt('An error occurred: [_1]',$putresult).'</span>';
       }
       return $resulttext;
   }
   
   sub modify_usersessions {
       my ($dom,%domconfig) = @_;
       my @hostingtypes = ('version','excludedomain','includedomain');
       my @offloadtypes = ('primary','default');
       my %types = (
                     remote => \@hostingtypes,
                     hosted => \@hostingtypes,
                     spares => \@offloadtypes,
                   );
       my @prefixes = ('remote','hosted','spares');
       my @lcversions = &Apache::lonnet::all_loncaparevs();
       my (%by_ip,%by_location,@intdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location);
       my @locations = sort(keys(%by_location));
       my (%defaultshash,%changes);
       foreach my $prefix (@prefixes) {
           $defaultshash{'usersessions'}{$prefix} = {};
       }
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
       my $resulttext;
       my %iphost = &Apache::lonnet::get_iphost();
       foreach my $prefix (@prefixes) {
           next if ($prefix eq 'spares');
           foreach my $type (@{$types{$prefix}}) {
               my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
               if ($type eq 'version') {
                   my $value = $env{'form.'.$prefix.'_'.$type};
                   my $okvalue;
                   if ($value ne '') {
                       if (grep(/^\Q$value\E$/,@lcversions)) {
                           $okvalue = $value;
                       }
                   }
                   if (ref($domconfig{'usersessions'}) eq 'HASH') {
                       if (ref($domconfig{'usersessions'}{$prefix}) eq 'HASH') {
                           if ($domconfig{'usersessions'}{$prefix}{$type} ne '') {
                               if ($inuse == 0) {
                                   $changes{$prefix}{$type} = 1;
                               } else {
                                   if ($okvalue ne $domconfig{'usersessions'}{$prefix}{$type}) {
                                       $changes{$prefix}{$type} = 1;
                                   }
                                   if ($okvalue ne '') {
                                       $defaultshash{'usersessions'}{$prefix}{$type} = $okvalue;
                                   } 
                               }
                           } else {
                               if (($inuse == 1) && ($okvalue ne '')) {
                                   $defaultshash{'usersessions'}{$prefix}{$type} = $okvalue;
                                   $changes{$prefix}{$type} = 1;
                               }
                           }
                       } else {
                           if (($inuse == 1) && ($okvalue ne '')) {
                               $defaultshash{'usersessions'}{$prefix}{$type} = $okvalue;
                               $changes{$prefix}{$type} = 1;
                           }
                       }
                   } else {
                       if (($inuse == 1) && ($okvalue ne '')) {
                           $defaultshash{'usersessions'}{$prefix}{$type} = $okvalue;
                           $changes{$prefix}{$type} = 1;
                       }
                   }
               } else {
                   my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
                   my @okvals;
                   foreach my $val (@vals) {
                       if ($val =~ /:/) {
                           my @items = split(/:/,$val);
                           foreach my $item (@items) {
                               if (ref($by_location{$item}) eq 'ARRAY') {
                                   push(@okvals,$item);
                               }
                           }
                       } else {
                           if (ref($by_location{$val}) eq 'ARRAY') {
                               push(@okvals,$val);
                           }
                       }
                   }
                   @okvals = sort(@okvals);
                   if (ref($domconfig{'usersessions'}) eq 'HASH') {
                       if (ref($domconfig{'usersessions'}{$prefix}) eq 'HASH') {
                           if (ref($domconfig{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {
                               if ($inuse == 0) {
                                   $changes{$prefix}{$type} = 1; 
                               } else {
                                   $defaultshash{'usersessions'}{$prefix}{$type} = \@okvals;
                                   my @changed = &Apache::loncommon::compare_arrays($domconfig{'usersessions'}{$prefix}{$type},$defaultshash{'usersessions'}{$prefix}{$type});
                                   if (@changed > 0) {
                                       $changes{$prefix}{$type} = 1;
                                   }
                               }
                           } else {
                               if ($inuse == 1) {
                                   $defaultshash{'usersessions'}{$prefix}{$type} = \@okvals;
                                   $changes{$prefix}{$type} = 1;
                               }
                           } 
                       } else {
                           if ($inuse == 1) {
                               $defaultshash{'usersessions'}{$prefix}{$type} = \@okvals;
                               $changes{$prefix}{$type} = 1;
                           }
                       }
                   } else {
                       if ($inuse == 1) {
                           $defaultshash{'usersessions'}{$prefix}{$type} = \@okvals;
                           $changes{$prefix}{$type} = 1;
                       }
                   }
               }
           }
       }
   
       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,
                                                    $dom);
           if ($putresult eq 'ok') {
               if (ref($defaultshash{'usersessions'}) eq 'HASH') {
                   if (ref($defaultshash{'usersessions'}{'remote'}) eq 'HASH') {
                       $domdefaults{'remotesessions'} = $defaultshash{'usersessions'}{'remote'};
                   }
                   if (ref($defaultshash{'usersessions'}{'hosted'}) eq 'HASH') {
                       $domdefaults{'hostedsessions'} = $defaultshash{'usersessions'}{'hosted'};
                   }
               }
               my $cachetime = 24*60*60;
               &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (keys(%changes) > 0) {
                   my %lt = &usersession_titles();
                   $resulttext = &mt('Changes made:').'<ul>';
                   foreach my $prefix (@prefixes) {
                       if (ref($changes{$prefix}) eq 'HASH') {
                           $resulttext .= '<li>'.$lt{$prefix}.'<ul>';
                           if ($prefix eq 'spares') {
                               if (ref($changes{$prefix}) eq 'HASH') {
                                   foreach my $lonhost (sort(keys(%{$changes{$prefix}}))) {
                                       $resulttext .= '<li><b>'.$lonhost.'</b> ';
                                       my $lonhostdom = &Apache::lonnet::host_domain($lonhost);
                                       &Apache::lonnet::remote_devalidate_cache($lonhost,'spares',$lonhostdom);
                                       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>';
                                       }
                                   }
                               }
                           }
                           $resulttext .= '</ul>';
                       }
                   }
                   $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) {
                   if (ref($changes{'delete'}) eq 'ARRAY') {
                       foreach my $balancer (sort(@{$changes{'delete'}})) {
                           $resulttext .= '<li>'.&mt('Load Balancing discontinued for: [_1]',$balancer).'</li>';
                           &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom);
                       }
                   }
                   if (ref($changes{'add'}) eq 'ARRAY') {
                       foreach my $balancer (sort(@{$changes{'add'}})) {   
                           $resulttext .= '<li>'.&mt('Load Balancing enabled for: [_1]',$balancer);
                       }
                   }
                   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')) {
                                               $balancetext =  $ruletitles{$rule};
                                           } 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>';     
                                       }
                                   }
                               }
                           }
                           &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom);
                       }
                   }
                   if ($resulttext ne '') {
                       $resulttext = &mt('Changes made:').'<ul>'.$resulttext.'</ul>';
                   } else {
                       $resulttext = $nochgmsg;
                   }
               } else {
                   $resulttext = $nochgmsg;
               }
           } else {
               $resulttext = '<span class="LC_error">'.
                             &mt('An error occurred: [_1]',$putresult).'</span>';
         }          }
     } else {      } else {
         $resulttext = &mt('No changes made to course categories');          $resulttext = $nochgmsg;
     }      }
     return $resulttext;      return $resulttext;
 }  }
Line 4402  sub recurse_cat_deletes { Line 8435  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;      return;
 }  }
   
 sub gather_categories {  sub get_active_dcs {
     my ($categories,$cats,$idx,$jsarray) = @_;      my ($dom) = @_;
     my %counters;      my %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc']);
     my $num = 0;      my %domcoords;
     foreach my $item (keys(%{$categories})) {      my $numdcs = 0;
         my ($cat,$container,$depth) = map { &unescape($_); } split(/:/,$item);      my $now = time;
         if ($container eq '' && $depth == 0) {      foreach my $server (keys(%dompersonnel)) {
             $cats->[$depth][$categories->{$item}] = $cat;          foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {
         } else {              my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user);
             $cats->[$depth]{$container}[$categories->{$item}] = $cat;              my ($end,$start) = split(':',$dompersonnel{$server}{$user});
         }              if (($end eq '') || ($end == 0) || ($end > $now)) {
         my ($escitem,$tail) = split(/:/,$item,2);                  if ($start <= $now) {
         if ($counters{$tail} eq '') {                      $domcoords{$uname.':'.$udom} = $dompersonnel{$server}{$user};
             $counters{$tail} = $num;                  }
             $num ++;              }
           }
       }
       return %domcoords;
   }
   
   sub active_dc_picker {
       my ($dom,$curr_dc) = @_;
       my %domcoords = &get_active_dcs($dom); 
       my @dcs = sort(keys(%domcoords));
       my $numdcs = scalar(@dcs); 
       my $datatable;
       my $numinrow = 2;
       if ($numdcs > 1) {
           $datatable = '<table>';
           for (my $i=0; $i<@dcs; $i++) {
               my $rem = $i%($numinrow);
               if ($rem == 0) {
                   if ($i > 0) {
                       $datatable .= '</tr>';
                   }
                   $datatable .= '<tr>';
               }
               my $check = ' ';
               if ($curr_dc eq '') {
                   if (!$i) { 
                       $check = ' checked="checked" ';
                   }
               } elsif ($dcs[$i] eq $curr_dc) {
                   $check = ' checked="checked" ';
               }
               if ($i == @dcs - 1) {
                   my $colsleft = $numinrow - $rem;
                   if ($colsleft > 1) {
                       $datatable .= '<td colspan="'.$colsleft.'">';
                   } else {
                       $datatable .= '<td>';
                   }
               } else {
                   $datatable .= '<td>';
               }
               my ($dcname,$dcdom) = split(':',$dcs[$i]);
               $datatable .= '<span class="LC_nobreak"><label>'.
                             '<input type="radio" name="autocreate_xmldc"'.
                             ' value="'.$dcs[$i].'"'.$check.'/>'.
                             &Apache::loncommon::plainname($dcname,$dcdom).
                             ' ('.$dcname.':'.$dcdom.')'.
                             '</label></span></td>';
           }
           $datatable .= '</tr></table>';
       } elsif (@dcs) {
           $datatable .= '<input type="hidden" name="autocreate_dc" value="'.
                         $dcs[0].'" />';
       }
       return ($numdcs,$datatable);
   }
   
   sub usersession_titles {
       return &Apache::lonlocal::texthash(
                  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',
                  spares => 'Servers offloaded to, when busy',
                  version => 'LON-CAPA version requirement',
                  excludedomain => 'Allow all, but exclude 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 (ref($idx) eq 'HASH') {          if ((insttypes[k] != '_LC_external') && 
             $idx->{$item} = $counters{$tail};              ((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);
                       
                   }
               }
         }          }
         if (ref($jsarray) eq 'ARRAY') {       }
             push(@{$jsarray->[$counters{$tail}]},$item);      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;      return;
 }  }
   
 sub extract_categories {  function checkOffloads(item,balnum,type) {
     my ($categories,$cats,$trails,$allitems,$idx,$jsarray) = @_;      var alltargets = new Array('$alltargets');
     if (ref($categories) eq 'HASH') {      var offloadtypes = new Array('primary','default');
         &gather_categories($categories,$cats,$idx,$jsarray);      if (item.checked) {
         if (ref($cats->[0]) eq 'ARRAY') {          var total = alltargets.length - 1;
             for (my $i=0; $i<@{$cats->[0]}; $i++) {          var other;
                 my $name = $cats->[0][$i];          if (type == offloadtypes[0]) {
                 my $item = &escape($name).'::0';              other = offloadtypes[1];
                 my $trailstr;          } else {
                 if ($name eq 'instcode') {              other = offloadtypes[0];
                     $trailstr = &mt('Official courses (with institutional codes)');          }
                 } else {          for (var i=0; i<total; i++) {
                     $trailstr = $name;              var server = document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).value;
                 }              if (server == item.value) {
                 if ($allitems->{$item} eq '') {                  if (document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).checked) {
                     push(@{$trails},$trailstr);                      document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).checked = false;
                     $allitems->{$item} = scalar(@{$trails})-1;                  }
                 }              }
                 my @parents = ($name);          }
                 if (ref($cats->[1]{$name}) eq 'ARRAY') {      }
                     for (my $j=0; $j<@{$cats->[1]{$name}}; $j++) {      return;
                         my $category = $cats->[1]{$name}[$j];  }
                         &recurse_categories($cats,2,$category,$trails,$allitems,\@parents);  
   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;      return;
 }  }
   
 sub recurse_categories {  function checkNewSpares(lonhost,type) {
     my ($cats,$depth,$category,$trails,$allitems,$parents) = @_;      var newSpare = document.getElementById('newspare_'+type+'_'+lonhost);
     my $shallower = $depth - 1;      var chosen =  newSpare.options[newSpare.selectedIndex].value;
     if (ref($cats->[$depth]{$category}) eq 'ARRAY') {      if (chosen != '') { 
         for (my $k=0; $k<@{$cats->[$depth]{$category}}; $k++) {          var othertype;
             my $name = $cats->[$depth]{$category}[$k];          var othernewSpare;
             my $item = &escape($category).':'.&escape($parents->[-1]).':'.$shallower;          if (type == 'primary') {
             my $trailstr = join(' -&gt; ',(@{$parents},$category));              othernewSpare = document.getElementById('newspare_default_'+lonhost);
             if ($allitems->{$item} eq '') {           }
                 push(@{$trails},$trailstr);          if (type == 'default') {
                 $allitems->{$item} = scalar(@{$trails})-1;              othernewSpare = document.getElementById('newspare_primary_'+lonhost);
             }          }
             my $deeper = $depth+1;          if (othernewSpare.options[othernewSpare.selectedIndex].value == chosen) {
             push(@{$parents},$category);              othernewSpare.selectedIndex = 0;
             &recurse_categories($cats,$deeper,$name,$trails,$allitems,$parents);          }
             pop(@{$parents});      }
         }      return;
     } else {  }
         my $item = &escape($category).':'.&escape($parents->[-1]).':'.$shallower;  
         my $trailstr = join(' -&gt; ',(@{$parents},$category));  // ]]>
         if ($allitems->{$item} eq '') {  </script>
             push(@{$trails},$trailstr);  
             $allitems->{$item} = scalar(@{$trails})-1;  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;      return;
 }  }
   
   // ]]>
   </script>
   
   END
   
   }
   
   sub captcha_phrases {
       return &Apache::lonlocal::texthash (
                    priv => 'Private key',
                    pub  => 'Public key',
                    original  => 'original (CAPTCHA)',
                    recaptcha => 'successor (ReCAPTCHA)',
                    notused   => 'unused',
       );
   }
   
 1;  1;

Removed from v.1.51  
changed lines
  Added in v.1.183


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