Diff for /loncom/interface/domainprefs.pm between versions 1.160.6.105 and 1.162

version 1.160.6.105, 2020/05/02 18:36:17 version 1.162, 2012/06/01 11:39:24
Line 19 Line 19
 #  #
 # You should have received a copy of the GNU General Public License  # You should have received a copy of the GNU General Public License
 # along with LON-CAPA; if not, write to the Free Software  # along with LON-CAPA; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA#
 #  
 # /home/httpd/html/adm/gpl.txt  # /home/httpd/html/adm/gpl.txt
 #  #
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
Line 46  described at http://www.lon-capa.org. Line 45  described at http://www.lon-capa.org.
 =head1 OVERVIEW  =head1 OVERVIEW
   
 Each institution using LON-CAPA will typically have a single domain designated   Each institution using LON-CAPA will typically have a single domain designated 
 for use by individuals affiliated with the institution.  Accordingly, each domain  for use by individuals affliated with the institution.  Accordingly, each domain
 may define a default set of logos and a color scheme which can be used to "brand"  may define a default set of logos and a color scheme which can be used to "brand"
 the LON-CAPA instance. In addition, an institution will typically have a language  the LON-CAPA instance. In addition, an institution will typically have a language
 and timezone which are used for the majority of courses.  and timezone which are used for the majority of courses.
Line 87  $dom,$settings,$rowtotal,$action. Line 86  $dom,$settings,$rowtotal,$action.
   
 $dom is the domain, $settings is a reference to a hash of current settings for  $dom is the domain, $settings is a reference to a hash of current settings for
 the current context, $rowtotal is a reference to the scalar used to record the   the current context, $rowtotal is a reference to the scalar used to record the 
 number of rows displayed on the page, and $action is the context (quotas,   number of rows displayed on the page, and $action is the context (either quotas 
 requestcourses or requestauthor).  or requestcourses).
   
 The print_quotas routine was orginally created to display/store information  The print_quotas routine was orginally created to display/store information
 about default quota sizes for portfolio spaces for the different types of   about default quota sizes for portfolio spaces for the different types of 
 institutional affiliation in the domain (e.g., Faculty, Staff, Student etc.),   institutional affiliation in the domain (e.g., Faculty, Staff, Student etc.), 
 but is now also used to manage availability of user tools:   but is now also used to manage availability of user tools: 
 i.e., blogs, aboutme page, and portfolios, and the course request tool,  i.e., blogs, aboutme page, and portfolios, and the course request tool,
 used by course owners to request creation of a course, and to display/store  used by course owners to request creation of a course.
 default quota sizes for Authoring Spaces.  
   
 Outputs: 1  Outputs: 1
   
Line 104  $datatable  - HTML containing form eleme Line 102  $datatable  - HTML containing form eleme
   
 In the case of course requests, radio buttons are displayed for each institutional  In the case of course requests, radio buttons are displayed for each institutional
 affiliate type (and also default, and _LC_adv) for each of the course types   affiliate type (and also default, and _LC_adv) for each of the course types 
 (official, unofficial, community, and textbook).  In each case the radio buttons   (official, unofficial and community).  In each case the radio buttons allow the 
 allow the selection of one of four values:  selection of one of four values:
   
 0, approval, validate, autolimit=N (where N is blank, or a positive integer).  0, approval, validate, autolimit=N (where N is blank, or a positive integer).
 which have the following effects:  which have the following effects:
Line 165  use Apache::lonhtmlcommon(); Line 163  use Apache::lonhtmlcommon();
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonmsg();  use Apache::lonmsg();
 use Apache::lonconfigsettings;  use Apache::lonconfigsettings;
 use Apache::lonuserutils();  
 use Apache::loncoursequeueadmin();  
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
 use LONCAPA::Enrollment;  use LONCAPA::Enrollment;
 use LONCAPA::lonauthcgi();  use LONCAPA::lonauthcgi();
Line 215  sub handler { Line 211  sub handler {
                 'directorysrch','usercreation','usermodification',                  'directorysrch','usercreation','usermodification',
                 'contacts','defaults','scantron','coursecategories',                  'contacts','defaults','scantron','coursecategories',
                 'serverstatuses','requestcourses','helpsettings',                  'serverstatuses','requestcourses','helpsettings',
                 'coursedefaults','usersessions','loadbalancing',                  'coursedefaults','usersessions','loadbalancing'],$dom);
                 'requestauthor','selfenrollment','inststatus','passwords'],$dom);      my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
     my @prefs_order = ('rolecolors','login','defaults','passwords','quotas','autoenroll',  
                        'autoupdate','autocreate','directorysrch','contacts',                         'autoupdate','autocreate','directorysrch','contacts',
                        'usercreation','selfcreation','usermodification','scantron',                         'usercreation','usermodification','scantron',
                        'requestcourses','requestauthor','coursecategories',                         'requestcourses','coursecategories','serverstatuses','helpsettings',
                        'serverstatuses','helpsettings','coursedefaults',                         'coursedefaults','usersessions');
                        'selfenrollment','usersessions');      if (keys(%servers) > 1) {
     my %existing;  
     if (ref($domconfig{'loadbalancing'}) eq 'HASH') {  
         %existing = %{$domconfig{'loadbalancing'}};  
     }  
     if ((keys(%servers) > 1) || (keys(%existing) > 0)) {  
         push(@prefs_order,'loadbalancing');          push(@prefs_order,'loadbalancing');
     }      }
     my %prefs = (      my %prefs = (
Line 242  sub handler { Line 232  sub handler {
                                  col2 => '',},                                   col2 => '',},
                                 {col1 => 'Administrator Settings',                                  {col1 => 'Administrator Settings',
                                  col2 => '',}],                                   col2 => '',}],
                       print => \&print_rolecolors,  
                       modify => \&modify_rolecolors,  
                     },                      },
         'login' =>          'login' =>
                     { text => 'Log-in page options',                      { text => 'Log-in page options',
                       help => 'Domain_Configuration_Login_Page',                        help => 'Domain_Configuration_Login_Page',
                       header => [{col1 => 'Log-in Page Items',                        header => [{col1 => 'Item',
                                   col2 => '',},                                    col2 => '',}],
                                  {col1 => 'Log-in Help',  
                                   col2 => 'Value'},  
                                  {col1 => 'Custom HTML in document head',  
                                   col2 => 'Value'}],  
                       print => \&print_login,  
                       modify => \&modify_login,  
                     },                      },
   
         'defaults' =>           'defaults' => 
                     { text => 'Default authentication/language/timezone/portal/types',                      { text => 'Default authentication/language/timezone/portal',
                       help => 'Domain_Configuration_LangTZAuth',                        help => 'Domain_Configuration_LangTZAuth',
                       header => [{col1 => 'Setting',                        header => [{col1 => 'Setting',
                                   col2 => 'Value'},                                    col2 => 'Value'}],
                                  {col1 => 'Institutional user types',  
                                   col2 => 'Name displayed'}],  
                       print => \&print_defaults,  
                       modify => \&modify_defaults,  
                     },  
         'passwords' =>  
                     { text => 'Passwords (Internal authentication)',  
                       help => 'Domain_Configuration_Passwords',  
                       header => [{col1 => 'Resetting Forgotten Password',  
                                   col2 => 'Settings'},  
                                  {col1 => 'Encryption of Stored Passwords (Internal Auth)',  
                                   col2 => 'Settings'},  
                                  {col1 => 'Rules for LON-CAPA Passwords',  
                                   col2 => 'Settings'},  
                                  {col1 => 'Course Owner Changing Student Passwords',  
                                   col2 => 'Settings'}],  
                       print => \&print_passwords,  
                       modify => \&modify_passwords,  
                     },                      },
         'quotas' =>           'quotas' => 
                     { text => 'Blogs, personal web pages, webDAV/quotas, portfolios',                      { text => 'Blogs, personal web pages, webDAV, portfolios',
                       help => 'Domain_Configuration_Quotas',                        help => 'Domain_Configuration_Quotas',
                       header => [{col1 => 'User affiliation',                        header => [{col1 => 'User affiliation',
                                   col2 => 'Available tools',                                    col2 => 'Available tools',
                                   col3 => 'Quotas, MB; (Authoring requires role)',}],                                    col3 => 'Portfolio quota',}],
                       print => \&print_quotas,  
                       modify => \&modify_quotas,  
                     },                      },
         'autoenroll' =>          'autoenroll' =>
                    { text => 'Auto-enrollment settings',                     { text => 'Auto-enrollment settings',
                      help => 'Domain_Configuration_Auto_Enrollment',                       help => 'Domain_Configuration_Auto_Enrollment',
                      header => [{col1 => 'Configuration setting',                       header => [{col1 => 'Configuration setting',
                                  col2 => 'Value(s)'}],                                   col2 => 'Value(s)'}],
                      print => \&print_autoenroll,  
                      modify => \&modify_autoenroll,  
                    },                     },
         'autoupdate' =>           'autoupdate' => 
                    { text => 'Auto-update settings',                     { text => 'Auto-update settings',
Line 306  sub handler { Line 267  sub handler {
                                 {col1 => 'Setting',                                  {col1 => 'Setting',
                                  col2 => 'Affiliation'},                                   col2 => 'Affiliation'},
                                 {col1 => 'User population',                                  {col1 => 'User population',
                                  col2 => 'Updatable user data'}],                                   col2 => 'Updateable user data'}],
                      print => \&print_autoupdate,  
                      modify => \&modify_autoupdate,  
                   },                    },
         'autocreate' =>           'autocreate' => 
                   { text => 'Auto-course creation settings',                    { text => 'Auto-course creation settings',
                      help => 'Domain_Configuration_Auto_Creation',                       help => 'Domain_Configuration_Auto_Creation',
                      header => [{col1 => 'Configuration Setting',                       header => [{col1 => 'Configuration Setting',
                                  col2 => 'Value',}],                                   col2 => 'Value',}],
                      print => \&print_autocreate,  
                      modify => \&modify_autocreate,  
                   },                    },
         'directorysrch' =>           'directorysrch' => 
                   { text => 'Directory searches',                    { text => 'Institutional directory searches',
                     help => 'Domain_Configuration_InstDirectory_Search',                      help => 'Domain_Configuration_InstDirectory_Search',
                     header => [{col1 => 'Institutional Directory Setting',                      header => [{col1 => 'Setting',
                                 col2 => 'Value',},  
                                {col1 => 'LON-CAPA Directory Setting',  
                                 col2 => 'Value',}],                                  col2 => 'Value',}],
                     print => \&print_directorysrch,  
                     modify => \&modify_directorysrch,  
                   },                    },
         'contacts' =>          'contacts' =>
                   { text => 'E-mail addresses and helpform',                    { text => 'Contact Information',
                     help => 'Domain_Configuration_Contact_Info',                      help => 'Domain_Configuration_Contact_Info',
                     header => [{col1 => 'Default e-mail addresses',                      header => [{col1 => 'Setting',
                                 col2 => 'Value',},                                  col2 => 'Value',}],
                                {col1 => 'Recipient(s) for notifications',  
                                 col2 => 'Value',},  
                                {col1 => 'Ask helpdesk form settings',  
                                 col2 => 'Value',},],  
                     print => \&print_contacts,  
                     modify => \&modify_contacts,  
                   },                    },
   
         'usercreation' =>           'usercreation' => 
                   { text => 'User creation',                    { text => 'User creation',
                     help => 'Domain_Configuration_User_Creation',                      help => 'Domain_Configuration_User_Creation',
Line 349  sub handler { Line 297  sub handler {
                                 col2 => 'Usernames which may be created',},                                  col2 => 'Usernames which may be created',},
                                {col1 => 'Context',                                 {col1 => 'Context',
                                 col2 => 'Assignable authentication types'}],                                  col2 => 'Assignable authentication types'}],
                     print => \&print_usercreation,  
                     modify => \&modify_usercreation,  
                   },  
         'selfcreation' =>   
                   { text => 'Users self-creating accounts',  
                     help => 'Domain_Configuration_Self_Creation',   
                     header => [{col1 => 'Self-creation with institutional username',  
                                 col2 => 'Enabled?'},  
                                {col1 => 'Institutional user type (login/SSO self-creation)',  
                                 col2 => 'Information user can enter'},  
                                {col1 => 'Self-creation with e-mail verification',  
                                 col2 => 'Settings'}],  
                     print => \&print_selfcreation,  
                     modify => \&modify_selfcreation,  
                   },                    },
         'usermodification' =>          'usermodification' =>
                   { text => 'User modification',                    { text => 'User modification',
                     help => 'Domain_Configuration_User_Modification',                      help => 'Domain_Configuration_User_Modification',
                     header => [{col1 => 'Target user has role',                      header => [{col1 => 'Target user has role',
                                 col2 => 'User information updatable in author context'},                                  col2 => 'User information updateable in author context'},
                                {col1 => 'Target user has role',                                 {col1 => 'Target user has role',
                                 col2 => 'User information updatable in course context'}],                                  col2 => 'User information updateable in course context'},
                     print => \&print_usermodification,                                 {col1 => "Status of user",
                     modify => \&modify_usermodification,                                  col2 => 'Information settable when self-creating account (if directory data blank)'}],
                   },                    },
         'scantron' =>          'scantron' =>
                   { text => 'Bubblesheet format',                    { text => 'Bubblesheet format file',
                     help => 'Domain_Configuration_Scantron_Format',                      help => 'Domain_Configuration_Scantron_Format',
                     header => [ {col1 => 'Bubblesheet format file',                      header => [ {col1 => 'Item',
                                  col2 => ''},                                   col2 => '',
                                 {col1 => 'Bubblesheet data upload formats',                                }],
                                  col2 => 'Settings'}],  
                     print => \&print_scantron,  
                     modify => \&modify_scantron,  
                   },                    },
         'requestcourses' =>           'requestcourses' => 
                  {text => 'Request creation of courses',                   {text => 'Request creation of courses',
Line 390  sub handler { Line 321  sub handler {
                   header => [{col1 => 'User affiliation',                    header => [{col1 => 'User affiliation',
                               col2 => 'Availability/Processing of requests',},                                col2 => 'Availability/Processing of requests',},
                              {col1 => 'Setting',                               {col1 => 'Setting',
                               col2 => 'Value'},  
                              {col1 => 'Available textbooks',  
                               col2 => ''},  
                              {col1 => 'Available templates',  
                               col2 => ''},  
                              {col1 => 'Validation (not official courses)',  
                               col2 => 'Value'},],  
                   print => \&print_quotas,  
                   modify => \&modify_quotas,  
                  },  
         'requestauthor' =>  
                  {text => 'Request Authoring Space',  
                   help => 'Domain_Configuration_Request_Author',  
                   header => [{col1 => 'User affiliation',  
                               col2 => 'Availability/Processing of requests',},  
                              {col1 => 'Setting',  
                               col2 => 'Value'}],                                col2 => 'Value'}],
                   print => \&print_quotas,  
                   modify => \&modify_quotas,  
                  },                   },
         'coursecategories' =>          'coursecategories' =>
                   { text => 'Cataloging of courses/communities',                    { text => 'Cataloging of courses/communities',
                     help => 'Domain_Configuration_Cataloging_Courses',                      help => 'Domain_Configuration_Cataloging_Courses',
                     header => [{col1 => 'Catalog type/availability',                      header => [{col1 => 'Category settings',
                                 col2 => '',},  
                                {col1 => 'Category settings for standard catalog',  
                                 col2 => '',},                                  col2 => '',},
                                {col1 => 'Categories',                                 {col1 => 'Categories',
                                 col2 => '',                                  col2 => '',
                                }],                                 }],
                     print => \&print_coursecategories,  
                     modify => \&modify_coursecategories,  
                   },                    },
         'serverstatuses' =>          'serverstatuses' =>
                  {text   => 'Access to server status pages',                   {text   => 'Access to server status pages',
Line 430  sub handler { Line 339  sub handler {
                               col2 => 'Other named users',                                col2 => 'Other named users',
                               col3 => 'Specific IPs',                                col3 => 'Specific IPs',
                             }],                              }],
                   print => \&print_serverstatuses,  
                   modify => \&modify_serverstatuses,  
                  },                   },
         'helpsettings' =>          'helpsettings' =>
                  {text   => 'Support settings',                   {text   => 'Help page settings',
                   help   => 'Domain_Configuration_Help_Settings',                    help   => 'Domain_Configuration_Help_Settings',
                   header => [{col1 => 'Help Page Settings (logged-in users)',                    header => [{col1 => 'Authenticated Help Settings',
                               col2 => 'Value'},                                col2 => ''},
                              {col1 => 'Helpdesk Roles',                               {col1 => 'Unauthenticated Help Settings',
                               col2 => 'Settings'},],                                col2 => ''}],
                   print  => \&print_helpsettings,  
                   modify => \&modify_helpsettings,  
                  },                   },
         'coursedefaults' =>           'coursedefaults' => 
                  {text => 'Course/Community defaults',                   {text => 'Course/Community defaults',
Line 450  sub handler { Line 355  sub handler {
                               col2 => 'Value',},                                col2 => 'Value',},
                              {col1 => 'Defaults which can be overridden for each course by a DC',                               {col1 => 'Defaults which can be overridden for each course by a DC',
                               col2 => 'Value',},],                                col2 => 'Value',},],
                   print => \&print_coursedefaults,  
                   modify => \&modify_coursedefaults,  
                  },                   },
         'selfenrollment' =>           'privacy' => 
                  {text   => 'Self-enrollment in Course/Community',                   {text   => 'User Privacy',
                   help   => 'Domain_Configuration_Selfenrollment',                    help   => 'Domain_Configuration_User_Privacy',
                   header => [{col1 => 'Configuration Rights',                    header => [{col1 => 'Setting',
                               col2 => 'Configured by Course Personnel or Domain Coordinator?'},                                col2 => 'Value',}],
                              {col1 => 'Defaults',  
                               col2 => 'Value'},  
                              {col1 => 'Self-enrollment validation (optional)',  
                               col2 => 'Value'},],  
                   print => \&print_selfenrollment,  
                   modify => \&modify_selfenrollment,  
                  },                   },
         'usersessions' =>          'usersessions' =>
                  {text  => 'User session hosting/offloading',                   {text  => 'User session hosting/offloading',
Line 474  sub handler { Line 371  sub handler {
                               col2 => 'Rules'},                                col2 => 'Rules'},
                              {col1 => "Hosting domain's own users elsewhere",                               {col1 => "Hosting domain's own users elsewhere",
                               col2 => 'Rules'}],                                col2 => 'Rules'}],
                   print => \&print_usersessions,  
                   modify => \&modify_usersessions,  
                  },                   },
         'loadbalancing' =>           'loadbalancing' =>
                  {text  => 'Dedicated Load Balancer(s)',                   {text  => 'Dedicated Load Balancer',
                   help  => 'Domain_Configuration_Load_Balancing',                    help  => 'Domain_Configuration_Load_Balancing',
                   header => [{col1 => 'Balancers',                    header => [{col1 => 'Server',
                               col2 => 'Default destinations',                                col2 => 'Default destinations',
                               col3 => 'User affiliation',                                col3 => 'User affliation',
                               col4 => 'Overrides'},                                col4 => 'Overrides'},
                             ],                              ],
                   print => \&print_loadbalancing,  
                   modify => \&modify_loadbalancing,  
                  },                   },
     );      );
     if (keys(%servers) > 1) {      if (keys(%servers) > 1) {
Line 495  sub handler { Line 388  sub handler {
                             header => [{col1 => 'Log-in Service',                              header => [{col1 => 'Log-in Service',
                                         col2 => 'Server Setting',},                                          col2 => 'Server Setting',},
                                        {col1 => 'Log-in Page Items',                                         {col1 => 'Log-in Page Items',
                                         col2 => ''},                                          col2 => ''}],
                                        {col1 => 'Log-in Help',  
                                         col2 => 'Value'},  
                                        {col1 => 'Custom HTML in document head',  
                                         col2 => 'Value'}],  
                             print => \&print_login,  
                             modify => \&modify_login,  
                            };                             };
     }      }
   
     my @roles = ('student','coordinator','author','admin');      my @roles = ('student','coordinator','author','admin');
     my @actions = &Apache::loncommon::get_env_multiple('form.actions');      my @actions = &Apache::loncommon::get_env_multiple('form.actions');
     &Apache::lonhtmlcommon::add_breadcrumb      &Apache::lonhtmlcommon::add_breadcrumb
     ({href=>"javascript:changePage(document.$phase,'pickactions')",      ({href=>"javascript:changePage(document.$phase,'pickactions')",
       text=>"Settings to display/modify"});        text=>"Settings to display/modify"});
     my $confname = $dom.'-domainconfig';      my $confname = $dom.'-domainconfig';
   
     if ($phase eq 'process') {      if ($phase eq 'process') {
         my $result = &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,          &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,\@roles);
                                                               \%prefs,\%domconfig,$confname,\@roles);  
         if ((ref($result) eq 'HASH') && (keys(%{$result}))) {  
             $r->rflush();  
             &devalidate_remote_domconfs($dom,$result);  
         }  
     } elsif ($phase eq 'display') {      } elsif ($phase eq 'display') {
         my $js = &recaptcha_js().          my $js;
                  &toggle_display_js();          if (keys(%servers) > 1) {
         if ((keys(%servers) > 1) || (keys(%existing) > 0)) {  
             my ($othertitle,$usertypes,$types) =              my ($othertitle,$usertypes,$types) =
                 &Apache::loncommon::sorted_inst_types($dom);                  &Apache::loncommon::sorted_inst_types($dom);
             $js .= &lonbalance_targets_js($dom,$types,\%servers,              $js = &lonbalance_targets_js($dom,$types,\%servers).
                                           $domconfig{'loadbalancing'}).                    &new_spares_js().
                    &new_spares_js().                    &common_domprefs_js().
                    &common_domprefs_js().                    &Apache::loncommon::javascript_array_indexof();
                    &Apache::loncommon::javascript_array_indexof();  
         }  
         if (grep(/^requestcourses$/,@actions)) {  
             my $javascript_validations;  
             my $coursebrowserjs=&Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'});   
             $js .= <<END;  
 <script type="text/javascript">  
 $javascript_validations  
 </script>  
 $coursebrowserjs  
 END  
         }  
         if (grep(/^selfcreation$/,@actions)) {  
             $js .= &selfcreate_javascript();  
         }  
         if (grep(/^contacts$/,@actions)) {  
             $js .= &contacts_javascript();  
         }  
         if (grep(/^scantron$/,@actions)) {  
             $js .= &scantron_javascript();  
         }          }
         &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);          &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);
     } else {      } else {
 # check if domconfig user exists for the domain.  
         my $servadm = $r->dir_config('lonAdmEMail');  
         my ($configuserok,$author_ok,$switchserver) =  
             &config_check($dom,$confname,$servadm);  
         unless ($configuserok eq 'ok') {  
             &Apache::lonconfigsettings::print_header($r,$phase,$context);  
             $r->print(&mt('The domain configuration user "[_1]" has yet to be created.',  
                           $confname).  
                       '<br />'  
             );  
             if ($switchserver) {  
                 $r->print(&mt('Ordinarily, that domain configuration user is created when the ./UPDATE script is run to install LON-CAPA for the first time.').  
                           '<br />'.  
                           &mt('However, that does not apply when new domains are added to a multi-domain server, and ./UPDATE has not been run recently.').  
                           '<br />'.  
                           &mt('The "[_1]" user can be created automatically when a Domain Coordinator visits the web-based "Set domain configuration" screen, in a session hosted on the primary library server.',$confname).  
                           '<br />'.  
                           &mt('To do that now, use the following link: [_1]',$switchserver)  
                 );  
             } else {  
                 $r->print(&mt('To create that user from the command line run the ./UPDATE script found in the top level directory of the extracted LON-CAPA tarball.').  
                           '<br />'.  
                           &mt('Once that is done, you will be able to use the web-based "Set domain configuration" to configure the domain')  
                 );  
             }  
             $r->print(&Apache::loncommon::end_page());  
             return OK;  
         }  
         if (keys(%domconfig) == 0) {          if (keys(%domconfig) == 0) {
             my $primarylibserv = &Apache::lonnet::domain($dom,'primary');              my $primarylibserv = &Apache::lonnet::domain($dom,'primary');
             my @ids=&Apache::lonnet::current_machine_ids();              my @ids=&Apache::lonnet::current_machine_ids();
Line 619  END Line 450  END
 }  }
   
 sub process_changes {  sub process_changes {
     my ($r,$dom,$confname,$action,$roles,$values,$lastactref) = @_;      my ($r,$dom,$confname,$action,$roles,$values) = @_;
     my %domconfig;      my %domconfig;
     if (ref($values) eq 'HASH') {      if (ref($values) eq 'HASH') {
         %domconfig = %{$values};          %domconfig = %{$values};
     }      }
     my $output;      my $output;
     if ($action eq 'login') {      if ($action eq 'login') {
         $output = &modify_login($r,$dom,$confname,$lastactref,%domconfig);          $output = &modify_login($r,$dom,$confname,%domconfig);
     } elsif ($action eq 'rolecolors') {      } elsif ($action eq 'rolecolors') {
         $output = &modify_rolecolors($r,$dom,$confname,$roles,          $output = &modify_rolecolors($r,$dom,$confname,$roles,
                                      $lastactref,%domconfig);                                       %domconfig);
     } elsif ($action eq 'quotas') {      } elsif ($action eq 'quotas') {
         $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);          $output = &modify_quotas($dom,$action,%domconfig);
     } elsif ($action eq 'autoenroll') {      } elsif ($action eq 'autoenroll') {
         $output = &modify_autoenroll($dom,$lastactref,%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') {      } elsif ($action eq 'autocreate') {
         $output = &modify_autocreate($dom,%domconfig);          $output = &modify_autocreate($dom,%domconfig);
     } elsif ($action eq 'directorysrch') {      } elsif ($action eq 'directorysrch') {
         $output = &modify_directorysrch($dom,$lastactref,%domconfig);          $output = &modify_directorysrch($dom,%domconfig);
     } elsif ($action eq 'usercreation') {      } elsif ($action eq 'usercreation') {
         $output = &modify_usercreation($dom,%domconfig);          $output = &modify_usercreation($dom,%domconfig);
     } elsif ($action eq 'selfcreation') {  
         $output = &modify_selfcreation($dom,$lastactref,%domconfig);  
     } elsif ($action eq 'usermodification') {      } elsif ($action eq 'usermodification') {
         $output = &modify_usermodification($dom,%domconfig);          $output = &modify_usermodification($dom,%domconfig);
     } elsif ($action eq 'contacts') {      } elsif ($action eq 'contacts') {
         $output = &modify_contacts($dom,$lastactref,%domconfig);          $output = &modify_contacts($dom,%domconfig);
     } elsif ($action eq 'defaults') {      } elsif ($action eq 'defaults') {
         $output = &modify_defaults($dom,$lastactref,%domconfig);          $output = &modify_defaults($dom,$r);
     } elsif ($action eq 'scantron') {      } elsif ($action eq 'scantron') {
         $output = &modify_scantron($r,$dom,$confname,$lastactref,%domconfig);          $output = &modify_scantron($r,$dom,$confname,%domconfig);
     } elsif ($action eq 'coursecategories') {      } elsif ($action eq 'coursecategories') {
         $output = &modify_coursecategories($dom,$lastactref,%domconfig);          $output = &modify_coursecategories($dom,%domconfig);
     } elsif ($action eq 'serverstatuses') {      } elsif ($action eq 'serverstatuses') {
         $output = &modify_serverstatuses($dom,%domconfig);          $output = &modify_serverstatuses($dom,%domconfig);
     } elsif ($action eq 'requestcourses') {      } elsif ($action eq 'requestcourses') {
         $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);          $output = &modify_quotas($dom,$action,%domconfig);
     } elsif ($action eq 'requestauthor') {  
         $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);  
     } elsif ($action eq 'helpsettings') {      } elsif ($action eq 'helpsettings') {
         $output = &modify_helpsettings($r,$dom,$confname,$lastactref,%domconfig);          $output = &modify_helpsettings($r,$dom,$confname,%domconfig);
     } elsif ($action eq 'coursedefaults') {      } elsif ($action eq 'coursedefaults') {
         $output = &modify_coursedefaults($dom,$lastactref,%domconfig);          $output = &modify_coursedefaults($dom,%domconfig);
     } elsif ($action eq 'selfenrollment') {  
         $output = &modify_selfenrollment($dom,$lastactref,%domconfig)  
     } elsif ($action eq 'usersessions') {      } elsif ($action eq 'usersessions') {
         $output = &modify_usersessions($dom,$lastactref,%domconfig);          $output = &modify_usersessions($dom,%domconfig);
     } elsif ($action eq 'loadbalancing') {      } elsif ($action eq 'loadbalancing') {
         $output = &modify_loadbalancing($dom,%domconfig);          $output = &modify_loadbalancing($dom,%domconfig);
     } elsif ($action eq 'passwords') {  
         $output = &modify_passwords($r,$dom,$confname,$lastactref,%domconfig);  
     }      }
     return $output;      return $output;
 }  }
Line 682  sub print_config_box { Line 505  sub print_config_box {
     my $output;      my $output;
     if ($action eq 'coursecategories') {      if ($action eq 'coursecategories') {
         $output = &coursecategories_javascript($settings);          $output = &coursecategories_javascript($settings);
     } elsif ($action eq 'defaults') {  
         $output = &defaults_javascript($settings);   
     } elsif ($action eq 'passwords') {  
         $output = &passwords_javascript();  
     } elsif ($action eq 'helpsettings') {  
         my (%privs,%levelscurrent);  
         my %full=();  
         my %levels=(  
                      course => {},  
                      domain => {},  
                      system => {},  
                    );  
         my $context = 'domain';  
         my $crstype = 'Course';  
         my $formname = 'display';  
         &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);  
         my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);  
         $output =  
             &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full,  
                                                       \@templateroles);  
     }      }
     $output .=      $output .= 
          '<table class="LC_nested_outer">           '<table class="LC_nested_outer">
           <tr>            <tr>
            <th align="left" valign="middle"><span class="LC_nobreak">'.             <th align="left" valign="middle"><span class="LC_nobreak">'.
Line 718  sub print_config_box { Line 521  sub print_config_box {
     if ($numheaders > 1) {      if ($numheaders > 1) {
         my $colspan = '';          my $colspan = '';
         my $rightcolspan = '';          my $rightcolspan = '';
         my $leftnobr = '';            if (($action eq 'rolecolors') || ($action eq 'coursecategories') || ($action eq 'helpsettings')) {
         if (($action eq 'rolecolors') || ($action eq 'defaults') ||  
             ($action eq 'directorysrch') ||  
             (($action eq 'login') && ($numheaders < 4))) {  
             $colspan = ' colspan="2"';              $colspan = ' colspan="2"';
         }          }
         if ($action eq 'usersessions') {          if ($action eq 'usersessions') {
             $rightcolspan = ' colspan="3"';               $rightcolspan = ' colspan="3"'; 
         }          }
         if ($action eq 'passwords') {  
             $leftnobr = ' LC_nobreak';  
         }  
         $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'.$leftnobr.'"'.$colspan.'>'.&mt($item->{'header'}->[0]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
               <td class="LC_right_item"'.$rightcolspan.'>'.&mt($item->{'header'}->[0]->{'col2'}).'</td>                <td class="LC_right_item"'.$rightcolspan.'>'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
              </tr>';               </tr>';
         $rowtotal ++;          $rowtotal ++;
         if (($action eq 'autoupdate') || ($action eq 'usercreation') || ($action eq 'selfcreation') ||          if ($action eq 'autoupdate') {
             ($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') ||              $output .= &print_autoupdate('top',$dom,$settings,\$rowtotal);
             ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'directorysrch') ||          } elsif ($action eq 'usercreation') {
             ($action eq 'helpsettings') || ($action eq 'contacts')) {              $output .= &print_usercreation('top',$dom,$settings,\$rowtotal);
             $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);          } elsif ($action eq 'usermodification') {
         } elsif ($action eq 'passwords') {              $output .= &print_usermodification('top',$dom,$settings,\$rowtotal);
             $output .= $item->{'print'}->('top',$dom,$confname,$settings,\$rowtotal);  
         } elsif ($action eq 'coursecategories') {          } elsif ($action eq 'coursecategories') {
             $output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal);              $output .= &print_coursecategories('top',$dom,$item,$settings,\$rowtotal);
         } elsif ($action eq 'scantron') {  
             $output .= $item->{'print'}->($r,'top',$dom,$confname,$settings,\$rowtotal);  
         } elsif ($action eq 'login') {          } elsif ($action eq 'login') {
             if ($numheaders == 4) {              $output .= &print_login('top',$dom,$confname,$phase,$settings,\$rowtotal);
                 $colspan = ' colspan="2"';              $colspan = ' colspan="2"';
                 $output .= &print_login('service',$dom,$confname,$phase,$settings,\$rowtotal);          } elsif ($action eq 'requestcourses') {
             } else {  
                 $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal);  
             }  
         } elsif (($action eq 'requestcourses') || ($action eq 'requestauthor')) {  
             $output .= &print_quotas($dom,$settings,\$rowtotal,$action);              $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
           } elsif ($action eq 'helpsettings') {
               $output .= &print_helpsettings('top',$dom,$confname,$settings,\$rowtotal);
           } elsif ($action eq 'usersessions') {
               $output .= &print_usersessions('top',$dom,$settings,\$rowtotal); 
         } elsif ($action eq 'rolecolors') {          } elsif ($action eq 'rolecolors') {
             $output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal);              $output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal);
           } elsif ($action eq 'coursedefaults') {
               $output .= &print_coursedefaults('top',$dom,$settings,\$rowtotal);
         }          }
         $output .= '          $output .= '
            </table>             </table>
Line 770  sub print_config_box { Line 566  sub print_config_box {
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col1'}).'</td>';
           $output .= '
               <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col2'}).'</td>                <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col2'}).'</td>
              </tr>';               </tr>';
             $rowtotal ++;              $rowtotal ++;
         if (($action eq 'autoupdate') || ($action eq 'usercreation') ||          if ($action eq 'autoupdate') {
             ($action eq 'selfcreation') || ($action eq 'selfenrollment') ||              $output .= &print_autoupdate('middle',$dom,$settings,\$rowtotal).'
             ($action eq 'usersessions') || ($action eq 'coursecategories') ||  
             ($action eq 'contacts') || ($action eq 'passwords')) {  
             if ($action eq 'coursecategories') {  
                 $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);  
                 $colspan = ' colspan="2"';  
             } elsif ($action eq 'passwords') {  
                 $output .= $item->{'print'}->('middle',$dom,$confname,$settings,\$rowtotal);  
             } else {  
                 $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);  
             }  
             $output .= '  
            </table>             </table>
           </td>            </td>
          </tr>           </tr>
Line 794  sub print_config_box { Line 580  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'.$leftnobr.'"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>                <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>      </tr>'.
              </tr>'."\n";              &print_autoupdate('bottom',$dom,$settings,\$rowtotal);
             if ($action eq 'coursecategories') {  
                 $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);  
             } elsif ($action eq 'passwords') {  
                 $output .= $item->{'print'}->('lower',$dom,$confname,$settings,\$rowtotal).'  
              </tr>  
             </table>  
            </td>  
           </tr>  
           <tr>  
            <td>  
             <table class="LC_nested">  
              <tr class="LC_info_row">  
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>  
               <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td></tr>'."\n".  
               $item->{'print'}->('bottom',$dom,$confname,$settings,\$rowtotal).'  
             </table>  
           </td>  
          </tr>  
          <tr>';  
             } else {  
                 $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);  
             }  
             $rowtotal ++;              $rowtotal ++;
         } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||          } elsif ($action eq 'usercreation') {
                  ($action eq 'defaults') || ($action eq 'directorysrch') ||              $output .= &print_usercreation('middle',$dom,$settings,\$rowtotal).'
                  ($action eq 'helpsettings')) {  
             $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);  
         } elsif ($action eq 'scantron') {  
             $output .= $item->{'print'}->($r,'bottom',$dom,$confname,$settings,\$rowtotal);  
         } elsif ($action eq 'login') {  
             if ($numheaders == 4) {  
                 $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'  
            </table>             </table>
           </td>            </td>
          </tr>           </tr>
Line 837  sub print_config_box { Line 594  sub print_config_box {
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td></tr>'.                <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>             </tr>'.
                        &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);              &print_usercreation('bottom',$dom,$settings,\$rowtotal);
                 $rowtotal ++;              $rowtotal ++;
             } else {          } elsif ($action eq 'usermodification') {
                 $output .= &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);              $output .= &print_usermodification('middle',$dom,$settings,\$rowtotal).'
             }  
             $output .= '  
            </table>             </table>
           </td>            </td>
          </tr>           </tr>
          <tr>           <tr>
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">';               <tr class="LC_info_row">
             if ($numheaders == 4) {  
                 $output .= '  
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>  
               <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td>  
              </tr>';  
             } else {  
                 $output .= '  
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td>                <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>      </tr>'.
              </tr>';                         &print_usermodification('bottom',$dom,$settings,\$rowtotal);
             }  
             $rowtotal ++;              $rowtotal ++;
             $output .= &print_login('headtag',$dom,$confname,$phase,$settings,\$rowtotal);          } elsif ($action eq 'coursecategories') {
               $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
           } elsif ($action eq 'login') {
               $output .= &print_login('bottom',$dom,$confname,$phase,$settings,\$rowtotal);
         } elsif ($action eq 'requestcourses') {          } elsif ($action eq 'requestcourses') {
             $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);              $output .= &print_courserequestmail($dom,$settings,\$rowtotal);
             $rowtotal ++;          } elsif ($action eq 'helpsettings') {
             $output .= &print_studentcode($settings,\$rowtotal).'              $output .= &print_helpsettings('bottom',$dom,$confname,$settings,\$rowtotal);
           } elsif ($action eq 'usersessions') {
               $output .= &print_usersessions('middle',$dom,$settings,\$rowtotal).'
            </table>             </table>
           </td>            </td>
          </tr>           </tr>
Line 876  sub print_config_box { Line 628  sub print_config_box {
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td> </tr>'.                <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>      </tr>'.
                        &textbookcourses_javascript($settings).                         &print_usersessions('bottom',$dom,$settings,\$rowtotal);
                        &print_textbookcourses($dom,'textbooks',$settings,\$rowtotal).'  
             </table>  
            </td>  
           </tr>  
          <tr>  
            <td>  
             <table class="LC_nested">  
              <tr class="LC_info_row">  
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>  
               <td class="LC_right_item">'.&mt($item->{'header'}->[3]->{'col2'}).'</td> </tr>'.  
                        &print_textbookcourses($dom,'templates',$settings,\$rowtotal).'  
             </table>  
            </td>  
           </tr>  
           <tr>  
            <td>  
             <table class="LC_nested">  
              <tr class="LC_info_row">  
               <td class="LC_left_item"'.$colspan.' valign="top">'.&mt($item->{'header'}->[4]->{'col1'}).'</td>  
               <td class="LC_right_item" valign="top">'.&mt($item->{'header'}->[4]->{'col2'}).'</td>  
              </tr>'.  
             &print_validation_rows('requestcourses',$dom,$settings,\$rowtotal);  
         } elsif ($action eq 'requestauthor') {  
             $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);  
             $rowtotal ++;              $rowtotal ++;
           } elsif ($action eq 'coursedefaults') {
               $output .= &print_coursedefaults('bottom',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'rolecolors') {          } elsif ($action eq 'rolecolors') {
             $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'              $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'
            </table>             </table>
Line 937  sub print_config_box { Line 667  sub print_config_box {
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">';               <tr class="LC_info_row">';
         if ($action eq 'login') {          if (($action eq 'login') || ($action eq 'directorysrch')) {
             $output .= '                $output .= '  
               <td class="LC_left_item" colspan="2">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';                <td class="LC_left_item" colspan="2">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
         } elsif ($action eq 'serverstatuses') {          } elsif ($action eq 'serverstatuses') {
Line 979  sub print_config_box { Line 709  sub print_config_box {
         }          }
         $output .= '</tr>';          $output .= '</tr>';
         $rowtotal ++;          $rowtotal ++;
         if ($action eq 'quotas') {          if ($action eq 'login') {
               $output .= &print_login('bottom',$dom,$confname,$phase,$settings,
                                       \$rowtotal);
           } elsif ($action eq 'quotas') {
             $output .= &print_quotas($dom,$settings,\$rowtotal,$action);              $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
         } elsif (($action eq 'autoenroll') || ($action eq 'autocreate') ||           } elsif ($action eq 'autoenroll') {
                  ($action eq 'serverstatuses') || ($action eq 'loadbalancing')) {              $output .= &print_autoenroll($dom,$settings,\$rowtotal);
             $output .= $item->{'print'}->($dom,$settings,\$rowtotal);          } elsif ($action eq 'autocreate') {
               $output .= &print_autocreate($dom,$settings,\$rowtotal);
           } elsif ($action eq 'directorysrch') {
               $output .= &print_directorysrch($dom,$settings,\$rowtotal);
           } elsif ($action eq 'contacts') {
               $output .= &print_contacts($dom,$settings,\$rowtotal);
           } elsif ($action eq 'defaults') {
               $output .= &print_defaults($dom,\$rowtotal);
           } elsif ($action eq 'scantron') {
               $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);
           } elsif ($action eq 'serverstatuses') {
               $output .= &print_serverstatuses($dom,$settings,\$rowtotal);
           } elsif ($action eq 'helpsettings') {
               $output .= &print_helpsettings('top',$dom,$confname,$settings,\$rowtotal);
           } elsif ($action eq 'loadbalancing') {
               $output .= &print_loadbalancing($dom,$settings,\$rowtotal);
         }          }
     }      }
     $output .= '      $output .= '
Line 995  sub print_config_box { Line 743  sub print_config_box {
 }  }
   
 sub print_login {  sub print_login {
     my ($caller,$dom,$confname,$phase,$settings,$rowtotal) = @_;      my ($position,$dom,$confname,$phase,$settings,$rowtotal) = @_;
     my ($css_class,$datatable);      my ($css_class,$datatable);
     my %choices = &login_choices();      my %choices = &login_choices();
   
     if ($caller eq 'service') {      if ($position eq 'top') {
         my %servers = &Apache::lonnet::internet_dom_servers($dom);          my %servers = &Apache::lonnet::internet_dom_servers($dom);
         my $choice = $choices{'disallowlogin'};          my $choice = $choices{'disallowlogin'};
         $css_class = ' class="LC_odd_row"';          $css_class = ' class="LC_odd_row"';
Line 1026  sub print_login { Line 774  sub print_login {
                           '<td><select name="'.$lonhost.'_server">'.                            '<td><select name="'.$lonhost.'_server">'.
                           '<option value=""'.$direct.'>'.$choices{'directlogin'}.                            '<option value=""'.$direct.'>'.$choices{'directlogin'}.
                           '</option>';                            '</option>';
             foreach my $hostid (sort(keys(%servers))) {              foreach my $hostid (keys(%servers)) {
                 next if ($servers{$hostid} eq $servers{$lonhost});                  next if ($servers{$hostid} eq $servers{$lonhost});
                 my $selected = '';                  my $selected = '';
                 if (ref($disallowed{$lonhost}) eq 'HASH') {                  if (ref($disallowed{$lonhost}) eq 'HASH') {
Line 1066  sub print_login { Line 814  sub print_login {
         }          }
         $datatable .= '</table></td></tr>';          $datatable .= '</table></td></tr>';
         return $datatable;          return $datatable;
     } elsif ($caller eq 'page') {      }
         my %defaultchecked = (   
                                'coursecatalog' => 'on',      my %defaultchecked = ( 
                                'helpdesk'      => 'on',                             'coursecatalog' => 'on',
                                'adminmail'     => 'off',                             'adminmail'     => 'off',
                                'newuser'       => 'off',                             'newuser'       => 'off',
                              );                           );
         my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');      my @toggles = ('coursecatalog','adminmail','newuser');
         my (%checkedon,%checkedoff);      my (%checkedon,%checkedoff);
       foreach my $item (@toggles) {
           if ($defaultchecked{$item} eq 'on') { 
               $checkedon{$item} = ' checked="checked" ';
               $checkedoff{$item} = ' ';
           } elsif ($defaultchecked{$item} eq 'off') {
               $checkedoff{$item} = ' checked="checked" ';
               $checkedon{$item} = ' ';
           }
       }
       my @images = ('img','logo','domlogo','login');
       my @logintext = ('textcol','bgcol');
       my @bgs = ('pgbg','mainbg','sidebg');
       my @links = ('link','alink','vlink');
       my %designhash = &Apache::loncommon::get_domainconf($dom);
       my %defaultdesign = %Apache::loncommon::defaultdesign;
       my (%is_custom,%designs);
       my %defaults = (
                      font => $defaultdesign{'login.font'},
                      );
       foreach my $item (@images) {
           $defaults{$item} = $defaultdesign{'login.'.$item};
           $defaults{'showlogo'}{$item} = 1;
       }
       foreach my $item (@bgs) {
           $defaults{'bgs'}{$item} = $defaultdesign{'login.'.$item};
       }
       foreach my $item (@logintext) {
           $defaults{'logintext'}{$item} = $defaultdesign{'login.'.$item};
       }
       foreach my $item (@links) {
           $defaults{'links'}{$item} = $defaultdesign{'login.'.$item};
       }
       if (ref($settings) eq 'HASH') {
         foreach my $item (@toggles) {          foreach my $item (@toggles) {
             if ($defaultchecked{$item} eq 'on') {               if ($settings->{$item} eq '1') {
                 $checkedon{$item} = ' checked="checked" ';                  $checkedon{$item} =  ' checked="checked" ';
                 $checkedoff{$item} = ' ';                  $checkedoff{$item} = ' ';
             } elsif ($defaultchecked{$item} eq 'off') {              } elsif ($settings->{$item} eq '0') {
                 $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) {
             $defaults{$item} = $defaultdesign{'login.'.$item};              if (defined($settings->{$item})) {
             $defaults{'showlogo'}{$item} = 1;                  $designs{$item} = $settings->{$item};
         }                  $is_custom{$item} = 1;
         foreach my $item (@bgs) {  
             $defaults{'bgs'}{$item} = $defaultdesign{'login.'.$item};  
         }  
         foreach my $item (@logintext) {  
             $defaults{'logintext'}{$item} = $defaultdesign{'login.'.$item};  
         }  
         foreach my $item (@links) {  
             $defaults{'links'}{$item} = $defaultdesign{'login.'.$item};  
         }  
         if (ref($settings) eq 'HASH') {  
             foreach my $item (@toggles) {  
                 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 (@images) {  
                 if (defined($settings->{$item})) {  
                     $designs{$item} = $settings->{$item};  
                     $is_custom{$item} = 1;  
                 }  
                 if (defined($settings->{'showlogo'}{$item})) {  
                     $designs{'showlogo'}{$item} = $settings->{'showlogo'}{$item};  
                 }  
             }  
             foreach my $item (@logintext) {  
                 if ($settings->{$item} ne '') {  
                     $designs{'logintext'}{$item} = $settings->{$item};  
                     $is_custom{$item} = 1;  
                 }  
             }  
             if ($settings->{'font'} ne '') {  
                 $designs{'font'} = $settings->{'font'};  
                 $is_custom{'font'} = 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 (defined($settings->{'showlogo'}{$item})) {
                 if ($designhash{$dom.'.login.'.$item} ne '') {                  $designs{'showlogo'}{$item} = $settings->{'showlogo'}{$item};
                     $designs{'bgs'}{$item} = $designhash{$dom.'.login.'.$item};  
                     $is_custom{$item} = 1;  
                 }  
             }              }
             foreach my $item (@links) {          }
                 if ($designhash{$dom.'.login.'.$item} ne '') {          foreach my $item (@logintext) {
                     $designs{'links'}{$item} = $designhash{$dom.'.login.'.$item};              if ($settings->{$item} ne '') {
                     $is_custom{$item} = 1;                  $designs{'logintext'}{$item} = $settings->{$item};
                 }                  $is_custom{$item} = 1;
             }              }
         }          }
         my %alt_text = &Apache::lonlocal::texthash  ( img => 'Log-in banner',          if ($settings->{'font'} ne '') {
                                                       logo => 'Institution Logo',              $designs{'font'} = $settings->{'font'};
                                                       domlogo => 'Domain Logo',              $is_custom{'font'} = 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);          foreach my $item (@bgs) {
         $datatable .= '</tr></table></td></tr>';              if ($settings->{$item} ne '') {
     } elsif ($caller eq 'help') {                  $designs{'bgs'}{$item} = $settings->{$item};
         my ($defaulturl,$defaulttype,%url,%type,%lt,%langchoices);                  $is_custom{$item} = 1;
         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)) {          foreach my $item (@links) {
             $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';              if ($settings->{$item} ne '') {
             $datatable .= '<tr'.$css_class.'>';                  $designs{'links'}{$item} = $settings->{$item};
             if ($url{$lang} eq '') {                  $is_custom{$item} = 1;
                 $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 ++;  
         }          }
         my @addlangs;      } else {
         foreach my $lang (sort(keys(%langchoices))) {          if ($designhash{$dom.'.login.font'} ne '') {
             next if ((grep(/^\Q$lang\E$/,@currlangs)) || ($lang eq 'x_chef'));              $designs{'font'} = $designhash{$dom.'.login.font'};
             push(@addlangs,$lang);              $is_custom{'font'} = 1;
         }  
         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);          foreach my $item (@images) {
     } elsif ($caller eq 'headtag') {              if ($designhash{$dom.'.login.'.$item} ne '') {
         my %domservers = &Apache::lonnet::get_servers($dom);                  $designs{$item} = $designhash{$dom.'.login.'.$item};
         my $choice = $choices{'headtag'};                  $is_custom{$item} = 1;
         $css_class = ' class="LC_odd_row"';  
         $datatable .= '<tr'.$css_class.'><td colspan="2">'.$choice.'</td>'.  
                       '<td align="left"><table><tr><th>'.$choices{'hostid'}.'</th>'.  
                       '<th>'.$choices{'current'}.'</th>'.  
                       '<th>'.$choices{'action'}.'</th>'.  
                       '<th>'.$choices{'exempt'}.'</th></tr>'."\n";  
         my (%currurls,%currexempt);  
         if (ref($settings) eq 'HASH') {  
             if (ref($settings->{'headtag'}) eq 'HASH') {  
                 foreach my $lonhost (keys(%{$settings->{'headtag'}})) {  
                     if (ref($settings->{'headtag'}{$lonhost}) eq 'HASH') {  
                         $currurls{$lonhost} = $settings->{'headtag'}{$lonhost}{'url'};  
                         $currexempt{$lonhost} = $settings->{'headtag'}{$lonhost}{'exempt'};  
                     }  
                 }  
             }              }
         }          }
         my %lt = &Apache::lonlocal::texthash(          foreach my $item (@bgs) {
                                                del  => 'Delete?',              if ($designhash{$dom.'.login.'.$item} ne '') {
                                                rep  => 'Replace:',                  $designs{'bgs'}{$item} = $designhash{$dom.'.login.'.$item};
                                                upl  => 'Upload:',                  $is_custom{$item} = 1;
                                                curr => 'View contents',  
                                                none => 'None',  
         );  
         my $switchserver = &check_switchserver($dom,$confname);  
         foreach my $lonhost (sort(keys(%domservers))) {  
             my $exempt = &check_exempt_addresses($currexempt{$lonhost});  
             $datatable .= '<tr><td>'.$domservers{$lonhost}.'</td>';  
             if ($currurls{$lonhost}) {  
                 $datatable .= '<td class="LC_right_item"><a href="'.  
                               "javascript:void(open('$currurls{$lonhost}?inhibitmenu=yes','Custom_HeadTag',  
                               'menubar=0,toolbar=1,scrollbars=1,width=600,height=500,resizable=yes'))".  
                               '">'.$lt{'curr'}.'</a></td>'.  
                               '<td><span class="LC_nobreak"><label>'.  
                               '<input type="checkbox" name="loginheadtag_del" value="'.$lonhost.'" />'.  
                               $lt{'del'}.'</label>&nbsp;'.$lt{'rep'}.'</span>';  
             } else {  
                 $datatable .= '<td class="LC_right_item">'.$lt{'none'}.'</td><td>'.$lt{'upl'};  
             }              }
             $datatable .='<br />';          }
             if ($switchserver) {          foreach my $item (@links) {
                 $datatable .= &mt('Upload to library server: [_1]',$switchserver);              if ($designhash{$dom.'.login.'.$item} ne '') {
             } else {                  $designs{'links'}{$item} = $designhash{$dom.'.login.'.$item};
                 $datatable .= '<input type="file" name="loginheadtag_'.$lonhost.'" />';                  $is_custom{$item} = 1;
             }              }
             $datatable .= '</td><td><input type="text" name="loginheadtagexempt_'.$lonhost.'" value="'.$exempt.'" /></td></tr>';  
         }          }
         $datatable .= '</table></td></tr>';  
     }      }
       my %alt_text = &Apache::lonlocal::texthash  ( img => 'Log-in banner',
                                                     logo => 'Institution Logo',
                                                     domlogo => 'Domain Logo',
                                                     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>';
     return $datatable;      return $datatable;
 }  }
   
Line 1340  sub login_choices { Line 947  sub login_choices {
         &Apache::lonlocal::texthash (          &Apache::lonlocal::texthash (
             coursecatalog => 'Display Course/Community Catalog link?',              coursecatalog => 'Display Course/Community Catalog link?',
             adminmail     => "Display Administrator's E-mail Address?",              adminmail     => "Display Administrator's E-mail Address?",
             helpdesk      => 'Display "Contact Helpdesk" link',  
             disallowlogin => "Login page requests redirected",              disallowlogin => "Login page requests redirected",
             hostid        => "Server",              hostid        => "Server",
             server        => "Redirect to:",              server        => "Redirect to:",
Line 1364  sub login_choices { Line 970  sub login_choices {
             link          => "Link",              link          => "Link",
             alink         => "Active link",              alink         => "Active link",
             vlink         => "Visited link",              vlink         => "Visited link",
             headtag       => "Custom markup",  
             action        => "Action",  
             current       => "Current",  
         );          );
     return %choices;      return %choices;
 }  }
Line 1381  sub print_rolecolors { Line 984  sub print_rolecolors {
     my %designhash = &Apache::loncommon::get_domainconf($dom);      my %designhash = &Apache::loncommon::get_domainconf($dom);
     my %defaultdesign = %Apache::loncommon::defaultdesign;      my %defaultdesign = %Apache::loncommon::defaultdesign;
     my (%is_custom,%designs);      my (%is_custom,%designs);
     my %defaults = &role_defaults($role,\@bgs,\@links,\@images);      my %defaults = (
                      img => $defaultdesign{$role.'.img'},
                      font => $defaultdesign{$role.'.font'},
      fontmenu => $defaultdesign{$role.'.fontmenu'},
                      );
       foreach my $item (@bgs) {
           $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item};
       }
       foreach my $item (@links) {
           $defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item};
       }
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{$role}) eq 'HASH') {          if (ref($settings->{$role}) eq 'HASH') {
             if ($settings->{$role}->{'img'} ne '') {              if ($settings->{$role}->{'img'} ne '') {
Line 1442  sub print_rolecolors { Line 1055  sub print_rolecolors {
     return $datatable;      return $datatable;
 }  }
   
 sub role_defaults {  
     my ($role,$bgs,$links,$images,$logintext) = @_;  
     my %defaults;  
     unless ((ref($bgs) eq 'ARRAY') && (ref($links) eq 'ARRAY') && (ref($images) eq 'ARRAY')) {  
         return %defaults;  
     }  
     my %defaultdesign = %Apache::loncommon::defaultdesign;  
     if ($role eq 'login') {  
         %defaults = (  
                        font => $defaultdesign{$role.'.font'},  
                     );  
         if (ref($logintext) eq 'ARRAY') {  
             foreach my $item (@{$logintext}) {  
                 $defaults{'logintext'}{$item} = $defaultdesign{$role.'.'.$item};  
             }  
         }  
         foreach my $item (@{$images}) {  
             $defaults{'showlogo'}{$item} = 1;  
         }  
     } else {  
         %defaults = (  
                        img => $defaultdesign{$role.'.img'},  
                        font => $defaultdesign{$role.'.font'},  
                        fontmenu => $defaultdesign{$role.'.fontmenu'},  
                     );  
     }  
     foreach my $item (@{$bgs}) {  
         $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item};  
     }  
     foreach my $item (@{$links}) {  
         $defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item};  
     }  
     foreach my $item (@{$images}) {  
         $defaults{$item} = $defaultdesign{$role.'.'.$item};  
     }  
     return %defaults;  
 }  
   
 sub display_color_options {  sub display_color_options {
     my ($dom,$confname,$phase,$role,$itemcount,$choices,$is_custom,$defaults,$designs,      my ($dom,$confname,$phase,$role,$itemcount,$choices,$is_custom,$defaults,$designs,
         $images,$bgs,$links,$alt_text,$rowtotal,$logintext) = @_;          $images,$bgs,$links,$alt_text,$rowtotal,$logintext) = @_;
Line 1488  sub display_color_options { Line 1063  sub display_color_options {
     my $datatable = '<tr'.$css_class.'>'.      my $datatable = '<tr'.$css_class.'>'.
         '<td>'.$choices->{'font'}.'</td>';          '<td>'.$choices->{'font'}.'</td>';
     if (!$is_custom->{'font'}) {      if (!$is_custom->{'font'}) {
         $datatable .=  '<td>'.&mt('Default in use:').'&nbsp;<span class="css_default_'.$role.'_font" style="color: '.$defaults->{'font'}.';">'.$defaults->{'font'}.'</span></td>';          $datatable .=  '<td>'.&mt('Default in use:').'&nbsp;<span id="css_default_'.$role.'_font" style="color: '.$defaults->{'font'}.';">'.$defaults->{'font'}.'</span></td>';
     } else {      } else {
         $datatable .= '<td>&nbsp;</td>';          $datatable .= '<td>&nbsp;</td>';
     }      }
     my $current_color = $designs->{'font'} ? $designs->{'font'} : $defaults->{'font'};      my $fontlink = &color_pick($phase,$role,'font',$choices->{'font'},$designs->{'font'});
   
     $datatable .= '<td><span class="LC_nobreak">'.      $datatable .= '<td><span class="LC_nobreak">'.
                   '<input type="text" class="colorchooser" size="10" name="'.$role.'_font"'.                    '<input type="text" size="10" name="'.$role.'_font"'.
                   ' value="'.$current_color.'" />&nbsp;'.                    ' value="'.$designs->{'font'}.'" />&nbsp;'.$fontlink.
                   '&nbsp;</span></td></tr>';                    '&nbsp;<span id="css_'.$role.'_font" style="background-color: '.
                     $designs->{'font'}.';">&nbsp;&nbsp;&nbsp;</span>'.
                     '</span></td></tr>';
     unless ($role eq 'login') {       unless ($role eq 'login') { 
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                       '<td>'.$choices->{'fontmenu'}.'</td>';                        '<td>'.$choices->{'fontmenu'}.'</td>';
         if (!$is_custom->{'fontmenu'}) {          if (!$is_custom->{'fontmenu'}) {
             $datatable .=  '<td>'.&mt('Default in use:').'&nbsp;<span class="css_default_'.$role.'_font" style="color: '.$defaults->{'fontmenu'}.';">'.$defaults->{'fontmenu'}.'</span></td>';              $datatable .=  '<td>'.&mt('Default in use:').'&nbsp;<span id="css_default_'.$role.'_font" style="color: '.$defaults->{'fontmenu'}.';">'.$defaults->{'fontmenu'}.'</span></td>';
         } else {          } else {
             $datatable .= '<td>&nbsp;</td>';              $datatable .= '<td>&nbsp;</td>';
         }          }
  $current_color = $designs->{'fontmenu'} ?          $fontlink = &color_pick($phase,$role,'fontmenu',$choices->{'fontmenu'},$designs->{'fontmenu'});
     $designs->{'fontmenu'} : $defaults->{'fontmenu'};  
         $datatable .= '<td><span class="LC_nobreak">'.          $datatable .= '<td><span class="LC_nobreak">'.
                       '<input class="colorchooser" type="text" size="10" name="'                        '<input type="text" size="10" name="'.$role.'_fontmenu"'.
       .$role.'_fontmenu"'.                        ' value="'.$designs->{'fontmenu'}.'" />&nbsp;'.$fontlink.
                       ' value="'.$current_color.'" />&nbsp;'.                        '&nbsp;<span id="css_'.$role.'_fontmenu" style="background-color: '.
                       '&nbsp;</span></td></tr>';                        $designs->{'fontmenu'}.';">&nbsp;&nbsp;&nbsp;</span>'.
                         '</span></td></tr>';
     }      }
     my $switchserver = &check_switchserver($dom,$confname);      my $switchserver = &check_switchserver($dom,$confname);
     foreach my $img (@{$images}) {      foreach my $img (@{$images}) {
Line 1527  sub display_color_options { Line 1103  sub display_color_options {
                     &login_header_options($img,$role,$defaults,$is_custom,$choices);                      &login_header_options($img,$role,$defaults,$is_custom,$choices);
                 $logincolors =                  $logincolors =
                     &login_text_colors($img,$role,$logintext,$phase,$choices,                      &login_text_colors($img,$role,$logintext,$phase,$choices,
                                        $designs,$defaults);                                              $designs);
             } elsif ($img ne 'domlogo') {              } elsif ($img ne 'domlogo') {
                 $datatable.= &logo_display_options($img,$defaults,$designs);                  $datatable.= &logo_display_options($img,$defaults,$designs);
             }              }
Line 1571  sub display_color_options { Line 1147  sub display_color_options {
                         if ($fullwidth ne '' && $fullheight ne '') {                          if ($fullwidth ne '' && $fullheight ne '') {
                             if ($fullwidth > $width && $fullheight > $height) {                               if ($fullwidth > $width && $fullheight > $height) { 
                                 my $size = $width.'x'.$height;                                  my $size = $width.'x'.$height;
                                 my @args = ('convert','-sample',$size,$input,$output);                                  system("convert -sample $size $input $output");
                                 system({$args[0]} @args);  
                                 $showfile = "/$imgdir/tn-".$filename;                                  $showfile = "/$imgdir/tn-".$filename;
                             }                              }
                         }                          }
Line 1607  sub display_color_options { Line 1182  sub display_color_options {
                 $datatable .= &image_changes($is_custom->{$img},$alt_text->{$img},$img_import,                  $datatable .= &image_changes($is_custom->{$img},$alt_text->{$img},$img_import,
                                              $showfile,$fullsize,$role,$img,$imgfile,$logincolors);                                               $showfile,$fullsize,$role,$img,$imgfile,$logincolors);
             } else {              } else {
                 $datatable .= '<td>&nbsp;</td><td class="LC_left_item">'.                  $datatable .= '<td colspan="2" class="LC_right_item"><br />'.
                               &mt('Upload:').'<br />';                                &mt('Upload:');
             }              }
         } else {          } else {
             $datatable .= '<td>&nbsp;</td><td class="LC_left_item">'.              $datatable .= '<td colspan="2" class="LC_right_item"><br />'.
                           &mt('Upload:').'<br />';                            &mt('Upload:');
         }          }
         if ($switchserver) {          if ($switchserver) {
             $datatable .= &mt('Upload to library server: [_1]',$switchserver);              $datatable .= &mt('Upload to library server: [_1]',$switchserver);
Line 1630  sub display_color_options { Line 1205  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><span class="LC_nobreak">'.$choices->{$item}.'</span>&nbsp;<span class="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 1640  sub display_color_options { Line 1215  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}) {
         $datatable .= '<td align="center">'.$choices->{$item};          my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'bgs'}{$item});
  my $color = $designs->{'bgs'}{$item} ? $designs->{'bgs'}{$item} : $defaults->{'bgs'}{$item};          $datatable .= '<td align="center">'.$link;
         if ($designs->{'bgs'}{$item}) {          if ($designs->{'bgs'}{$item}) {
             $datatable .= '&nbsp;';              $datatable .= '&nbsp;<span id="css_'.$role.'_'.$item.'" style="background-color: '.$designs->{'bgs'}{$item}.';">&nbsp;&nbsp;&nbsp;</span>';
         }          }
         $datatable .= '<br /><input type="text" class="colorchooser" size="8" name="'.$role.'_'.$item.'" value="'.$color.          $datatable .= '<br /><input type="text" size="8" name="'.$role.'_'.$item.'" value="'.$designs->{'bgs'}{$item}.
                       '" 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 1658  sub display_color_options { Line 1232  sub display_color_options {
     my $links_def;      my $links_def;
     foreach my $item (@{$links}) {      foreach my $item (@{$links}) {
         if (!$is_custom->{$item}) {          if (!$is_custom->{$item}) {
             $links_def .= '<td>'.$choices->{$item}.'<br /><span class="css_default_'.$role.'_'.$item.'" style="color: '.$defaults->{'links'}{$item}.';">'.$defaults->{'links'}{$item}.'</span></td>';              $links_def .= '<td>'.$choices->{$item}.'<br /><span id="css_default_'.$role.'_'.$item.'" style="color: '.$defaults->{'links'}{$item}.';">'.$defaults->{'links'}{$item}.'</span></td>';
         }          }
     }      }
     if ($links_def) {      if ($links_def) {
Line 1669  sub display_color_options { Line 1243  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}) {
  my $color = $designs->{'links'}{$item} ? $designs->{'links'}{$item} : $defaults->{'links'}{$item};          $datatable .= '<td align="center">'."\n".
         $datatable .= '<td align="center">'.$choices->{$item}."\n";                        &color_pick($phase,$role,$item,$choices->{$item},
                                     $designs->{'links'}{$item});
         if ($designs->{'links'}{$item}) {          if ($designs->{'links'}{$item}) {
             $datatable.='&nbsp;';              $datatable.='&nbsp;<span id="css_'.$role.'_'.$item.'" style="background-color: '.$designs->{'links'}{$item}.';">&nbsp;&nbsp;&nbsp;</span>';
         }          }
         $datatable .= '<br /><input type="text" size="8" class="colorchooser" name="'.$role.'_'.$item.'" value="'.$color.          $datatable .= '<br /><input type="text" size="8" name="'.$role.'_'.$item.'" value="'.$designs->{'links'}{$item}.
                       '" /></td>';                        '" /></td>';
     }      }
     $$rowtotal += $itemcount;      $$rowtotal += $itemcount;
Line 1728  sub login_header_options  { Line 1303  sub login_header_options  {
 }  }
   
 sub login_text_colors {  sub login_text_colors {
     my ($img,$role,$logintext,$phase,$choices,$designs,$defaults) = @_;      my ($img,$role,$logintext,$phase,$choices,$designs) = @_;
     my $color_menu = '<table border="0"><tr>';      my $color_menu = '<table border="0"><tr>';
     foreach my $item (@{$logintext}) {      foreach my $item (@{$logintext}) {
         $color_menu .= '<td align="center">'.$choices->{$item};          my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'logintext'}{$item});
         my $color = $designs->{'logintext'}{$item} ? $designs->{'logintext'}{$item} : $defaults->{'logintext'}{$item};          $color_menu .= '<td align="center">'.$link;
         $color_menu .= '<br /><input type="text" class="colorchooser" size="8" name="'.$role.'_'.$item.'" value="'.$color.          if ($designs->{'logintext'}{$item}) {
                       '" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>';              $color_menu .= '&nbsp;<span id="css_'.$role.'_'.$item.'" style="background-color: '.$designs->{'logintext'}{$item}.';">&nbsp;&nbsp;&nbsp;</span>';
           }
           $color_menu .= '<br /><input type="text" size="8" name="'.$role.'_'.$item.'" value="'.
                          $designs->{'logintext'}{$item}.'" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>'.
                          '<td>&nbsp;</td>';
     }      }
     $color_menu .= '</tr></table><br />';      $color_menu .= '</tr></table><br />';
     return $color_menu;      return $color_menu;
Line 1744  sub image_changes { Line 1323  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 ($img eq 'login') {      if ($img eq 'login') {
         $output = '</td><td>'.$logincolors; # suppress image for Log-in header              # suppress image for Log-in header
     } elsif (!$is_custom) {      } elsif (!$is_custom) {
         if ($img ne 'domlogo') {          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 ne 'login') {      if ($img eq 'login') { # suppress image for Log-in header
           $output .= '<td>'.$logincolors;
       } else {
         if ($img_import) {          if ($img_import) {
             $output .= '<input type="hidden" name="'.$role.'_import_'.$img.'" value="'.$imgfile.'" />';              $output .= '<input type="hidden" name="'.$role.'_import_'.$img.'" value="'.$imgfile.'" />';
         }          }
Line 1764  sub image_changes { Line 1345  sub image_changes {
                        $role.'_del_'.$img.'" value="1" />'.&mt('Delete?').                         $role.'_del_'.$img.'" value="1" />'.&mt('Delete?').
                        '</label>&nbsp;'.&mt('Replace:').'</span><br />';                         '</label>&nbsp;'.&mt('Replace:').'</span><br />';
         } else {          } else {
             $output .= '<td valign="middle">'.$logincolors.&mt('Upload:').'<br />';              $output .= '<td valign="bottom">'.$logincolors.&mt('Upload:').'<br />';
         }          }
     }      }
     return $output;      return $output;
 }  }
   
   sub color_pick {
       my ($phase,$role,$item,$desc,$curcol) = @_;
       my $link = '<a href="javascript:pjump('."'color_custom','".$desc.
                  "','".$curcol."','".$role.'_'.$item."','parmform.pres','psub'".
                  ');">'.$desc.'</a>';
       return $link;
   }
   
 sub print_quotas {  sub print_quotas {
     my ($dom,$settings,$rowtotal,$action) = @_;      my ($dom,$settings,$rowtotal,$action) = @_;
     my $context;      my $context;
Line 1778  sub print_quotas { Line 1367  sub print_quotas {
     } else {      } else {
         $context = $action;          $context = $action;
     }      }
     my ($datatable,$defaultquota,$authorquota,@usertools,@options,%validations);      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,%titles);      my ($css_class,%titles);
     if ($context eq 'requestcourses') {      if ($context eq 'requestcourses') {
         @usertools = ('official','unofficial','community','textbook');          @usertools = ('official','unofficial','community');
         @options =('norequest','approval','validate','autolimit');          @options =('norequest','approval','validate','autolimit');
         %validations = &Apache::lonnet::auto_courserequest_checks($dom);          %validations = &Apache::lonnet::auto_courserequest_checks($dom);
         %titles = &courserequest_titles();          %titles = &courserequest_titles();
     } elsif ($context eq 'requestauthor') {  
         @usertools = ('author');  
         @options = ('norequest','approval','automatic');  
         %titles = &authorrequest_titles();  
     } else {      } else {
         @usertools = ('aboutme','blog','webdav','portfolio');          @usertools = ('aboutme','blog','webdav','portfolio');
         %titles = &tool_titles();          %titles = &tool_titles();
     }      }
     if (ref($types) eq 'ARRAY') {      if (ref($types) eq 'ARRAY') {
         foreach my $type (@{$types}) {          foreach my $type (@{$types}) {
             my ($currdefquota,$currauthorquota);              my $currdefquota;
             unless (($context eq 'requestcourses') ||              unless ($context eq 'requestcourses') {
                     ($context eq 'requestauthor')) {  
                 if (ref($settings) eq 'HASH') {                  if (ref($settings) eq 'HASH') {
                     if (ref($settings->{defaultquota}) eq 'HASH') {                      if (ref($settings->{defaultquota}) eq 'HASH') {
                         $currdefquota = $settings->{defaultquota}->{$type};                          $currdefquota = $settings->{defaultquota}->{$type}; 
                     } else {                      } else {
                         $currdefquota = $settings->{$type};                          $currdefquota = $settings->{$type};
                     }                      }
                     if (ref($settings->{authorquota}) eq 'HASH') {  
                         $currauthorquota = $settings->{authorquota}->{$type};  
                     }  
                 }                  }
             }              }
             if (defined($usertypes->{$type})) {              if (defined($usertypes->{$type})) {
Line 1872  sub print_quotas { Line 1453  sub print_quotas {
                                 $cell{$item} .= $titles{'unlimited'};                                  $cell{$item} .= $titles{'unlimited'};
                             }                              }
                         }                          }
                     } elsif ($context eq 'requestauthor') {  
                         my $curroption;  
                         if (ref($settings) eq 'HASH') {  
                             $curroption = $settings->{$type};  
                         }  
                         if (!$curroption) {  
                             $curroption = 'norequest';  
                         }  
                         foreach my $option (@options) {  
                             my $val = $option;  
                             if ($option eq 'norequest') {  
                                 $val = 0;  
                             }  
                             my $checked = '';  
                             if ($option eq $curroption) {  
                                 $checked = ' checked="checked"';  
                             }  
                             $datatable .= '<span class="LC_nobreak"><label>'.  
                                   '<input type="radio" name="authorreq_'.$type.  
                                   '" value="'.$val.'"'.$checked.' />'.  
                                   $titles{$option}.'</label></span>&nbsp; ';  
                         }  
                     } else {                      } else {
                         my $checked = 'checked="checked" ';                          my $checked = 'checked="checked" ';
                         if (ref($settings) eq 'HASH') {                          if (ref($settings) eq 'HASH') {
Line 1919  sub print_quotas { Line 1478  sub print_quotas {
                     $datatable .= '</tr></table>';                      $datatable .= '</tr></table>';
                 }                  }
                 $datatable .= '</td>';                  $datatable .= '</td>';
                 unless (($context eq 'requestcourses') ||                  unless ($context eq 'requestcourses') {
                         ($context eq 'requestauthor')) {  
                     $datatable .=                       $datatable .= 
                               '<td class="LC_right_item">'.                                '<td class="LC_right_item"><span class="LC_nobreak">'.
                               '<span class="LC_nobreak">'.&mt('Portfolio').':&nbsp;'.  
                               '<input type="text" name="quota_'.$type.                                '<input type="text" name="quota_'.$type.
                               '" value="'.$currdefquota.                                '" value="'.$currdefquota.
                               '" size="5" /></span>'.('&nbsp;' x 2).                                '" size="5" /> Mb</span></td>';
                               '<span class="LC_nobreak">'.&mt('Authoring').':&nbsp;'.  
                               '<input type="text" name="authorquota_'.$type.  
                               '" value="'.$currauthorquota.  
                               '" size="5" /></span></td>';  
                 }                  }
                 $datatable .= '</tr>';                  $datatable .= '</tr>';
             }              }
         }          }
     }      }
     unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {      unless ($context eq 'requestcourses') {
         $defaultquota = '20';          $defaultquota = '20';
         $authorquota = '500';  
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if (ref($settings->{'defaultquota'}) eq 'HASH') {              if (ref($settings->{'defaultquota'}) eq 'HASH') {
                 $defaultquota = $settings->{'defaultquota'}->{'default'};                  $defaultquota = $settings->{'defaultquota'}->{'default'};
             } elsif (defined($settings->{'default'})) {              } elsif (defined($settings->{'default'})) {
                 $defaultquota = $settings->{'default'};                  $defaultquota = $settings->{'default'};
             }              }
             if (ref($settings->{'authorquota'}) eq 'HASH') {  
                 $authorquota = $settings->{'authorquota'}->{'default'};  
             }  
         }          }
     }      }
     $typecount ++;      $typecount ++;
Line 2010  sub print_quotas { Line 1559  sub print_quotas {
                     $defcell{$item} .= $titles{'unlimited'};                      $defcell{$item} .= $titles{'unlimited'};
                 }                  }
             }              }
         } elsif ($context eq 'requestauthor') {  
             my $curroption;  
             if (ref($settings) eq 'HASH') {  
                 $curroption = $settings->{'default'};  
             }  
             if (!$curroption) {  
                 $curroption = 'norequest';  
             }  
             foreach my $option (@options) {  
                 my $val = $option;  
                 if ($option eq 'norequest') {  
                     $val = 0;  
                 }  
                 my $checked = '';  
                 if ($option eq $curroption) {  
                     $checked = ' checked="checked"';  
                 }  
                 $datatable .= '<span class="LC_nobreak"><label>'.  
                               '<input type="radio" name="authorreq_default"'.  
                               ' value="'.$val.'"'.$checked.' />'.  
                               $titles{$option}.'</label></span>&nbsp; ';  
             }  
         } else {          } else {
             my $checked = 'checked="checked" ';              my $checked = 'checked="checked" ';
             if (ref($settings) eq 'HASH') {              if (ref($settings) eq 'HASH') {
Line 2057  sub print_quotas { Line 1584  sub print_quotas {
         $datatable .= '</tr></table>';          $datatable .= '</tr></table>';
     }      }
     $datatable .= '</td>';      $datatable .= '</td>';
     unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {      unless ($context eq 'requestcourses') {
         $datatable .= '<td class="LC_right_item">'.          $datatable .= '<td class="LC_right_item"><span class="LC_nobreak">'.
                       '<span class="LC_nobreak">'.&mt('Portfolio').':&nbsp;'.  
                       '<input type="text" name="defaultquota" value="'.                        '<input type="text" name="defaultquota" value="'.
                       $defaultquota.'" size="5" /></span>'.('&nbsp;' x2).                        $defaultquota.'" size="5" /> Mb</span></td>';
                       '<span class="LC_nobreak">'.&mt('Authoring').':&nbsp;'.  
                       '<input type="text" name="authorquota" value="'.  
                       $authorquota.'" size="5" /></span></td>';  
     }      }
     $datatable .= '</tr>';      $datatable .= '</tr>';
     $typecount ++;      $typecount ++;
     $css_class = $typecount%2?' class="LC_odd_row"':'';      $css_class = $typecount%2?' class="LC_odd_row"':'';
     $datatable .= '<tr'.$css_class.'>'.      $datatable .= '<tr'.$css_class.'>'.
                   '<td>'.&mt('LON-CAPA Advanced Users').'<br />';                    '<td>'.&mt('LON-CAPA Advanced Users').' ';
     if ($context eq 'requestcourses') {      if ($context eq 'requestcourses') {
         $datatable .= &mt('(overrides affiliation, if set)').          $datatable .= &mt('(overrides affiliation, if set)').
                       '</td>'.                        '</td>'.
Line 2139  sub print_quotas { Line 1662  sub print_quotas {
                     $advcell{$item} .= $titles{'unlimited'};                      $advcell{$item} .= $titles{'unlimited'};
                 }                  }
             }              }
         } elsif ($context eq 'requestauthor') {  
             my $curroption;  
             if (ref($settings) eq 'HASH') {  
                 $curroption = $settings->{'_LC_adv'};  
             }  
             my $checked = '';  
             if ($curroption eq '') {  
                 $checked = ' checked="checked"';  
             }  
             $datatable .= '<span class="LC_nobreak"><label>'.  
                           '<input type="radio" name="authorreq__LC_adv"'.  
                           ' value=""'.$checked.' />'.  
                           &mt('No override set').'</label></span>&nbsp; ';  
             foreach my $option (@options) {  
                 my $val = $option;  
                 if ($option eq 'norequest') {  
                     $val = 0;  
                 }  
                 my $checked = '';  
                 if ($val eq $curroption) {  
                     $checked = ' checked="checked"';  
                 }  
                 $datatable .= '<span class="LC_nobreak"><label>'.  
                               '<input type="radio" name="authorreq__LC_adv"'.  
                               ' value="'.$val.'"'.$checked.' />'.  
                               $titles{$option}.'</label></span>&nbsp; ';  
             }  
         } else {          } else {
             my $checked = 'checked="checked" ';              my $checked = 'checked="checked" ';
             if (ref($settings) eq 'HASH') {              if (ref($settings) eq 'HASH') {
Line 2195  sub print_quotas { Line 1691  sub print_quotas {
     return $datatable;      return $datatable;
 }  }
   
 sub print_requestmail {  sub print_courserequestmail {
     my ($dom,$action,$settings,$rowtotal,$customcss,$rowstyle) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my ($now,$datatable,%currapp);      my ($now,$datatable,%dompersonnel,@domcoord,@currapproval,$rows);
     $now = time;      $now = time;
     if (ref($settings) eq 'HASH') {      $rows = 0;
         if (ref($settings->{'notify'}) eq 'HASH') {      %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc'],$now,$now);
             if ($settings->{'notify'}{'approval'} ne '') {      foreach my $server (keys(%dompersonnel)) {
                 map {$currapp{$_}=1;} split(/,/,$settings->{'notify'}{'approval'});          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);
             }              }
         }          }
     }      }
     my $numinrow = 2;  
     my $css_class;  
     if ($$rowtotal%2) {  
         $css_class = 'LC_odd_row';  
     }  
     if ($customcss) {  
         $css_class .= " $customcss";  
     }  
     $css_class =~ s/^\s+//;  
     if ($css_class) {  
         $css_class = ' class="'.$css_class.'"';  
     }  
     if ($rowstyle) {  
         $css_class .= ' style="'.$rowstyle.'"';  
     }  
     my $text;  
     if ($action eq 'requestcourses') {  
         $text = &mt('Receive notification of course requests requiring approval');  
     } elsif ($action eq 'requestauthor') {  
         $text = &mt('Receive notification of Authoring Space requests requiring approval');  
     } else {  
        $text = &mt('Receive notification of queued requests for self-created user accounts requiring approval');  
     }  
     $datatable = '<tr'.$css_class.'>'.  
                  ' <td>'.$text.'</td>'.  
                  ' <td class="LC_left_item">';  
     my ($numdc,$table,$rows) = &active_dc_picker($dom,$numinrow,'checkbox',  
                                                  $action.'notifyapproval',%currapp);  
     if ($numdc > 0) {  
         $datatable .= $table;  
     } else {  
         $datatable .= &mt('There are no active Domain Coordinators');  
     }  
     $datatable .='</td></tr>';  
     return $datatable;  
 }  
   
 sub print_studentcode {  
     my ($settings,$rowtotal) = @_;  
     my $rownum = 0;   
     my ($output,%current);  
     my @crstypes = ('official','unofficial','community','textbook');  
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{'uniquecode'}) eq 'HASH') {          if (ref($settings->{'notify'}) eq 'HASH') {
             foreach my $type (@crstypes) {              if ($settings->{'notify'}{'approval'} ne '') {
                 $current{$type} = $settings->{'uniquecode'}{$type};                 @currapproval = split(',',$settings->{'notify'}{'approval'});
             }              }
         }          }
     }      }
     $output .= '<tr>'.      if (@currapproval) {
                '<td class="LC_left_item">'.&mt('Generate unique six character code as course identifier?').'</td>'.          foreach my $dc (@currapproval) {
                '<td class="LC_left_item">';              unless (grep(/^\Q$dc\E$/,@domcoord)) {
     foreach my $type (@crstypes) {                  push(@domcoord,$dc);
         my $check = ' ';  
         if ($current{$type}) {  
             $check = ' checked="checked" ';  
         }  
         $output .= '<span class="LC_nobreak"><label>'.  
                    '<input type="checkbox" name="uniquecode" value="'.$type.'"'.$check.'/>'.  
                    &mt($type).'</label></span>'.('&nbsp;'x2).' ';  
     }  
     $output .= '</td></tr>';  
     $$rowtotal ++;  
     return $output;  
 }  
   
 sub print_textbookcourses {  
     my ($dom,$type,$settings,$rowtotal) = @_;  
     my $rownum = 0;  
     my $css_class;  
     my $itemcount = 1;  
     my $maxnum = 0;  
     my $bookshash;  
     if (ref($settings) eq 'HASH') {  
         $bookshash = $settings->{$type};  
     }  
     my %ordered;  
     if (ref($bookshash) eq 'HASH') {  
         foreach my $item (keys(%{$bookshash})) {  
             if (ref($bookshash->{$item}) eq 'HASH') {  
                 my $num = $bookshash->{$item}{'order'};  
                 $ordered{$num} = $item;  
             }              }
         }          }
     }      }
     my $confname = $dom.'-domainconfig';      @domcoord = sort(@domcoord);
     my $switchserver = &check_switchserver($dom,$confname);      my $numinrow = 4;
     my $maxnum = scalar(keys(%ordered));      my $numdc = @domcoord;
     my $datatable;      my $css_class = 'class="LC_odd_row"';
     if (keys(%ordered)) {      $datatable = '<tr'.$css_class.'>'.
         my @items = sort { $a <=> $b } keys(%ordered);                   ' <td>'.&mt('Receive notification of course requests requiring approval.').
         for (my $i=0; $i<@items; $i++) {                   ' </td>'.
             $css_class = $itemcount%2?' class="LC_odd_row"':'';                   ' <td class="LC_left_item">';
             my $key = $ordered{$items[$i]};      if (@domcoord > 0) {
             my %coursehash=&Apache::lonnet::coursedescription($key);          $datatable .= '<table>';
             my $coursetitle = $coursehash{'description'};          for (my $i=0; $i<$numdc; $i++) {
             my ($subject,$title,$author,$publisher,$image,$imgsrc,$cdom,$cnum);              my $rem = $i%($numinrow);
             if (ref($bookshash->{$key}) eq 'HASH') {              if ($rem == 0) {
                 $subject = $bookshash->{$key}->{'subject'};                  if ($i > 0) {
                 $title = $bookshash->{$key}->{'title'};                      $datatable .= '</tr>';
                 if ($type eq 'textbooks') {  
                     $publisher = $bookshash->{$key}->{'publisher'};  
                     $author = $bookshash->{$key}->{'author'};  
                     $image = $bookshash->{$key}->{'image'};  
                     if ($image ne '') {  
                         my ($path,$imagefile) = ($image =~ m{^(.+)/([^/]+)$});  
                         my $imagethumb = "$path/tn-".$imagefile;  
                         $imgsrc = '<img src="'.$imagethumb.'" alt="'.&mt('Textbook image').'" />';  
                     }  
                 }                  }
                   $datatable .= '<tr>';
                   $rows ++;
             }              }
             my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$type".'_'."$key','$type'".');"';              my $check = ' ';
             $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'              if (grep(/^\Q$domcoord[$i]\E$/,@currapproval)) {
                          .'<select name="'.$type.'_'.$key.'"'.$chgstr.'>';                  $check = ' checked="checked" ';
             for (my $k=0; $k<=$maxnum; $k++) {              }
                 my $vpos = $k+1;              my ($uname,$udom) = split(':',$domcoord[$i]);
                 my $selstr;              my $fullname = &Apache::loncommon::plainname($uname,$udom);
                 if ($k == $i) {              if ($i == $numdc-1) {
                     $selstr = ' selected="selected" ';                  my $colsleft = $numinrow-$rem;
                 }                  if ($colsleft > 1) {
                 $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';                      $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
             }  
             $datatable .= '</select>'.('&nbsp;'x2).  
                 '<label><input type="checkbox" name="'.$type.'_del" value="'.$key.'" />'.  
                 &mt('Delete?').'</label></span></td>'.  
                 '<td colspan="2">'.  
                 '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_subject_'.$i.'" value="'.$subject.'" /></span> '.  
                 ('&nbsp;'x2).  
                 '<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="'.$type.'_title_'.$i.'" value="'.$title.'" /></span> ';  
             if ($type eq 'textbooks') {  
                 $datatable .= ('&nbsp;'x2).  
                               '<span class="LC_nobreak">'.&mt('Publisher:').'<input type="text" size="10" name="'.$type.'_publisher_'.$i.'" value="'.$publisher.'" /></span> '.  
                               ('&nbsp;'x2).  
                               '<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="'.$type.'_author_'.$i.'" value="'.$author.'" /></span> '.  
                               ('&nbsp;'x2).  
                               '<span class="LC_nobreak">'.&mt('Thumbnail:');  
                 if ($image) {  
                     $datatable .= '<span class="LC_nobreak">'.  
                                   $imgsrc.  
                                   '<label><input type="checkbox" name="'.$type.'_image_del"'.  
                                   ' value="'.$key.'" />'.&mt('Delete?').'</label></span> '.  
                                   '<span class="LC_nobreak">&nbsp;'.&mt('Replace:').'&nbsp;';  
                 }  
                 if ($switchserver) {  
                     $datatable .= &mt('Upload to library server: [_1]',$switchserver);  
                 } else {                  } else {
                     $datatable .= '<input type="file" name="'.$type.'_image_'.$i.'" value="" />';                      $datatable .= '<td class="LC_left_item">';
                 }  
             }  
             $datatable .= '<input type="hidden" name="'.$type.'_id_'.$i.'" value="'.$type.'_'.$key.'" /></span> '.  
                           '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.  
                           $coursetitle.'</span></td></tr>'."\n";  
             $itemcount ++;  
         }  
     }  
     $css_class = $itemcount%2?' class="LC_odd_row"':'';  
     my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$type"."_addbook_pos','$type'".');"';  
     $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".  
                   '<input type="hidden" name="'.$type.'_maxnum" value="'.$maxnum.'" />'."\n".  
                   '<select name="'.$type.'_addbook_pos"'.$chgstr.'>';  
     for (my $k=0; $k<$maxnum+1; $k++) {  
         my $vpos = $k+1;  
         my $selstr;  
         if ($k == $maxnum) {  
             $selstr = ' selected="selected" ';  
         }  
         $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';  
     }  
     $datatable .= '</select>&nbsp;'."\n".  
                   '<input type="checkbox" name="'.$type.'_addbook" value="1" />'.&mt('Add').'</span></td>'."\n".  
                   '<td colspan="2">'.  
                   '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_addbook_subject" value="" /></span> '."\n".  
                   ('&nbsp;'x2).  
                   '<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="'.$type.'_addbook_title" value="" /></span> '."\n".  
                   ('&nbsp;'x2);  
     if ($type eq 'textbooks') {  
         $datatable .= '<span class="LC_nobreak">'.&mt('Publisher:').'<input type="text" size="10" name="'.$type.'_addbook_publisher" value="" /></span> '."\n".  
                       ('&nbsp;'x2).  
                       '<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="'.$type.'_addbook_author" value="" /></span> '."\n".  
                       ('&nbsp;'x2).  
                       '<span class="LC_nobreak">'.&mt('Image:').'&nbsp;';  
         if ($switchserver) {  
             $datatable .= &mt('Upload to library server: [_1]',$switchserver);  
         } else {  
             $datatable .= '<input type="file" name="'.$type.'_addbook_image" value="" />';  
         }  
         $datatable .= '</span>'."\n";  
     }  
     $datatable .= '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.  
                   &Apache::loncommon::select_dom_form($env{'request.role.domain'},$type.'_addbook_cdom').  
                   '<input type="text" size="25" name="'.$type.'_addbook_cnum" value="" />'.  
                   &Apache::loncommon::selectcourse_link  
                       ('display',$type.'_addbook_cnum',$type.'_addbook_cdom',undef,undef,undef,'Course').  
                   '</span></td>'."\n".  
                   '</tr>'."\n";  
     $itemcount ++;  
     return $datatable;  
 }  
   
 sub textbookcourses_javascript {  
     my ($settings) = @_;  
     return unless(ref($settings) eq 'HASH');  
     my (%ordered,%total,%jstext);  
     foreach my $type ('textbooks','templates') {  
         $total{$type} = 0;  
         if (ref($settings->{$type}) eq 'HASH') {  
             foreach my $item (keys(%{$settings->{$type}})) {  
                 if (ref($settings->{$type}->{$item}) eq 'HASH') {  
                     my $num = $settings->{$type}->{$item}{'order'};  
                     $ordered{$type}{$num} = $item;  
                 }  
             }  
             $total{$type} = scalar(keys(%{$settings->{$type}}));  
         }  
         my @jsarray = ();  
         foreach my $item (sort {$a <=> $b } (keys(%{$ordered{$type}}))) {  
             push(@jsarray,$ordered{$type}{$item});  
         }  
         $jstext{$type} = '    var '.$type.' = Array('."'".join("','",@jsarray)."'".');'."\n";  
     }  
     return <<"ENDSCRIPT";  
 <script type="text/javascript">  
 // <![CDATA[  
 function reorderBooks(form,item,caller) {  
     var changedVal;  
 $jstext{'textbooks'};  
 $jstext{'templates'};  
     var newpos;  
     var maxh;  
     if (caller == 'textbooks') {    
         newpos = 'textbooks_addbook_pos';  
         maxh = 1 + $total{'textbooks'};  
     } else {  
         newpos = 'templates_addbook_pos';  
         maxh = 1 + $total{'templates'};  
     }  
     var current = new Array;  
     var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;  
     if (item == newpos) {  
         changedVal = newitemVal;  
     } else {  
         changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;  
         current[newitemVal] = newpos;  
     }  
     if (caller == 'textbooks') {  
         for (var i=0; i<textbooks.length; i++) {  
             var elementName = 'textbooks_'+textbooks[i];  
             if (elementName != item) {  
                 if (form.elements[elementName]) {  
                     var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;  
                     current[currVal] = elementName;  
                 }  
             }  
         }  
     }  
     if (caller == 'templates') {  
         for (var i=0; i<templates.length; i++) {  
             var elementName = 'templates_'+templates[i];  
             if (elementName != item) {  
                 if (form.elements[elementName]) {  
                     var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;  
                     current[currVal] = elementName;  
                 }                  }
               } else {
                   $datatable .= '<td class="LC_left_item">';
             }              }
               $datatable .= '<span class="LC_nobreak"><label>'.
                             '<input type="checkbox" name="reqapprovalnotify" '.
                             'value="'.$domcoord[$i].'"'.$check.'/>'.
                             $fullname.'</label></span></td>';
         }          }
     }          $datatable .= '</tr></table>';
     var oldVal;  
     for (var j=0; j<maxh; j++) {  
         if (current[j] == undefined) {  
             oldVal = j;  
         }  
     }  
     if (oldVal < changedVal) {  
         for (var k=oldVal+1; k<=changedVal ; k++) {  
            var elementName = current[k];  
            form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;  
         }  
     } else {      } else {
         for (var k=changedVal; k<oldVal; k++) {          $datatable .= &mt('There are no active Domain Coordinators');
             var elementName = current[k];          $rows ++;
             form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;  
         }  
     }      }
     return;      $datatable .='</td></tr>';
 }      $$rowtotal += $rows;
       return $datatable;
 // ]]>  
 </script>  
   
 ENDSCRIPT  
 }  }
   
 sub print_autoenroll {  sub print_autoenroll {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my $autorun = &Apache::lonnet::auto_run(undef,$dom),      my $autorun = &Apache::lonnet::auto_run(undef,$dom),
     my ($defdom,$runon,$runoff,$coownerson,$coownersoff,$failsafe);      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 2535  sub print_autoenroll { Line 1806  sub print_autoenroll {
         if (exists($settings->{'sender_domain'})) {          if (exists($settings->{'sender_domain'})) {
             $defdom = $settings->{'sender_domain'};              $defdom = $settings->{'sender_domain'};
         }          }
         if (exists($settings->{'autofailsafe'})) {  
             $failsafe = $settings->{'autofailsafe'};  
         }  
     } else {      } else {
         if ($autorun) {          if ($autorun) {
             $runon = ' checked="checked" ';              $runon = ' checked="checked" ';
Line 2573  sub print_autoenroll { Line 1841  sub print_autoenroll {
                   $coownerson.' value="1" />'.&mt('Yes').'</label>&nbsp;'.                    $coownerson.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                   '<label><input type="radio" name="autoassign_coowners"'.                    '<label><input type="radio" name="autoassign_coowners"'.
                   $coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.                    $coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.
                   '</tr><tr>'.                    '</tr>';
                   '<td>'.&mt('Failsafe for no drops when institutional data missing').'</td>'.      $$rowtotal += 3;
                   '<td class="LC_right_item"><span class="LC_nobreak">'.  
                   '<input type="text" name="autoenroll_failsafe"'.  
                   ' value="'.$failsafe.'" size="4" /></span></td></tr>';  
     $$rowtotal += 4;  
     return $datatable;      return $datatable;
 }  }
   
Line 2626  sub print_autoupdate { Line 1890  sub print_autoupdate {
         my $locknamesettings;          my $locknamesettings;
         $datatable .= &insttypes_row($settings,$types,$usertypes,          $datatable .= &insttypes_row($settings,$types,$usertypes,
                                      $dom,$numinrow,$othertitle,                                       $dom,$numinrow,$othertitle,
                                     'lockablenames',$rowtotal);                                      'lockablenames');
         $$rowtotal ++;          $$rowtotal ++;
     } else {      } else {
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);          my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
Line 2653  sub print_autoupdate { Line 1917  sub print_autoupdate {
   
 sub print_autocreate {  sub print_autocreate {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my (%createon,%createoff,%currhash);      my (%createon,%createoff);
       my $curr_dc;
     my @types = ('xml','req');      my @types = ('xml','req');
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         foreach my $item (@types) {          foreach my $item (@types) {
Line 2666  sub print_autocreate { Line 1931  sub print_autocreate {
                 }                  }
             }              }
         }          }
         if ($settings->{'xmldc'} ne '') {          $curr_dc = $settings->{'xmldc'};
             $currhash{$settings->{'xmldc'}} = 1;  
         }  
     } else {      } else {
         foreach my $item (@types) {          foreach my $item (@types) {
             $createoff{$item} = ' checked="checked" ';              $createoff{$item} = ' checked="checked" ';
Line 2676  sub print_autocreate { Line 1939  sub print_autocreate {
         }          }
     }      }
     $$rowtotal += 2;      $$rowtotal += 2;
     my $numinrow = 2;  
     my $datatable='<tr class="LC_odd_row">'.      my $datatable='<tr class="LC_odd_row">'.
                   '<td>'.&mt('Create pending official courses from XML files').'</td>'.                    '<td>'.&mt('Create pending official courses from XML files').'</td>'.
                   '<td class="LC_right_item"><span class="LC_nobreak"><label>'.                    '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
Line 2691  sub print_autocreate { Line 1953  sub print_autocreate {
                   $createon{'req'}.' value="1" />'.&mt('Yes').'</label>&nbsp;'.                    $createon{'req'}.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                   '<label><input type="radio" name="autocreate_req"'.                    '<label><input type="radio" name="autocreate_req"'.
                   $createoff{'req'}.' value="0" />'.&mt('No').'</label></span>';                    $createoff{'req'}.' value="0" />'.&mt('No').'</label></span>';
     my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',      my ($numdc,$dctable) = &active_dc_picker($dom,$curr_dc);
                                                    'autocreate_xmldc',%currhash);  
     $datatable .= '</td></tr><tr class="LC_odd_row"><td>';  
     if ($numdc > 1) {      if ($numdc > 1) {
         $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)').          $datatable .= '</td></tr><tr class="LC_odd_row"><td>'.
                       '</td><td class="LC_left_item">';                        &mt('Course creation processed as: (choose Dom. Coord.)').
                         '</td><td class="LC_left_item">'.$dctable.'</td></tr>';
           $$rowtotal ++ ;
     } else {      } else {
         $datatable .= &mt('Course creation processed as:').          $datatable .= $dctable.'</td></tr>';
                       '</td><td class="LC_right_item">';  
     }      }
     $datatable .= $dctable.'</td></tr>';  
     $$rowtotal += $rows;  
     return $datatable;      return $datatable;
 }  }
   
 sub print_directorysrch {  sub print_directorysrch {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my $datatable;      my $srchon = ' ';
     if ($position eq 'top') {      my $srchoff = ' checked="checked" ';
         my $instsrchon = ' ';      my ($exacton,$containson,$beginson);
         my $instsrchoff = ' checked="checked" ';      my $localon = ' ';
         my ($exacton,$containson,$beginson);      my $localoff = ' checked="checked" ';
         my $instlocalon = ' ';      if (ref($settings) eq 'HASH') {
         my $instlocaloff = ' checked="checked" ';          if ($settings->{'available'} eq '1') {
         if (ref($settings) eq 'HASH') {              $srchon = $srchoff;
             if ($settings->{'available'} eq '1') {              $srchoff = ' ';
                 $instsrchon = $instsrchoff;          }
                 $instsrchoff = ' ';          if ($settings->{'localonly'} eq '1') {
             }              $localon = $localoff;
             if ($settings->{'localonly'} eq '1') {              $localoff = ' ';
                 $instlocalon = $instlocaloff;          }
                 $instlocaloff = ' ';          if (ref($settings->{'searchtypes'}) eq 'ARRAY') {
             }              foreach my $type (@{$settings->{'searchtypes'}}) {
             if (ref($settings->{'searchtypes'}) eq 'ARRAY') {                  if ($type eq 'exact') {
                 foreach my $type (@{$settings->{'searchtypes'}}) {  
                     if ($type eq 'exact') {  
                         $exacton = ' checked="checked" ';  
                     } elsif ($type eq 'contains') {  
                         $containson = ' checked="checked" ';  
                     } elsif ($type eq 'begins') {  
                         $beginson = ' checked="checked" ';  
                     }  
                 }  
             } else {  
                 if ($settings->{'searchtypes'} eq 'exact') {  
                     $exacton = ' checked="checked" ';  
                 } elsif ($settings->{'searchtypes'} eq 'contains') {  
                     $containson = ' checked="checked" ';  
                 } elsif ($settings->{'searchtypes'} eq 'specify') {  
                     $exacton = ' checked="checked" ';                      $exacton = ' checked="checked" ';
                   } elsif ($type eq 'contains') {
                     $containson = ' checked="checked" ';                      $containson = ' checked="checked" ';
                   } elsif ($type eq 'begins') {
                       $beginson = ' checked="checked" ';
                 }                  }
             }              }
         }          } else {
         my ($searchtitles,$titleorder) = &sorted_searchtitles();              if ($settings->{'searchtypes'} eq 'exact') {
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);                  $exacton = ' checked="checked" ';
               } elsif ($settings->{'searchtypes'} eq 'contains') {
         my $numinrow = 4;                  $containson = ' checked="checked" ';
         my $cansrchrow = 0;              } elsif ($settings->{'searchtypes'} eq 'specify') {
         $datatable='<tr class="LC_odd_row">'.                  $exacton = ' checked="checked" ';
                    '<td colspan="2"><span class ="LC_nobreak">'.&mt('Institutional directory search available?').'</span></td>'.                  $containson = ' checked="checked" ';
                    '<td class="LC_right_item"><span class="LC_nobreak"><label>'.  
                    '<input type="radio" name="dirsrch_available"'.  
                    $instsrchon.' value="1" />'.&mt('Yes').'</label>&nbsp;'.  
                    '<label><input type="radio" name="dirsrch_available"'.  
                    $instsrchoff.' value="0" />'.&mt('No').'</label></span></td>'.  
                    '</tr><tr>'.  
                    '<td colspan="2"><span class ="LC_nobreak">'.&mt('Other domains can search institution?').'</span></td>'.  
                    '<td class="LC_right_item"><span class="LC_nobreak"><label>'.  
                    '<input type="radio" name="dirsrch_instlocalonly"'.  
                    $instlocaloff.' value="0" />'.&mt('Yes').'</label>&nbsp;'.  
                    '<label><input type="radio" name="dirsrch_instlocalonly"'.  
                    $instlocalon.' value="1" />'.&mt('No').'</label></span></td>'.  
                    '</tr>';  
         $$rowtotal += 2;  
         if (ref($usertypes) eq 'HASH') {  
             if (keys(%{$usertypes}) > 0) {  
                 $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,  
                                              $numinrow,$othertitle,'cansearch',  
                                              $rowtotal);  
                 $cansrchrow = 1;  
             }              }
         }          }
         if ($cansrchrow) {      }
             $$rowtotal ++;      my ($searchtitles,$titleorder) = &sorted_searchtitles();
             $datatable .= '<tr>';      my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
         } else {  
             $datatable .= '<tr class="LC_odd_row">';      my $numinrow = 4;
       my $cansrchrow = 0;
       my $datatable='<tr class="LC_odd_row">'.
                     '<td colspan="2"><span class ="LC_nobreak">'.&mt('Directory search available?').'</span></td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                     '<input type="radio" name="dirsrch_available"'.
                     $srchon.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                     '<label><input type="radio" name="dirsrch_available"'.
                     $srchoff.' value="0" />'.&mt('No').'</label></span></td>'.
                     '</tr><tr>'.
                     '<td colspan="2"><span class ="LC_nobreak">'.&mt('Other domains can search?').'</span></td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                     '<input type="radio" name="dirsrch_localonly"'.
                     $localoff.' value="0" />'.&mt('Yes').'</label>&nbsp;'.
                     '<label><input type="radio" name="dirsrch_localonly"'.
                     $localon.' value="1" />'.&mt('No').'</label></span></td>'.
                     '</tr>';
       $$rowtotal += 2;
       if (ref($usertypes) eq 'HASH') {
           if (keys(%{$usertypes}) > 0) {
               $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,
                                            $numinrow,$othertitle,'cansearch');
               $cansrchrow = 1;
         }          }
         $datatable .= '<td><span class ="LC_nobreak">'.&mt('Supported search methods').      }
                       '</span></td><td class="LC_left_item" colspan="2"><table><tr>';      if ($cansrchrow) {
         foreach my $title (@{$titleorder}) {          $$rowtotal ++;
             if (defined($searchtitles->{$title})) {          $datatable .= '<tr>';
                 my $check = ' ';      } else {
                 if (ref($settings) eq 'HASH') {          $datatable .= '<tr class="LC_odd_row">';
                     if (ref($settings->{'searchby'}) eq 'ARRAY') {      }
                         if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) {      $datatable .= '<td><span class ="LC_nobreak">'.&mt('Supported search methods').
                             $check = ' checked="checked" ';                    '</span></td><td class="LC_left_item" colspan="2"><table><tr>';
                         }      foreach my $title (@{$titleorder}) {
           if (defined($searchtitles->{$title})) {
               my $check = ' ';
               if (ref($settings) eq 'HASH') {
                   if (ref($settings->{'searchby'}) eq 'ARRAY') {
                       if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) {
                           $check = ' checked="checked" ';
                     }                      }
                 }                  }
                 $datatable .= '<td class="LC_left_item">'.  
                               '<span class="LC_nobreak"><label>'.  
                               '<input type="checkbox" name="searchby" '.  
                               'value="'.$title.'"'.$check.'/>'.  
                               $searchtitles->{$title}.'</label></span></td>';  
             }              }
               $datatable .= '<td class="LC_left_item">'.
                             '<span class="LC_nobreak"><label>'.
                             '<input type="checkbox" name="searchby" '.
                             'value="'.$title.'"'.$check.'/>'.
                             $searchtitles->{$title}.'</label></span></td>';
         }          }
         $datatable .= '</tr></table></td></tr>';      }
         $$rowtotal ++;      $datatable .= '</tr></table></td></tr>';
         if ($cansrchrow) {      $$rowtotal ++;
             $datatable .= '<tr class="LC_odd_row">';      if ($cansrchrow) {
         } else {          $datatable .= '<tr class="LC_odd_row">';
             $datatable .= '<tr>';  
         }  
         $datatable .= '<td><span class ="LC_nobreak">'.&mt('Search latitude').'</span></td>'.     
                       '<td class="LC_left_item" colspan="2">'.  
                       '<span class="LC_nobreak"><label>'.  
                       '<input type="checkbox" name="searchtypes" '.  
                       $exacton.' value="exact" />'.&mt('Exact match').  
                       '</label>&nbsp;'.  
                       '<label><input type="checkbox" name="searchtypes" '.  
                       $beginson.' value="begins" />'.&mt('Begins with').  
                       '</label>&nbsp;'.  
                       '<label><input type="checkbox" name="searchtypes" '.  
                       $containson.' value="contains" />'.&mt('Contains').  
                       '</label></span></td></tr>';  
         $$rowtotal ++;  
     } else {      } else {
         my $domsrchon = ' checked="checked" ';          $datatable .= '<tr>';
         my $domsrchoff = ' ';  
         my $domlocalon = ' ';  
         my $domlocaloff = ' checked="checked" ';  
         if (ref($settings) eq 'HASH') {  
             if ($settings->{'lclocalonly'} eq '1') {  
                 $domlocalon = $domlocaloff;  
                 $domlocaloff = ' ';  
             }  
             if ($settings->{'lcavailable'} eq '0') {  
                 $domsrchoff = $domsrchon;  
                 $domsrchon = ' ';  
             }  
         }  
         $datatable='<tr class="LC_odd_row">'.  
                       '<td colspan="2"><span class ="LC_nobreak">'.&mt('LON-CAPA directory search available?').'</span></td>'.  
                       '<td class="LC_right_item"><span class="LC_nobreak"><label>'.  
                       '<input type="radio" name="dirsrch_domavailable"'.  
                       $domsrchon.' value="1" />'.&mt('Yes').'</label>&nbsp;'.  
                       '<label><input type="radio" name="dirsrch_domavailable"'.  
                       $domsrchoff.' value="0" />'.&mt('No').'</label></span></td>'.  
                       '</tr><tr>'.  
                       '<td colspan="2"><span class ="LC_nobreak">'.&mt('Other domains can search LON-CAPA domain?').'</span></td>'.  
                       '<td class="LC_right_item"><span class="LC_nobreak"><label>'.  
                       '<input type="radio" name="dirsrch_domlocalonly"'.  
                       $domlocaloff.' value="0" />'.&mt('Yes').'</label>&nbsp;'.  
                       '<label><input type="radio" name="dirsrch_domlocalonly"'.  
                       $domlocalon.' value="1" />'.&mt('No').'</label></span></td>'.  
                       '</tr>';  
         $$rowtotal += 2;  
     }      }
       $datatable .= '<td><span class ="LC_nobreak">'.&mt('Search latitude').'</span></td>'.   
                     '<td class="LC_left_item" colspan="2">'.
                     '<span class="LC_nobreak"><label>'.
                     '<input type="checkbox" name="searchtypes" '.
                     $exacton.' value="exact" />'.&mt('Exact match').
                     '</label>&nbsp;'.
                     '<label><input type="checkbox" name="searchtypes" '.
                     $beginson.' value="begins" />'.&mt('Begins with').
                     '</label>&nbsp;'.
                     '<label><input type="checkbox" name="searchtypes" '.
                     $containson.' value="contains" />'.&mt('Contains').
                     '</label></span></td></tr>';
       $$rowtotal ++;
     return $datatable;      return $datatable;
 }  }
   
 sub print_contacts {  sub print_contacts {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my $datatable;      my $datatable;
     my @contacts = ('adminemail','supportemail');      my @contacts = ('adminemail','supportemail');
     my (%checked,%to,%otheremails,%bccemails,%includestr,%includeloc,%currfield,      my (%checked,%to,%otheremails,%bccemails);
         $maxsize,$fields,$fieldtitles,$fieldoptions,$possoptions,@mailings);      my @mailings = ('errormail','packagesmail','lonstatusmail','helpdeskmail',
     if ($position eq 'top') {                      'requestsmail');
         if (ref($settings) eq 'HASH') {      foreach my $type (@mailings) {
             foreach my $item (@contacts) {          $otheremails{$type} = '';
                 if (exists($settings->{$item})) {  
                     $to{$item} = $settings->{$item};  
                 }  
             }  
         }  
     } elsif ($position eq 'middle') {  
         @mailings = ('errormail','packagesmail','lonstatusmail','requestsmail',  
                      'updatesmail','idconflictsmail','hostipmail');  
         foreach my $type (@mailings) {  
             $otheremails{$type} = '';  
         }  
     } else {  
         @mailings = ('helpdeskmail','otherdomsmail');  
         foreach my $type (@mailings) {  
             $otheremails{$type} = '';  
         }  
         $bccemails{'helpdeskmail'} = '';  
         $bccemails{'otherdomsmail'} = '';  
         $includestr{'helpdeskmail'} = '';  
         $includestr{'otherdomsmail'} = '';  
         ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();  
     }      }
       $bccemails{'helpdeskmail'} = '';
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         unless ($position eq 'top') {          foreach my $item (@contacts) {
             foreach my $type (@mailings) {              if (exists($settings->{$item})) {
                 if (exists($settings->{$type})) {                  $to{$item} = $settings->{$item};
                     if (ref($settings->{$type}) eq 'HASH') {  
                         foreach my $item (@contacts) {  
                             if ($settings->{$type}{$item}) {  
                                 $checked{$type}{$item} = ' checked="checked" ';  
                             }  
                         }  
                         $otheremails{$type} = $settings->{$type}{'others'};  
                         if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {  
                             $bccemails{$type} = $settings->{$type}{'bcc'};  
                             if ($settings->{$type}{'include'} ne '') {  
                                 ($includeloc{$type},$includestr{$type}) = split(/:/,$settings->{$type}{'include'},2);  
                                 $includestr{$type} = &unescape($includestr{$type});  
                             }  
                         }  
                     }  
                 } elsif ($type eq 'lonstatusmail') {  
                     $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';  
                 }  
             }              }
         }          }
         if ($position eq 'bottom') {          foreach my $type (@mailings) {
             foreach my $type (@mailings) {              if (exists($settings->{$type})) {
                 $bccemails{$type} = $settings->{$type}{'bcc'};                  if (ref($settings->{$type}) eq 'HASH') {
                 if ($settings->{$type}{'include'} ne '') {                      foreach my $item (@contacts) {
                     ($includeloc{$type},$includestr{$type}) = split(/:/,$settings->{$type}{'include'},2);                          if ($settings->{$type}{$item}) {
                     $includestr{$type} = &unescape($includestr{$type});                              $checked{$type}{$item} = ' checked="checked" ';
                 }                          }
             }  
             if (ref($settings->{'helpform'}) eq 'HASH') {  
                 if (ref($fields) eq 'ARRAY') {  
                     foreach my $field (@{$fields}) {  
                         $currfield{$field} = $settings->{'helpform'}{$field};  
                     }                      }
                 }                      $otheremails{$type} = $settings->{$type}{'others'};
                 if (exists($settings->{'helpform'}{'maxsize'})) {                      if ($type eq 'helpdeskmail') {
                     $maxsize = $settings->{'helpform'}{'maxsize'};                          $bccemails{$type} = $settings->{$type}{'bcc'};
                 } else {  
                     $maxsize = '1.0';  
                 }  
             } else {  
                 if (ref($fields) eq 'ARRAY') {  
                     foreach my $field (@{$fields}) {  
                         $currfield{$field} = 'yes';  
                     }                      }
                 }                  }
                 $maxsize = '1.0';              } elsif ($type eq 'lonstatusmail') {
                   $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';
             }              }
         }          }
     } else {      } else {
         if ($position eq 'top') {          $to{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};
             $to{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};          $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{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';          $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" '; 
             $checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';          $checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';
             $checked{'updatesmail'}{'adminemail'} = ' checked="checked" ';  
             $checked{'idconflictsmail'}{'adminemail'} = ' checked="checked" ';  
             $checked{'hostipmail'}{'adminemail'} = ' checked="checked" ';  
         } elsif ($position eq 'bottom') {  
             $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';  
             $checked{'otherdomsmail'}{'supportemail'} = ' checked="checked" ';  
             if (ref($fields) eq 'ARRAY') {  
                 foreach my $field (@{$fields}) {  
                     $currfield{$field} = 'yes';  
                 }  
             }  
             $maxsize = '1.0';  
         }  
     }      }
     my ($titles,$short_titles) = &contact_titles();      my ($titles,$short_titles) = &contact_titles();
     my $rownum = 0;      my $rownum = 0;
     my $css_class;      my $css_class;
     if ($position eq 'top') {      foreach my $item (@contacts) {
         foreach my $item (@contacts) {          $rownum ++;
             $css_class = $rownum%2?' class="LC_odd_row"':'';          $css_class = $rownum%2?' class="LC_odd_row"':'';
             $datatable .= '<tr'.$css_class.'>'.           $datatable .= '<tr'.$css_class.'>'. 
                           '<td><span class="LC_nobreak">'.$titles->{$item}.                    '<td><span class="LC_nobreak">'.$titles->{$item}.
                           '</span></td><td class="LC_right_item">'.                    '</span></td><td class="LC_right_item">'.
                           '<input type="text" name="'.$item.'" value="'.                    '<input type="text" name="'.$item.'" value="'.
                           $to{$item}.'" /></td></tr>';                    $to{$item}.'" /></td></tr>';
             $rownum ++;      }
         }      foreach my $type (@mailings) {
     } elsif ($position eq 'bottom') {          $rownum ++;
         $css_class = $rownum%2?' class="LC_odd_row"':'';          $css_class = $rownum%2?' class="LC_odd_row"':'';
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                       '<td>'.&mt('Extra helpdesk form fields:').'<br />'.                        '<td><span class="LC_nobreak">'.
                       &mt('(e-mail, subject, and description always shown)').                        $titles->{$type}.': </span></td>'.
                       '</td><td class="LC_left_item">';                        '<td class="LC_left_item">'.
         if ((ref($fields) eq 'ARRAY') && (ref($fieldtitles) eq 'HASH') &&                        '<span class="LC_nobreak">';
             (ref($fieldoptions) eq 'HASH') && (ref($possoptions) eq 'HASH')) {          foreach my $item (@contacts) {
             $datatable .= '<table><tr><th>'.&mt('Field').'</th><th>'.&mt('Status').'</th></tr>';              $datatable .= '<label>'.
             foreach my $field (@{$fields}) {                            '<input type="checkbox" name="'.$type.'"'.
                 $datatable .= '<tr><td>'.$fieldtitles->{$field};                            $checked{$type}{$item}.
                 if (($field eq 'screenshot') || ($field eq 'cc')) {                            ' value="'.$item.'" />'.$short_titles->{$item}.
                     $datatable .= ' '.&mt('(logged-in users)');                            '</label>&nbsp;';
                 }          }
                 $datatable .='</td><td>';          $datatable .= '</span><br />'.&mt('Others').':&nbsp;&nbsp;'.
                 my $clickaction;                        '<input type="text" name="'.$type.'_others" '.
                 if ($field eq 'screenshot') {                        'value="'.$otheremails{$type}.'"  />';
                     $clickaction = ' onclick="screenshotSize(this);"';          if ($type eq 'helpdeskmail') {
                 }              $datatable .= '<br />'.&mt('Bcc:').('&nbsp;'x6).
                 if (ref($possoptions->{$field}) eq 'ARRAY') {                            '<input type="text" name="'.$type.'_bcc" '.
                     foreach my $option (@{$possoptions->{$field}}) {                            'value="'.$bccemails{$type}.'"  />';
                         my $checked;  
                         if ($currfield{$field} eq $option) {  
                             $checked = ' checked="checked"';  
                         }  
                         $datatable .= '<span class="LC_nobreak"><label>'.  
                                       '<input type="radio" name="helpform_'.$field.'" '.  
                                       'value="'.$option.'"'.$checked.$clickaction.' />'.$fieldoptions->{$option}.  
                                       '</label></span>'.('&nbsp;'x2);  
                     }  
                 }  
                 if ($field eq 'screenshot') {  
                     my $display;  
                     if ($currfield{$field} eq 'no') {  
                         $display = ' style="display:none"';  
                     }  
                     $datatable .= '</td></tr><tr id="help_screenshotsize"'.$display.'>'.  
                                   '<td>'.&mt('Maximum size for upload (MB)').'</td><td>'.  
                                   '<input type="text" size="5" name="helpform_maxsize" value="'.$maxsize.'" />';  
                 }  
                 $datatable .= '</td></tr>';  
             }  
             $datatable .= '</table>';  
         }          }
         $datatable .= '</td></tr>'."\n";          $datatable .= '</td></tr>'."\n";
         $rownum ++;  
     }  
     unless ($position eq 'top') {  
         foreach my $type (@mailings) {  
             $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">';  
             if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {  
                 $datatable .= '<fieldset><legend>'.&mt('E-mail recipient(s)').'</legend>';  
             }  
             $datatable .= '<span class="LC_nobreak">';  
             foreach my $item (@contacts) {  
                 $datatable .= '<label>'.  
                               '<input type="checkbox" name="'.$type.'"'.  
                               $checked{$type}{$item}.  
                               ' value="'.$item.'" />'.$short_titles->{$item}.  
                               '</label>&nbsp;';  
             }  
             $datatable .= '</span><br />'.&mt('Others').':&nbsp;&nbsp;'.  
                           '<input type="text" name="'.$type.'_others" '.  
                           'value="'.$otheremails{$type}.'"  />';  
             my %locchecked;  
             if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {  
                 foreach my $loc ('s','b') {  
                     if ($includeloc{$type} eq $loc) {  
                         $locchecked{$loc} = ' checked="checked"';  
                         last;  
                     }  
                 }  
                 $datatable .= '<br />'.&mt('Bcc:').('&nbsp;'x6).  
                               '<input type="text" name="'.$type.'_bcc" '.  
                               'value="'.$bccemails{$type}.'"  /></fieldset>'.  
                               '<fieldset><legend>'.&mt('Optional added text').'</legend>'.  
                               &mt('Text automatically added to e-mail:').' '.  
                               '<input type="text" name="'.$type.'_includestr" value="'.$includestr{$type}.'" /><br />'.  
                               '<span class="LC_nobreak">'.&mt('Location:').'&nbsp;'.  
                               '<label><input type="radio" name="'.$type.'_includeloc" value="s"'.$locchecked{'s'}.' />'.&mt('in subject').'</label>'.  
                               ('&nbsp;'x2).  
                               '<label><input type="radio" name="'.$type.'_includeloc" value="b"'.$locchecked{'b'}.' />'.&mt('in body').'</label>'.  
                               '</span></fieldset>';  
             }  
             $datatable .= '</td></tr>'."\n";  
             $rownum ++;  
         }  
     }  
     if ($position eq 'middle') {  
         my %choices;  
         $choices{'reporterrors'} = &mt('E-mail error reports to [_1]',  
                                        &Apache::loncommon::modal_link('http://loncapa.org/core.html',  
                                        &mt('LON-CAPA core group - MSU'),600,500));  
         $choices{'reportupdates'} = &mt('E-mail record of completed LON-CAPA updates to [_1]',  
                                         &Apache::loncommon::modal_link('http://loncapa.org/core.html',  
                                         &mt('LON-CAPA core group - MSU'),600,500));  
         my @toggles = ('reporterrors','reportupdates');  
         my %defaultchecked = ('reporterrors'  => 'on',  
                               'reportupdates' => 'on');  
         (my $reports,$rownum) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,  
                                                    \%choices,$rownum);  
         $datatable .= $reports;  
     } elsif ($position eq 'bottom') {  
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
         my (@posstypes,%usertypeshash);  
         if (ref($types) eq 'ARRAY') {  
             @posstypes = @{$types};  
         }  
         if (@posstypes) {  
             if (ref($usertypes) eq 'HASH') {  
                 %usertypeshash = %{$usertypes};  
             }  
             my @overridden;  
             my $numinrow = 4;  
             if (ref($settings) eq 'HASH') {  
                 if (ref($settings->{'overrides'}) eq 'HASH') {  
                     foreach my $key (sort(keys(%{$settings->{'overrides'}}))) {  
                         if (ref($settings->{'overrides'}{$key}) eq 'HASH') {  
                             push(@overridden,$key);  
                             foreach my $item (@contacts) {  
                                 if ($settings->{'overrides'}{$key}{$item}) {  
                                     $checked{'override_'.$key}{$item} = ' checked="checked" ';  
                                 }  
                             }  
                             $otheremails{'override_'.$key} = $settings->{'overrides'}{$key}{'others'};  
                             $bccemails{'override_'.$key} = $settings->{'overrides'}{$key}{'bcc'};  
                             $includeloc{'override_'.$key} = '';  
                             $includestr{'override_'.$key} = '';  
                             if ($settings->{'overrides'}{$key}{'include'} ne '') {  
                                 ($includeloc{'override_'.$key},$includestr{'override_'.$key}) =  
                                     split(/:/,$settings->{'overrides'}{$key}{'include'},2);  
                                 $includestr{'override_'.$key} = &unescape($includestr{'override_'.$key});  
                             }  
                         }  
                     }  
                 }  
             }  
             my $customclass = 'LC_helpdesk_override';  
             my $optionsprefix = 'LC_options_helpdesk_';  
   
             my $onclicktypes = "toggleHelpdeskRow(this.form,'overrides','$customclass','$optionsprefix');";  
   
             $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,  
                                          $numinrow,$othertitle,'overrides',  
                                          \$rownum,$onclicktypes,$customclass);  
             $rownum ++;  
             $usertypeshash{'default'} = $othertitle;  
             foreach my $status (@posstypes) {  
                 my $css_class;  
                 if ($rownum%2) {  
                     $css_class = 'LC_odd_row ';  
                 }  
                 $css_class .= $customclass;  
                 my $rowid = $optionsprefix.$status;  
                 my $hidden = 1;  
                 my $currstyle = 'display:none';  
                 if (grep(/^\Q$status\E$/,@overridden)) {  
                     $currstyle = 'display:table-row';  
                     $hidden = 0;  
                 }  
                 my $key = 'override_'.$status;  
                 $datatable .= &overridden_helpdesk($checked{$key},$otheremails{$key},$bccemails{$key},  
                                                   $includeloc{$key},$includestr{$key},$status,$rowid,  
                                                   $usertypeshash{$status},$css_class,$currstyle,  
                                                   \@contacts,$short_titles);  
                 unless ($hidden) {  
                     $rownum ++;  
                 }  
             }  
         }  
     }      }
     $$rowtotal += $rownum;      $$rowtotal += $rownum;
     return $datatable;      return $datatable;
 }  }
   
 sub overridden_helpdesk {  
     my ($checked,$otheremails,$bccemails,$includeloc,$includestr,$type,$rowid,  
         $typetitle,$css_class,$rowstyle,$contacts,$short_titles) = @_;  
     my $class = 'LC_left_item';  
     if ($css_class) {  
         $css_class = ' class="'.$css_class.'"';  
     }  
     if ($rowid) {  
         $rowid = ' id="'.$rowid.'"';  
     }  
     if ($rowstyle) {  
         $rowstyle = ' style="'.$rowstyle.'"';  
     }  
     my ($output,$description);  
     $description = &mt('Helpdesk requests from: [_1] in this domain (overrides default)',"<b>$typetitle</b>");  
     $output = '<tr'.$css_class.$rowid.$rowstyle.'>'.  
               "<td>$description</td>\n".  
               '<td class="'.$class.'" colspan="2">'.  
               '<fieldset><legend>'.&mt('E-mail recipient(s)').'</legend>'.  
               '<span class="LC_nobreak">';  
     if (ref($contacts) eq 'ARRAY') {  
         foreach my $item (@{$contacts}) {  
             my $check;  
             if (ref($checked) eq 'HASH') {  
                $check = $checked->{$item};  
             }  
             my $title;  
             if (ref($short_titles) eq 'HASH') {  
                 $title = $short_titles->{$item};  
             }  
             $output .= '<label>'.  
                        '<input type="checkbox" name="override_'.$type.'"'.$check.  
                        ' value="'.$item.'" />'.$title.'</label>&nbsp;';  
         }  
     }  
     $output .= '</span><br />'.&mt('Others').':&nbsp;&nbsp;'.  
                '<input type="text" name="override_'.$type.'_others" '.  
                'value="'.$otheremails.'"  />';  
     my %locchecked;  
     foreach my $loc ('s','b') {  
         if ($includeloc eq $loc) {  
             $locchecked{$loc} = ' checked="checked"';  
             last;  
         }  
     }  
     $output .= '<br />'.&mt('Bcc:').('&nbsp;'x6).  
                '<input type="text" name="override_'.$type.'_bcc" '.  
                'value="'.$bccemails.'"  /></fieldset>'.  
                '<fieldset><legend>'.&mt('Optional added text').'</legend>'.  
                &mt('Text automatically added to e-mail:').' '.  
                '<input type="text" name="override_'.$type.'_includestr" value="'.$includestr.'" /><br />'.  
                '<span class="LC_nobreak">'.&mt('Location:').'&nbsp;'.  
                '<label><input type="radio" name="override_'.$type.'_includeloc" value="s"'.$locchecked{'s'}.' />'.&mt('in subject').'</label>'.  
                ('&nbsp;'x2).  
                '<label><input type="radio" name="override_'.$type.'_includeloc" value="b"'.$locchecked{'b'}.' />'.&mt('in body').'</label>'.  
                '</span></fieldset>'.  
                '</td></tr>'."\n";  
     return $output;  
 }  
   
 sub contacts_javascript {  
     return <<"ENDSCRIPT";  
   
 <script type="text/javascript">  
 // <![CDATA[  
   
 function screenshotSize(field) {  
     if (document.getElementById('help_screenshotsize')) {  
         if (field.value == 'no') {  
             document.getElementById('help_screenshotsize').style.display="none";  
         } else {  
             document.getElementById('help_screenshotsize').style.display="";  
         }  
     }  
     return;  
 }  
   
 function toggleHelpdeskRow(form,checkbox,target,prefix,docount) {  
     if (form.elements[checkbox].length != undefined) {  
         var count = 0;  
         if (docount) {  
             for (var i=0; i<form.elements[checkbox].length; i++) {  
                 if (form.elements[checkbox][i].checked) {  
                     count ++;  
                 }  
             }  
         }  
         for (var i=0; i<form.elements[checkbox].length; i++) {  
             var type = form.elements[checkbox][i].value;  
             if (document.getElementById(prefix+type)) {  
                 if (form.elements[checkbox][i].checked) {  
                     document.getElementById(prefix+type).style.display = 'table-row';  
                     if (count % 2 == 1) {  
                         document.getElementById(prefix+type).className = target+' LC_odd_row';  
                     } else {  
                         document.getElementById(prefix+type).className = target;  
                     }  
                     count ++;  
                 } else {  
                     document.getElementById(prefix+type).style.display = 'none';  
                 }  
             }  
         }  
     }  
     return;  
 }  
   
 // ]]>  
 </script>  
   
 ENDSCRIPT  
 }  
   
 sub print_helpsettings {  sub print_helpsettings {
     my ($position,$dom,$settings,$rowtotal) = @_;  
     my $confname = $dom.'-domainconfig';  
     my $formname = 'display';  
     my ($datatable,$itemcount);  
     if ($position eq 'top') {  
         $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);  
         $$rowtotal ++;  
     } else {  
         my $css_class;  
         my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');  
         my (%customroles,%ordered,%current);  
         if (ref($settings) eq 'HASH') {  
             if (ref($settings->{'adhoc'}) eq 'HASH') {  
                 %current = %{$settings->{'adhoc'}};  
             }  
         }  
         my $count = 0;  
         foreach my $key (sort(keys(%existing))) {  
             if ($key=~/^rolesdef\_(\w+)$/) {  
                 my $rolename = $1;  
                 my (%privs,$order);  
                 ($privs{'system'},$privs{'domain'},$privs{'course'}) = split(/\_/,$existing{$key});  
                 $customroles{$rolename} = \%privs;  
                 if (ref($current{$rolename}) eq 'HASH') {  
                     $order = $current{$rolename}{'order'};  
                 }  
                 if ($order eq '') {  
                     $order = $count;  
                 }  
                 $ordered{$order} = $rolename;  
                 $count++;  
             }  
         }  
         my $maxnum = scalar(keys(%ordered));  
         my @roles_by_num = ();  
         foreach my $item (sort {$a <=> $b } (keys(%ordered))) {  
             push(@roles_by_num,$item);  
         }  
         my $context = 'domprefs';  
         my $crstype = 'Course';  
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
         my @accesstypes = ('all','dh','da','none');  
         my ($numstatustypes,@jsarray);  
         if (ref($types) eq 'ARRAY') {  
             if (@{$types} > 0) {  
                 $numstatustypes = scalar(@{$types});  
                 push(@accesstypes,'status');  
                 @jsarray = ('bystatus');  
             }  
         }  
         my %domhelpdesk = &Apache::lonnet::get_active_domroles($dom,['dh','da']);  
         if (keys(%domhelpdesk)) {  
             push(@accesstypes,('inc','exc'));  
             push(@jsarray,('notinc','notexc'));  
         }  
         my $hiddenstr = join("','",@jsarray);  
         $datatable .= &helpsettings_javascript(\@roles_by_num,$maxnum,$hiddenstr,$formname);  
         my $context = 'domprefs';  
         my $crstype = 'Course';  
         my $prefix = 'helproles_';  
         my $add_class = 'LC_hidden';  
         foreach my $num (@roles_by_num) {  
             my $role = $ordered{$num};  
             my ($desc,$access,@statuses);  
             if (ref($current{$role}) eq 'HASH') {  
                 $desc = $current{$role}{'desc'};  
                 $access = $current{$role}{'access'};  
                 if (ref($current{$role}{'insttypes'}) eq 'ARRAY') {  
                     @statuses = @{$current{$role}{'insttypes'}};  
                 }  
             }  
             if ($desc eq '') {  
                 $desc = $role;  
             }  
             my $identifier = 'custhelp'.$num;  
             my %full=();  
             my %levels= (  
                          course => {},  
                          domain => {},  
                          system => {},  
                         );  
             my %levelscurrent=(  
                                course => {},  
                                domain => {},  
                                system => {},  
                               );  
             &Apache::lonuserutils::custom_role_privs($customroles{$role},\%full,\%levels,\%levelscurrent);  
             my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);  
             $css_class = $itemcount%2?' class="LC_odd_row"':'';  
             my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$num."_pos'".');"';  
             $datatable .= '<tr '.$css_class.'><td valign="top"><b>'.$role.'</b><br />'.  
                           '<select name="helproles_'.$num.'_pos"'.$chgstr.'>';  
             for (my $k=0; $k<=$maxnum; $k++) {  
                 my $vpos = $k+1;  
                 my $selstr;  
                 if ($k == $num) {  
                     $selstr = ' selected="selected" ';  
                 }  
                 $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';  
             }  
             $datatable .= '</select>'.('&nbsp;'x2).  
                           '<input type="hidden" name="helproles_'.$num.'" value="'.$role.'" />'.  
                           '</td>'.  
                           '<td><fieldset><legend>'.&mt('Role name').'</legend>'.  
                           &mt('Name shown to users:').  
                           '<input type="text" name="helproles_'.$num.'_desc" value="'.$desc.'" />'.  
                           '</fieldset>'.  
                           &helpdeskroles_access($dom,$prefix,$num,$add_class,$current{$role},\@accesstypes,  
                                                 $othertitle,$usertypes,$types,\%domhelpdesk).  
                           '<fieldset>'.  
                           '<legend>'.&mt('Role privileges').&adhocbutton($prefix,$num,'privs','show').'</legend>'.  
                           &Apache::lonuserutils::custom_role_table($crstype,\%full,\%levels,  
                                                                    \%levelscurrent,$identifier,  
                                                                    'LC_hidden',$prefix.$num.'_privs').  
                           '</fieldset></td>';  
             $itemcount ++;  
         }  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         my $newcust = 'custhelp'.$count;  
         my (%privs,%levelscurrent);  
         my %full=();  
         my %levels= (  
                      course => {},  
                      domain => {},  
                      system => {},  
                     );  
         &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);  
         my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);  
         my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$count."_pos'".');"';  
         $datatable .= '<tr '.$css_class.'><td valign="top"><span class="LC_nobreak"><label>'.  
                       '<input type="hidden" name="helproles_maxnum" value="'.$maxnum.'" />'."\n".  
                       '<select name="helproles_'.$count.'_pos"'.$chgstr.'>';  
         for (my $k=0; $k<$maxnum+1; $k++) {  
             my $vpos = $k+1;  
             my $selstr;  
             if ($k == $maxnum) {  
                 $selstr = ' selected="selected" ';  
             }  
             $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';  
         }  
         $datatable .= '</select>&nbsp;'."\n".  
                       '<input type="checkbox" name="newcusthelp" value="'.$count.'" />'. &mt('Add').  
                       '</label></span></td>'.  
                       '<td><fieldset><legend>'.&mt('Role name').'</legend>'.  
                       '<span class="LC_nobreak">'.  
                       &mt('Internal name:').  
                       '<input type="text" size="10" name="custhelpname'.$count.'" value="" />'.  
                       '</span>'.('&nbsp;'x4).  
                       '<span class="LC_nobreak">'.  
                       &mt('Name shown to users:').  
                       '<input type="text" size="20" name="helproles_'.$count.'_desc" value="" />'.  
                       '</span></fieldset>'.  
                        &helpdeskroles_access($dom,$prefix,$count,'',undef,\@accesstypes,$othertitle,  
                                              $usertypes,$types,\%domhelpdesk).  
                       '<fieldset><legend>'.&mt('Role privileges').'</legend>'.  
                       &Apache::lonuserutils::custom_role_header($context,$crstype,  
                                                                 \@templateroles,$newcust).  
                       &Apache::lonuserutils::custom_role_table('Course',\%full,\%levels,  
                                                                \%levelscurrent,$newcust).  
                       '</fieldset>'.  
                       &helpsettings_javascript(\@roles_by_num,$maxnum,$hiddenstr,$formname).  
                       '</td></tr>';  
         $count ++;  
         $$rowtotal += $count;  
     }  
     return $datatable;  
 }  
   
 sub adhocbutton {   my ($position,$dom,$confname,$settings,$rowtotal) = @_;
     my ($prefix,$num,$field,$visibility) = @_;   my ($css_class,$datatable);
     my %lt = &Apache::lonlocal::texthash(  
                                           show => 'Show details',   my $switchserver = &check_switchserver($dom,$confname);
                                           hide => 'Hide details',  
                                         );   my $itemcount = 1;
     return '<span style="text-decoration:line-through; font-weight: normal;">'.('&nbsp;'x10).  
            '</span>'.('&nbsp;'x2).'<input type="button" id="'.$prefix.$num.'_'.$field.'_vis"'.   if ($position eq 'top') {
            ' value="'.$lt{$visibility}.'" style="height:20px;" '.  
            'onclick="toggleHelpdeskItem('."'$num','$field'".');" />'.('&nbsp;'x2);   my (%checkedon,%checkedoff,%choices,%defaultchecked,@toggles);
 }  
    %choices =
 sub helpsettings_javascript {   &Apache::lonlocal::texthash (
     my ($roles_by_num,$total,$hiddenstr,$formname) = @_;   submitbugs => 'Display &quot;Submit a bug&quot; link?',
     return unless(ref($roles_by_num) eq 'ARRAY');   );
     my %html_js_lt = &Apache::lonlocal::texthash(  
                                           show => 'Show details',   %defaultchecked = ('submitbugs' => 'on');
                                           hide => 'Hide details',  
                                         );   @toggles = ('submitbugs',);
     &html_escape(\%html_js_lt);  
     my $jstext = '    var helproles = Array('."'".join("','",@{$roles_by_num})."'".');'."\n";   foreach my $item (@toggles) {
     return <<"ENDSCRIPT";   if ($defaultchecked{$item} eq 'on') { 
 <script type="text/javascript">   $checkedon{$item} = ' checked="checked" ';
 // <![CDATA[   $checkedoff{$item} = ' ';
    } elsif ($defaultchecked{$item} eq 'off') {
 function reorderHelpRoles(form,item) {   $checkedoff{$item} = ' checked="checked" ';
     var changedVal;   $checkedon{$item} = ' ';
 $jstext   }
     var newpos = 'helproles_${total}_pos';   }
     var maxh = 1 + $total;  
     var current = new Array();   if (ref($settings) eq 'HASH') {
     var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;   foreach my $item (@toggles) {
     if (item == newpos) {   if ($settings->{$item} eq '1') {
         changedVal = newitemVal;   $checkedon{$item} =  ' checked="checked" ';
     } else {   $checkedoff{$item} = ' ';
         changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;   } elsif ($settings->{$item} eq '0') {
         current[newitemVal] = newpos;   $checkedoff{$item} =  ' checked="checked" ';
     }   $checkedon{$item} = ' ';
     for (var i=0; i<helproles.length; i++) {   }
         var elementName = 'helproles_'+helproles[i]+'_pos';   }
         if (elementName != item) {   }
             if (form.elements[elementName]) {  
                 var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;   foreach my $item (@toggles) {
                 current[currVal] = elementName;   $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
             }   $datatable .=  
         }   '<tr'.$css_class.'>
     }   <td><span class="LC_nobreak">'.$choices{$item}.'</span></td>
     var oldVal;   <td><span class="LC_nobreak">&nbsp;</span></td>
     for (var j=0; j<maxh; j++) {   <td class="LC_right_item"><span class="LC_nobreak">
         if (current[j] == undefined) {   <label><input type="radio" name="'.$item.'" '.$checkedon{$item}.' value="1" />'.&mt('Yes').'</label>&nbsp;
             oldVal = j;   <label><input type="radio" name="'.$item.'" '.$checkedoff{$item}.' value="0" />'.&mt('No').'</label>'.
         }   '</span></td>'.
     }   '</tr>';
     if (oldVal < changedVal) {   $itemcount ++;
         for (var k=oldVal+1; k<=changedVal ; k++) {   }
            var elementName = current[k];       
            form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;       } else {
         }       
     } else {        $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
         for (var k=changedVal; k<oldVal; k++) {       
             var elementName = current[k];        $datatable .= '<tr'.$css_class.'>';
             form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;       
         }        if (ref($settings) eq 'HASH') {
     }   if ($settings->{'loginhelpurl'} ne '') {
     return;   my($directory, $filename) = $settings->{'loginhelpurl'} =~ m/(.*\/)(.*)$/;
 }   $datatable .= '<td width="33%"><span class="LC_left_item"><label><a href="'.$settings->{'loginhelpurl'}.'" target="_blank">'.&mt('Custom Login Page Help File In Use').'</a></label></span></td>';
    $datatable .= '<td width="33%"><span class="LC_right_item"><label><input type="checkbox" name="loginhelpurl_del" value="1" />'.&mt('Delete?').'</label></span></td>'
 function helpdeskAccess(num) {   } else {
     var curraccess = null;   $datatable .= '<td width="33%"><span class="LC_left_item"><label>'.&mt('Default Login Page Help File In Use').'</label></span></td>';
     if (document.$formname.elements['helproles_'+num+'_access'].length) {   $datatable .= '<td width="33%"><span class="LC_right_item">&nbsp;</span></td>';
         for (var i=0; i<document.$formname.elements['helproles_'+num+'_access'].length; i++) {   }
             if (document.$formname.elements['helproles_'+num+'_access'][i].checked) {   } else {
                 curraccess = document.$formname.elements['helproles_'+num+'_access'][i].value;   $datatable .= '<td><span class="LC_left_item">&nbsp;</span></td>';
             }   $datatable .= '<td><span class="LC_right_item">&nbsp;</span></td>';
         }   }
     }     
     var shown = Array();        $datatable .= '<td width="33%"><span class="LC_right_item">';
     var hidden = Array();        if ($switchserver) {
     if (curraccess == 'none') {              $datatable .= &mt('Upload to library server: [_1]',$switchserver);
         hidden = Array('$hiddenstr');  
     } else {  
         if (curraccess == 'status') {  
             shown = Array('bystatus');  
             hidden = Array('notinc','notexc');  
         } else {  
             if (curraccess == 'exc') {  
                 shown = Array('notexc');  
                 hidden = Array('notinc','bystatus');  
             }  
             if (curraccess == 'inc') {  
                 shown = Array('notinc');  
                 hidden = Array('notexc','bystatus');  
             }  
             if ((curraccess == 'all') || (curraccess == 'dh') || (curraccess == 'da')) {  
                 hidden = Array('notinc','notexc','bystatus');  
             }  
         }  
     }  
     if (hidden.length > 0) {  
         for (var i=0; i<hidden.length; i++) {  
             if (document.getElementById('helproles_'+num+'_'+hidden[i])) {  
                 document.getElementById('helproles_'+num+'_'+hidden[i]).style.display = 'none';  
             }  
         }  
     }  
     if (shown.length > 0) {  
         for (var i=0; i<shown.length; i++) {  
             if (document.getElementById('helproles_'+num+'_'+shown[i])) {  
                 if (shown[i] == 'privs') {  
                     document.getElementById('helproles_'+num+'_'+shown[i]).style.display = 'block';  
                 } else {  
                     document.getElementById('helproles_'+num+'_'+shown[i]).style.display = 'inline-block';  
                 }  
             }  
         }  
     }  
     return;  
 }  
   
 function toggleHelpdeskItem(num,field) {  
     if (document.getElementById('helproles_'+num+'_'+field)) {  
         if (document.getElementById('helproles_'+num+'_'+field).className.match(/(?:^|\\s)LC_hidden(?!\\S)/)) {  
             document.getElementById('helproles_'+num+'_'+field).className =  
                 document.getElementById('helproles_'+num+'_'+field).className.replace(/(?:^|\\s)LC_hidden(?!\\S)/g ,'');  
             if (document.getElementById('helproles_'+num+'_'+field+'_vis')) {  
                 document.getElementById('helproles_'+num+'_'+field+'_vis').value = '$html_js_lt{hide}';  
             }  
         } else {          } else {
             document.getElementById('helproles_'+num+'_'+field).className += ' LC_hidden';          $datatable .= &mt('Upload Custom Login Page Help File:');
             if (document.getElementById('helproles_'+num+'_'+field+'_vis')) {              $datatable .='<input type="file" name="loginhelpurl" />';
                 document.getElementById('helproles_'+num+'_'+field+'_vis').value = '$html_js_lt{show}';  
             }  
         }          }
     }          $datatable .= '</span></td></tr>';
     return;          
        }
        
        return $datatable;
   
 }  }
   
 // ]]>  
 </script>  
   
 ENDSCRIPT  
 }  
   
 sub helpdeskroles_access {  
     my ($dom,$prefix,$num,$add_class,$current,$accesstypes,$othertitle,  
         $usertypes,$types,$domhelpdesk) = @_;  
     return unless ((ref($accesstypes) eq 'ARRAY') && (ref($domhelpdesk) eq 'HASH'));  
     my %lt = &Apache::lonlocal::texthash(  
                     'rou'    => 'Role usage',  
                     'whi'    => 'Which helpdesk personnel may use this role?',  
                     'all'    => 'All with domain helpdesk or helpdesk assistant role',  
                     'dh'     => 'All with domain helpdesk role',  
                     'da'     => 'All with domain helpdesk assistant role',  
                     'none'   => 'None',  
                     'status' => 'Determined based on institutional status',  
                     'inc'    => 'Include all, but exclude specific personnel',  
                     'exc'    => 'Exclude all, but include specific personnel',  
                   );  
     my %usecheck = (  
                      all => ' checked="checked"',  
                    );  
     my %displaydiv = (  
                       status => 'none',  
                       inc    => 'none',  
                       exc    => 'none',  
                       priv   => 'block',  
                      );  
     my $output;  
     if (ref($current) eq 'HASH') {  
         if (($current->{'access'} ne '') && ($current->{'access'} ne 'all')) {  
             if (grep(/^\Q$current->{access}\E$/,@{$accesstypes})) {  
                 $usecheck{$current->{access}} = $usecheck{'all'};  
                 delete($usecheck{'all'});  
                 if ($current->{access} =~ /^(status|inc|exc)$/) {  
                     my $access = $1;  
                     $displaydiv{$access} = 'inline';  
                 } elsif ($current->{access} eq 'none') {  
                     $displaydiv{'priv'} = 'none';  
                 }  
             }  
         }  
     }  
     $output = '<fieldset id="'.$prefix.$num.'_usage"><legend>'.$lt{'rou'}.'</legend>'.  
               '<p>'.$lt{'whi'}.'</p>';  
     foreach my $access (@{$accesstypes}) {  
         $output .= '<p><label><input type="radio" name="'.$prefix.$num.'_access" value="'.$access.'" '.$usecheck{$access}.  
                    ' onclick="helpdeskAccess('."'$num'".');" />'.  
                    $lt{$access}.'</label>';  
         if ($access eq 'status') {  
             $output .= '<div id="'.$prefix.$num.'_bystatus" style="display:'.$displaydiv{$access}.'">'.  
                        &Apache::lonuserutils::adhoc_status_types($dom,$prefix,$num,$current->{$access},  
                                                                  $othertitle,$usertypes,$types).  
                        '</div>';  
         } elsif (($access eq 'inc') && (keys(%{$domhelpdesk}) > 0)) {  
             $output .= '<div id="'.$prefix.$num.'_notinc" style="display:'.$displaydiv{$access}.'">'.  
                        &Apache::lonuserutils::adhoc_staff($access,$prefix,$num,$current->{$access},$domhelpdesk).  
                        '</div>';  
         } elsif (($access eq 'exc') && (keys(%{$domhelpdesk}) > 0)) {  
             $output .= '<div id="'.$prefix.$num.'_notexc" style="display:'.$displaydiv{$access}.'">'.  
                        &Apache::lonuserutils::adhoc_staff($access,$prefix,$num,$current->{$access},$domhelpdesk).  
                        '</div>';  
         }  
         $output .= '</p>';  
     }  
     $output .= '</fieldset>';  
     return $output;  
 }  
   
 sub radiobutton_prefs {  sub radiobutton_prefs {
     my ($settings,$toggles,$defaultchecked,$choices,$itemcount,$onclick,      my ($settings,$toggles,$defaultchecked,$choices,$itemcount) = @_;
         $additional,$align) = @_;  
     return unless ((ref($toggles) eq 'ARRAY') && (ref($defaultchecked) eq 'HASH') &&      return unless ((ref($toggles) eq 'ARRAY') && (ref($defaultchecked) eq 'HASH') &&
                    (ref($choices) eq 'HASH'));                     (ref($choices) eq 'HASH'));
   
Line 3677  sub radiobutton_prefs { Line 2283  sub radiobutton_prefs {
             }              }
         }          }
     }      }
     if ($onclick) {  
         $onclick = ' onclick="'.$onclick.'"';  
     }  
     foreach my $item (@{$toggles}) {      foreach my $item (@{$toggles}) {
         $css_class = $itemcount%2?' class="LC_odd_row"':'';          $css_class = $itemcount%2?' class="LC_odd_row"':'';
         $datatable .=          $datatable .=
             '<tr'.$css_class.'><td valign="top">'.              '<tr'.$css_class.'><td><span class="LC_nobreak">'.$choices->{$item}.
             '<span class="LC_nobreak">'.$choices->{$item}.              '</span></td>'.
             '</span></td>';              '<td class="LC_right_item"><span class="LC_nobreak">'.
         if ($align eq 'left') {  
             $datatable .= '<td class="LC_left_item">';  
         } else {  
             $datatable .= '<td class="LC_right_item">';  
         }  
         $datatable .=  
             '<span class="LC_nobreak">'.  
             '<label><input type="radio" name="'.              '<label><input type="radio" name="'.
             $item.'" '.$checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').              $item.'" '.$checkedon{$item}.' value="1" />'.&mt('Yes').
             '</label>&nbsp;<label><input type="radio" name="'.$item.'" '.              '</label>&nbsp;<label><input type="radio" name="'.$item.'" '.
             $checkedoff{$item}.' value="0"'.$onclick.' />'.&mt('No').'</label>'.              $checkedoff{$item}.' value="0" />'.&mt('No').'</label>'.
             '</span>'.$additional.              '</span></td>'.
             '</td>'.  
             '</tr>';              '</tr>';
         $itemcount ++;          $itemcount ++;
     }      }
Line 3707  sub radiobutton_prefs { Line 2302  sub radiobutton_prefs {
   
 sub print_coursedefaults {  sub print_coursedefaults {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles);      my ($css_class,$datatable);
     my $itemcount = 1;      my $itemcount = 1;
     my %choices =  &Apache::lonlocal::texthash (  
         uploadquota          => 'Default quota for files uploaded directly to course/community using Course Editor (MB)',  
         anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',  
         coursecredits        => 'Credits can be specified for courses',  
         uselcmath            => 'Math preview uses LON-CAPA previewer (javascript) in place of DragMath (Java)',  
         usejsme              => 'Molecule editor uses JSME (HTML5) in place of JME (Java)',  
         texengine            => 'Default method to display mathematics',  
         postsubmit           => 'Disable submit button/keypress following student submission',  
         canclone             => "People who may clone a course (besides course's owner and coordinators)",  
         mysqltables          => 'Lifetime (s) of "Temporary" MySQL tables (student performance data) on homeserver',  
     );  
     my %staticdefaults = (  
                            anonsurvey_threshold => 10,  
                            uploadquota          => 500,  
                            postsubmit           => 60,  
                            mysqltables          => 172800,  
                          );  
     if ($position eq 'top') {      if ($position eq 'top') {
         %defaultchecked = (          my (%checkedon,%checkedoff,%choices,%defaultchecked,@toggles);
                             'uselcmath'       => 'on',          %choices =
                             'usejsme'         => 'on',              &Apache::lonlocal::texthash (
                             'canclone'        => 'none',                  canuse_pdfforms => 'Course/Community users can create/upload PDF forms',
                           );          );
         @toggles = ('uselcmath','usejsme');          %defaultchecked = ('canuse_pdfforms' => 'off');
         my $deftex = $Apache::lonnet::deftex;          @toggles = ('canuse_pdfforms',);
         if (ref($settings) eq 'HASH') {  
             if ($settings->{'texengine'}) {  
                 if ($settings->{'texengine'} =~ /^(MathJax|mimetex|tth)$/) {  
                     $deftex = $settings->{'texengine'};  
                 }  
             }  
         }  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         my $mathdisp = '<tr'.$css_class.'><td style="vertical-align: top">'.  
                        '<span class="LC_nobreak">'.$choices{'texengine'}.  
                        '</span></td><td class="LC_right_item">'.  
                        '<select name="texengine">'."\n";  
         my %texoptions = (  
                             MathJax  => 'MathJax',  
                             mimetex  => &mt('Convert to Images'),  
                             tth      => &mt('TeX to HTML'),  
                          );  
         foreach my $renderer ('MathJax','mimetex','tth') {  
             my $selected = '';  
             if ($renderer eq $deftex) {  
                 $selected = ' selected="selected"';  
             }  
             $mathdisp .= '<option value="'.$renderer.'"'.$selected.'>'.$texoptions{$renderer}.'</option>'."\n";  
         }  
         $mathdisp .= '</select></td></tr>'."\n";  
         $itemcount ++;  
         ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,          ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
                                                      \%choices,$itemcount);                                                   \%choices,$itemcount);
         $datatable = $mathdisp.$datatable;          $$rowtotal += $itemcount;
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .=  
             '<tr'.$css_class.'><td valign="top">'.  
             '<span class="LC_nobreak">'.$choices{'canclone'}.  
             '</span></td><td class="LC_left_item">';  
         my $currcanclone = 'none';  
         my $onclick;  
         my @cloneoptions = ('none','domain');  
         my %clonetitles = (  
                              none     => 'No additional course requesters',  
                              domain   => "Any course requester in course's domain",  
                              instcode => 'Course requests for official courses ...',  
                           );  
         my (%codedefaults,@code_order,@posscodes);  
         if (&Apache::lonnet::auto_instcode_defaults($dom,\%codedefaults,  
                                                     \@code_order) eq 'ok') {  
             if (@code_order > 0) {  
                 push(@cloneoptions,'instcode');  
                 $onclick = ' onclick="toggleDisplay(this.form,'."'cloneinstcode'".');"';  
             }  
         }  
         if (ref($settings) eq 'HASH') {  
             if ($settings->{'canclone'}) {  
                 if (ref($settings->{'canclone'}) eq 'HASH') {  
                     if (ref($settings->{'canclone'}{'instcode'}) eq 'ARRAY') {  
                         if (@code_order > 0) {  
                             $currcanclone = 'instcode';  
                             @posscodes = @{$settings->{'canclone'}{'instcode'}};  
                         }  
                     }  
                 } elsif ($settings->{'canclone'} eq 'domain') {  
                     $currcanclone = $settings->{'canclone'};  
                 }  
             }  
         }  
         foreach my $option (@cloneoptions) {  
             my ($checked,$additional);  
             if ($currcanclone eq $option) {  
                 $checked = ' checked="checked"';  
             }  
             if ($option eq 'instcode') {  
                 if (@code_order) {  
                     my $show = 'none';  
                     if ($checked) {  
                         $show = 'block';  
                     }  
                     $additional = '<div id="cloneinstcode" style="display:'.$show.'" />'.  
                                   &mt('Institutional codes for new and cloned course have identical:').  
                                   '<br />';  
                     foreach my $item (@code_order) {  
                         my $codechk;  
                         if ($checked) {  
                             if (grep(/^\Q$item\E$/,@posscodes)) {  
                                 $codechk = ' checked="checked"';  
                             }  
                         }  
                         $additional .= '<label>'.  
                                        '<input type="checkbox" name="clonecode" value="'.$item.'"'.$codechk.' />'.  
                                        $item.'</label>';  
                     }  
                     $additional .= ('&nbsp;'x2).'('.&mt('check as many as needed').')</div>';  
                 }  
             }  
             $datatable .=  
                 '<span class="LC_nobreak"><label><input type="radio" name="canclone"'.$checked.  
                 ' value="'.$option.'"'.$onclick.' />'.$clonetitles{$option}.  
                 '</label>&nbsp;'.$additional.'</span><br />';  
         }  
         $datatable .= '</td>'.  
                       '</tr>';  
         $itemcount ++;  
     } else {      } else {
         $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';          $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
         my ($currdefresponder,%defcredits,%curruploadquota,%deftimeout,%currmysql);          my %choices =
         my $currusecredits = 0;              &Apache::lonlocal::texthash (
         my $postsubmitclient = 1;                  anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',
         my @types = ('official','unofficial','community','textbook');          );
           my $currdefresponder;
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             $currdefresponder = $settings->{'anonsurvey_threshold'};              $currdefresponder = $settings->{'anonsurvey_threshold'};
             if (ref($settings->{'uploadquota'}) eq 'HASH') {  
                 foreach my $type (keys(%{$settings->{'uploadquota'}})) {  
                     $curruploadquota{$type} = $settings->{'uploadquota'}{$type};  
                 }  
             }  
             if (ref($settings->{'coursecredits'}) eq 'HASH') {  
                 foreach my $type (@types) {  
                     next if ($type eq 'community');  
                     $defcredits{$type} = $settings->{'coursecredits'}->{$type};  
                     if ($defcredits{$type} ne '') {  
                         $currusecredits = 1;  
                     }  
                 }  
             }  
             if (ref($settings->{'postsubmit'}) eq 'HASH') {  
                 if ($settings->{'postsubmit'}->{'client'} eq 'off') {  
                     $postsubmitclient = 0;  
                     foreach my $type (@types) {  
                         $deftimeout{$type} = $staticdefaults{'postsubmit'};  
                     }  
                 } else {  
                     foreach my $type (@types) {  
                         if (ref($settings->{'postsubmit'}->{'timeout'}) eq 'HASH') {  
                             if ($settings->{'postsubmit'}->{'timeout'}->{$type} =~ /^\d+$/) {  
                                 $deftimeout{$type} = $settings->{'postsubmit'}->{'timeout'}->{$type};  
                             } else {  
                                 $deftimeout{$type} = $staticdefaults{'postsubmit'};  
                             }  
                         } else {  
                             $deftimeout{$type} = $staticdefaults{'postsubmit'};  
                         }  
                     }  
                 }  
             } else {  
                 foreach my $type (@types) {  
                     $deftimeout{$type} = $staticdefaults{'postsubmit'};  
                 }  
             }  
             if (ref($settings->{'mysqltables'}) eq 'HASH') {  
                 foreach my $type (keys(%{$settings->{'mysqltables'}})) {  
                     $currmysql{$type} = $settings->{'mysqltables'}{$type};  
                 }  
             } else {  
                 foreach my $type (@types) {  
                     $currmysql{$type} = $staticdefaults{'mysqltables'};  
                 }  
             }  
         } else {  
             foreach my $type (@types) {  
                 $deftimeout{$type} = $staticdefaults{'postsubmit'};  
             }  
         }          }
         if (!$currdefresponder) {          if (!$currdefresponder) {
             $currdefresponder = $staticdefaults{'anonsurvey_threshold'};              $currdefresponder = 10;
         } elsif ($currdefresponder < 1) {          } elsif ($currdefresponder < 1) {
             $currdefresponder = 1;              $currdefresponder = 1;
         }          }
         foreach my $type (@types) {  
             if ($curruploadquota{$type} eq '') {  
                 $curruploadquota{$type} = $staticdefaults{'uploadquota'};  
             }  
         }  
         $datatable .=          $datatable .=
                 '<tr'.$css_class.'><td><span class="LC_nobreak">'.                 '<tr'.$css_class.'><td><span class="LC_nobreak">'.$choices{'anonsurvey_threshold'}.
                 $choices{'anonsurvey_threshold'}.  
                 '</span></td>'.                  '</span></td>'.
                 '<td class="LC_right_item"><span class="LC_nobreak">'.                  '<td class="LC_right_item"><span class="LC_nobreak">'.
                 '<input type="text" name="anonsurvey_threshold"'.                  '<input type="text" name="anonsurvey_threshold"'.
                 ' value="'.$currdefresponder.'" size="5" /></span>'.                  ' value="'.$currdefresponder.'" size="5" /></span>'.
                 '</td></tr>'."\n";                  '</td></tr>';
         $itemcount ++;  
         $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';  
         $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.  
                       $choices{'uploadquota'}.  
                       '</span></td>'.  
                       '<td align="right" class="LC_right_item">'.  
                       '<table><tr>';  
         foreach my $type (@types) {  
             $datatable .= '<td align="center">'.&mt($type).'<br />'.  
                            '<input type="text" name="uploadquota_'.$type.'"'.  
                            ' value="'.$curruploadquota{$type}.'" size="5" /></td>';  
         }  
         $datatable .= '</tr></table></td></tr>'."\n";  
         $itemcount ++;  
         my $onclick = "toggleDisplay(this.form,'credits');";  
         my $display = 'none';  
         if ($currusecredits) {  
             $display = 'block';  
         }  
         my $additional = '<div id="credits" style="display: '.$display.'">'.  
                          '<i>'.&mt('Default credits').'</i><br /><table><tr>';  
         foreach my $type (@types) {  
             next if ($type eq 'community');  
             $additional .= '<td align="center">'.&mt($type).'<br />'.  
                            '<input type="text" name="'.$type.'_credits"'.  
                            ' value="'.$defcredits{$type}.'" size="3" /></td>';  
         }  
         $additional .= '</tr></table></div>'."\n";  
         %defaultchecked = ('coursecredits' => 'off');  
         @toggles = ('coursecredits');  
         my $current = {  
                         'coursecredits' => $currusecredits,  
                       };  
         (my $table,$itemcount) =  
             &radiobutton_prefs($current,\@toggles,\%defaultchecked,  
                                \%choices,$itemcount,$onclick,$additional,'left');  
         $datatable .= $table;  
         $onclick = "toggleDisplay(this.form,'studentsubmission');";  
         my $display = 'none';  
         if ($postsubmitclient) {  
             $display = 'block';  
         }  
         $additional = '<div id="studentsubmission" style="display: '.$display.'">'.  
                       &mt('Number of seconds submit is disabled').'<br />'.  
                       '<i>'.&mt('Enter 0 to remain disabled until page reload.').'</i><br />'.  
                       '<table><tr>';  
         foreach my $type (@types) {  
             $additional .= '<td align="center">'.&mt($type).'<br />'.  
                            '<input type="text" name="'.$type.'_timeout" value="'.  
                            $deftimeout{$type}.'" size="5" /></td>';  
         }  
         $additional .= '</tr></table></div>'."\n";  
         %defaultchecked = ('postsubmit' => 'on');  
         @toggles = ('postsubmit');  
         $current = {  
                        'postsubmit' => $postsubmitclient,  
                    };  
         ($table,$itemcount) =  
             &radiobutton_prefs($current,\@toggles,\%defaultchecked,  
                                \%choices,$itemcount,$onclick,$additional,'left');  
         $datatable .= $table;  
         $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';  
         $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.  
                       $choices{'mysqltables'}.  
                       '</span></td>'.  
                       '<td align="right" class="LC_right_item">'.  
                       '<table><tr>';  
         foreach my $type (@types) {  
             $datatable .= '<td align="center">'.&mt($type).'<br />'.  
                            '<input type="text" name="mysqltables_'.$type.'"'.  
                            ' value="'.$currmysql{$type}.'" size="8" /></td>';  
         }  
         $datatable .= '</tr></table></td></tr>'."\n";  
         $itemcount ++;  
   
     }  
     $$rowtotal += $itemcount;  
     return $datatable;  
 }  
   
 sub print_selfenrollment {  
     my ($position,$dom,$settings,$rowtotal) = @_;  
     my ($css_class,$datatable);  
     my $itemcount = 1;  
     my @types = ('official','unofficial','community','textbook');  
     if (($position eq 'top') || ($position eq 'middle')) {  
         my ($rowsref,$titlesref) = &Apache::lonuserutils::get_selfenroll_titles();  
         my %descs = &Apache::lonuserutils::selfenroll_default_descs();  
         my @rows;  
         my $key;  
         if ($position eq 'top') {  
             $key = 'admin';   
             if (ref($rowsref) eq 'ARRAY') {  
                 @rows = @{$rowsref};  
             }  
         } elsif ($position eq 'middle') {  
             $key = 'default';  
             @rows = ('types','registered','approval','limit');  
         }  
         foreach my $row (@rows) {  
             if (defined($titlesref->{$row})) {  
                 $itemcount ++;  
                 $css_class = $itemcount%2?' class="LC_odd_row"':'';  
                 $datatable .= '<tr'.$css_class.'>'.  
                               '<td>'.$titlesref->{$row}.'</td>'.  
                               '<td class="LC_left_item">'.  
                               '<table><tr>';  
                 my (%current,%currentcap);  
                 if (ref($settings) eq 'HASH') {  
                     if (ref($settings->{$key}) eq 'HASH') {  
                         foreach my $type (@types) {  
                             if (ref($settings->{$key}->{$type}) eq 'HASH') {  
                                 $current{$type} = $settings->{$key}->{$type}->{$row};  
                             }  
                             if (($row eq 'limit') && ($key eq 'default')) {  
                                 if (ref($settings->{$key}->{$type}) eq 'HASH') {  
                                     $currentcap{$type} = $settings->{$key}->{$type}->{'cap'};  
                                 }  
                             }  
                         }  
                     }  
                 }  
                 my %roles = (  
                              '0' => &Apache::lonnet::plaintext('dc'),  
                             );   
               
                 foreach my $type (@types) {  
                     unless (($row eq 'registered') && ($key eq 'default')) {  
                         $datatable .= '<th>'.&mt($type).'</th>';  
                     }  
                 }  
                 unless (($row eq 'registered') && ($key eq 'default')) {  
                     $datatable .= '</tr><tr>';  
                 }  
                 foreach my $type (@types) {  
                     if ($type eq 'community') {  
                         $roles{'1'} = &mt('Community personnel');  
                     } else {  
                         $roles{'1'} = &mt('Course personnel');  
                     }  
                     $datatable .= '<td style="vertical-align: top">';  
                     if ($position eq 'top') {  
                         my %checked;  
                         if ($current{$type} eq '0') {  
                             $checked{'0'} = ' checked="checked"';  
                         } else {  
                             $checked{'1'} = ' checked="checked"';  
                         }  
                         foreach my $role ('1','0') {  
                             $datatable .= '<span class="LC_nobreak"><label>'.  
                                           '<input type="radio" name="selfenrolladmin_'.$row.'_'.$type.'" '.  
                                           'value="'.$role.'"'.$checked{$role}.' />'.  
                                           $roles{$role}.'</label></span> ';  
                         }  
                     } else {  
                         if ($row eq 'types') {  
                             my %checked;  
                             if ($current{$type} =~ /^(all|dom)$/) {  
                                 $checked{$1} = ' checked="checked"';  
                             } else {  
                                 $checked{''} = ' checked="checked"';  
                             }  
                             foreach my $val ('','dom','all') {  
                                 $datatable .= '<span class="LC_nobreak"><label>'.  
                                               '<input type ="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.  
                                               'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';  
                             }  
                         } elsif ($row eq 'registered') {  
                             my %checked;  
                             if ($current{$type} eq '1') {  
                                 $checked{'1'} = ' checked="checked"';  
                             } else {  
                                 $checked{'0'} = ' checked="checked"';  
                             }  
                             foreach my $val ('0','1') {  
                                 $datatable .= '<span class="LC_nobreak"><label>'.  
                                               '<input type ="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.  
                                               'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';  
                             }  
                         } elsif ($row eq 'approval') {  
                             my %checked;  
                             if ($current{$type} =~ /^([12])$/) {  
                                 $checked{$1} = ' checked="checked"';  
                             } else {  
                                 $checked{'0'} = ' checked="checked"';  
                             }  
                             for my $val (0..2) {  
                                 $datatable .= '<span class="LC_nobreak"><label>'.  
                                               '<input type="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.  
                                               'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';  
                             }  
                         } elsif ($row eq 'limit') {  
                             my %checked;  
                             if ($current{$type} =~ /^(allstudents|selfenrolled)$/) {  
                                 $checked{$1} = ' checked="checked"';  
                             } else {  
                                 $checked{'none'} = ' checked="checked"';  
                             }  
                             my $cap;  
                             if ($currentcap{$type} =~ /^\d+$/) {  
                                 $cap = $currentcap{$type};  
                             }  
                             foreach my $val ('none','allstudents','selfenrolled') {  
                                 $datatable .= '<span class="LC_nobreak"><label>'.  
                                               '<input type="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.  
                                               'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';  
                             }  
                             $datatable .= '<br />'.  
                                           '<span class="LC_nobreak">'.&mt('Maximum allowed: ').  
                                           '<input type="text" name="selfenrolldefault_cap_'.$type.'" size = "5" value="'.$cap.'" />'.  
                                           '</span>';   
                         }  
                     }  
                     $datatable .= '</td>';  
                 }  
                 $datatable .= '</tr>';  
             }  
             $datatable .= '</table></td></tr>';  
         }  
     } elsif ($position eq 'bottom') {  
         $datatable .= &print_validation_rows('selfenroll',$dom,$settings,\$itemcount);  
     }  
     $$rowtotal += $itemcount;  
     return $datatable;  
 }  
   
 sub print_validation_rows {  
     my ($caller,$dom,$settings,$rowtotal) = @_;  
     my ($itemsref,$namesref,$fieldsref);  
     if ($caller eq 'selfenroll') {   
         ($itemsref,$namesref,$fieldsref) = &Apache::lonuserutils::selfenroll_validation_types();  
     } elsif ($caller eq 'requestcourses') {  
         ($itemsref,$namesref,$fieldsref) = &Apache::loncoursequeueadmin::requestcourses_validation_types();  
     }  
     my %currvalidation;  
     if (ref($settings) eq 'HASH') {  
         if (ref($settings->{'validation'}) eq 'HASH') {  
             %currvalidation = %{$settings->{'validation'}};  
         }  
     }  
     my $datatable;  
     my $itemcount = 0;  
     foreach my $item (@{$itemsref}) {  
         my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';  
         $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.  
                       $namesref->{$item}.  
                       '</span></td>'.  
                       '<td class="LC_left_item">';  
         if (($item eq 'url') || ($item eq 'button')) {  
             $datatable .= '<span class="LC_nobreak">'.  
                           '<input type="text" name="'.$caller.'_validation_'.$item.'"'.  
                           ' value="'.$currvalidation{$item}.'" size="50" /></span>';  
         } elsif ($item eq 'fields') {  
             my @currfields;  
             if (ref($currvalidation{$item}) eq 'ARRAY') {  
                 @currfields = @{$currvalidation{$item}};  
             }  
             foreach my $field (@{$fieldsref}) {  
                 my $check = '';  
                 if (grep(/^\Q$field\E$/,@currfields)) {  
                     $check = ' checked="checked"';  
                 }  
                 $datatable .= '<span class="LC_nobreak"><label>'.  
                               '<input type="checkbox" name="'.$caller.'_validation_fields"'.  
                               ' value="'.$field.'"'.$check.' />'.$field.  
                               '</label></span> ';  
             }  
         } elsif ($item eq 'markup') {  
             $datatable .= '<textarea name="'.$caller.'_validation_markup" cols="50" rows="5">'.  
                            $currvalidation{$item}.  
                               '</textarea>';  
         }  
         $datatable .= '</td></tr>'."\n";  
         if (ref($rowtotal)) {  
             $itemcount ++;  
         }  
     }  
     if ($caller eq 'requestcourses') {  
         my %currhash;  
         if (ref($settings) eq 'HASH') {  
             if (ref($settings->{'validation'}) eq 'HASH') {  
                 if ($settings->{'validation'}{'dc'} ne '') {  
                     $currhash{$settings->{'validation'}{'dc'}} = 1;  
                 }  
             }  
         }  
         my $numinrow = 2;  
         my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',  
                                                        'validationdc',%currhash);  
         my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';  
         $datatable .= '<tr'.$css_class.'><td>';  
         if ($numdc > 1) {  
             $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)');  
         } else {  
             $datatable .=  &mt('Course creation processed as: ');  
         }  
         $datatable .= '</td><td class="LC_left_item">'.$dctable.'</td></tr>';  
         $itemcount ++;  
     }  
     if (ref($rowtotal)) {  
         $$rowtotal += $itemcount;  
     }  
     return $datatable;  
 }  
   
 sub print_passwords {  
     my ($position,$dom,$confname,$settings,$rowtotal) = @_;  
     my ($datatable,$css_class);  
     my $itemcount = 0;  
     my %titles = &Apache::lonlocal::texthash (  
         captcha        => '"Forgot Password" CAPTCHA validation',  
         link           => 'Reset link expiration (hours)',  
         case           => 'Case-sensitive usernames/e-mail',  
         prelink        => 'Information required (form 1)',  
         postlink       => 'Information required (form 2)',  
         emailsrc       => 'LON-CAPA e-mail address type(s)',  
         customtext     => 'Domain specific text (HTML)',  
         intauth_cost   => 'Encryption cost for bcrypt (positive integer)',  
         intauth_check  => 'Check bcrypt cost if authenticated',  
         intauth_switch => 'Existing crypt-based switched to bcrypt on authentication',  
         permanent      => 'Permanent e-mail address',  
         critical       => 'Critical notification address',  
         notify         => 'Notification address',  
         min            => 'Minimum password length',  
         max            => 'Maximum password length',  
         chars          => 'Required characters',  
         numsaved       => 'Number of previous passwords to save and disallow reuse',  
     );  
     if ($position eq 'top') {  
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
         my $shownlinklife = 2;  
         my $prelink = 'both';  
         my (%casesens,%postlink,%emailsrc,$nostdtext,$customurl);  
         if (ref($settings) eq 'HASH') {  
             if ($settings->{resetlink} =~ /^\d+(|\.\d*)$/) {  
                 $shownlinklife = $settings->{resetlink};  
             }  
             if (ref($settings->{resetcase}) eq 'ARRAY') {  
                 map { $casesens{$_} = 1; } (@{$settings->{resetcase}});  
             }  
             if ($settings->{resetprelink} =~ /^(both|either)$/) {  
                 $prelink = $settings->{resetprelink};  
             }  
             if (ref($settings->{resetpostlink}) eq 'HASH') {  
                 %postlink = %{$settings->{resetpostlink}};  
             }  
             if (ref($settings->{resetemail}) eq 'ARRAY') {  
                 map { $emailsrc{$_} = 1; } (@{$settings->{resetemail}});  
             }  
             if ($settings->{resetremove}) {  
                 $nostdtext = 1;  
             }  
             if ($settings->{resetcustom}) {  
                 $customurl = $settings->{resetcustom};  
             }  
         } else {  
             if (ref($types) eq 'ARRAY') {  
                 foreach my $item (@{$types}) {  
                     $casesens{$item} = 1;  
                     $postlink{$item} = ['username','email'];  
                 }  
             }  
             $casesens{'default'} = 1;  
             $postlink{'default'} = ['username','email'];  
             $prelink = 'both';  
             %emailsrc = (  
                           permanent => 1,  
                           critical  => 1,  
                           notify    => 1,  
             );  
         }  
         $datatable = &captcha_choice('passwords',$settings,$$rowtotal);  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'link'}.'</td>'.  
                       '<td class="LC_left_item">'.  
                       '<input type="textbox" value="'.$shownlinklife.'" '.  
                       'name="passwords_link" size="3" /></td></tr>';  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'case'}.'</td>'.  
                       '<td class="LC_left_item">';  
         if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {  
             foreach my $item (@{$types}) {  
                 my $checkedcase;  
                 if ($casesens{$item}) {  
                     $checkedcase = ' checked="checked"';  
                 }  
                 $datatable .= '<span class="LC_nobreak"><label>'.  
                               '<input type="checkbox" name="passwords_case_sensitive" value="'.  
                               $item.'"'.$checkedcase.' />'.$usertypes->{$item}.'</label>'.  
                               '</span>&nbsp;&nbsp; ';  
             }  
         }  
         my $checkedcase;  
         if ($casesens{'default'}) {  
             $checkedcase = ' checked="checked"';  
         }  
         $datatable .= '<span class="LC_nobreak"><label><input type="checkbox" '.  
                       'name="passwords_case_sensitive" value="default"'.$checkedcase.' />'.  
                       $othertitle.'</label></span></td>';  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         my %checkedpre = (  
                              both => ' checked="checked"',  
                              either => '',  
                          );  
         if ($prelink eq 'either') {  
             $checkedpre{either} = ' checked="checked"';  
             $checkedpre{both} = '';  
         }  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'prelink'}.'</td>'.  
                       '<td class="LC_left_item"><span class="LC_nobreak">'.  
                       '<label><input type="radio" name="passwords_prelink" value="both"'.$checkedpre{'both'}.' />'.  
                       &mt('Both username and e-mail address').'</label></span>&nbsp;&nbsp; '.  
                       '<span class="LC_nobreak"><label>'.  
                       '<input type="radio" name="passwords_prelink" value="either"'.$checkedpre{'either'}.' />'.  
                       &mt('Either username or e-mail address').'</label></span></td></tr>';  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'postlink'}.'</td>'.  
                       '<td class="LC_left_item">';  
         my %postlinked;  
         if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {  
             foreach my $item (@{$types}) {  
                 undef(%postlinked);  
                 $datatable .= '<fieldset style="display: inline-block;">'.  
                               '<legend>'.$usertypes->{$item}.'</legend>';  
                 if (ref($postlink{$item}) eq 'ARRAY') {  
                     map { $postlinked{$_} = 1; } (@{$postlink{$item}});  
                 }  
                 foreach my $field ('email','username') {  
                     my $checked;  
                     if ($postlinked{$field}) {  
                         $checked = ' checked="checked"';  
                     }  
                     $datatable .= '<span class="LC_nobreak"><label>'.  
                                   '<input type="checkbox" name="passwords_postlink_'.$item.'" value="'.  
                                   $field.'"'.$checked.' />'.$field.'</label>'.  
                                   '<span>&nbsp;&nbsp; ';  
                 }  
                 $datatable .= '</fieldset>';  
             }  
         }  
         if (ref($postlink{'default'}) eq 'ARRAY') {  
             map { $postlinked{$_} = 1; } (@{$postlink{'default'}});  
         }  
         $datatable .= '<fieldset style="display: inline-block;">'.  
                       '<legend>'.$othertitle.'</legend>';  
         foreach my $field ('email','username') {  
             my $checked;  
             if ($postlinked{$field}) {  
                 $checked = ' checked="checked"';  
             }  
             $datatable .= '<span class="LC_nobreak"><label>'.  
                           '<input type="checkbox" name="passwords_postlink_default" value="'.  
                           $field.'"'.$checked.' />'.$field.'</label>'.  
                           '<span>&nbsp;&nbsp; ';  
         }  
         $datatable .= '</fieldset></td></tr>';  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'emailsrc'}.'</td>'.  
                       '<td class="LC_left_item">';  
         foreach my $type ('permanent','critical','notify') {  
             my $checkedemail;  
             if ($emailsrc{$type}) {  
                 $checkedemail = ' checked="checked"';  
             }  
             $datatable .= '<span class="LC_nobreak"><label>'.  
                           '<input type="checkbox" name="passwords_emailsrc" value="'.  
                           $type.'"'.$checkedemail.' />'.$titles{$type}.'</label>'.  
                           '<span>&nbsp;&nbsp; ';  
         }  
         $datatable .= '</td></tr>';  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         my $switchserver = &check_switchserver($dom,$confname);  
         my ($showstd,$noshowstd);  
         if ($nostdtext) {  
             $noshowstd = ' checked="checked"';  
         } else {  
             $showstd = ' checked="checked"';  
         }  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'customtext'}.'</td>'.  
                       '<td class="LC_left_item"><span class="LC_nobreak">'.  
                       &mt('Retain standard text:').  
                       '<label><input type="radio" name="passwords_stdtext" value="1"'.$showstd.' />'.  
                       &mt('Yes').'</label>'.'&nbsp;'.  
                       '<label><input type="radio" name="passwords_stdtext" value="0"'.$noshowstd.' />'.  
                       &mt('No').'</label></span><br />'.  
                       '<span class="LC_fontsize_small">'.  
                       &mt('(If you use the same account ...  reset a password from this page.)').'</span><br /><br />'.  
                       &mt('Include custom text:');  
         if ($customurl) {  
             my $link =  &Apache::loncommon::modal_link($customurl,&mt('custom text'),600,500,  
                                                        undef,undef,undef,undef,'background-color:#ffffff');  
             $datatable .= '<span class="LC_nobreak">&nbsp;'.$link.  
                           '<label><input type="checkbox" name="passwords_custom_del"'.  
                           ' value="1" />'.&mt('Delete?').'</label></span>'.  
                           ' <span class="LC_nobreak">&nbsp;'.&mt('Replace:').'</span>';  
         }  
         if ($switchserver) {  
             $datatable .= '<span class="LC_nobreak">&nbsp;'.&mt('Upload to library server: [_1]',$switchserver).'</span>';  
         } else {  
             $datatable .='<span class="LC_nobreak">&nbsp;'.  
                          '<input type="file" name="passwords_customfile" /></span>';  
         }  
         $datatable .= '</td></tr>';  
     } elsif ($position eq 'middle') {  
         my %domconf = &Apache::lonnet::get_dom('configuration',['defaults'],$dom);  
         my @items = ('intauth_cost','intauth_check','intauth_switch');  
         my %defaults;  
         if (ref($domconf{'defaults'}) eq 'HASH') {  
             %defaults = %{$domconf{'defaults'}};  
             if ($defaults{'intauth_cost'} !~ /^\d+$/) {  
                 $defaults{'intauth_cost'} = 10;  
             }  
             if ($defaults{'intauth_check'} !~ /^(0|1|2)$/) {  
                 $defaults{'intauth_check'} = 0;  
             }  
             if ($defaults{'intauth_switch'} !~ /^(0|1|2)$/) {  
                 $defaults{'intauth_switch'} = 0;  
             }  
         } else {  
             %defaults = (  
                           'intauth_cost'   => 10,  
                           'intauth_check'  => 0,  
                           'intauth_switch' => 0,  
                         );  
         }  
         foreach my $item (@items) {  
             if ($itemcount%2) {  
                 $css_class = '';  
             } else {  
                 $css_class = ' class="LC_odd_row" ';  
             }  
             $datatable .= '<tr'.$css_class.'>'.  
                           '<td><span class="LC_nobreak">'.$titles{$item}.  
                           '</span></td><td class="LC_left_item" colspan="3">';  
             if ($item eq 'intauth_switch') {  
                 my @options = (0,1,2);  
                 my %optiondesc = &Apache::lonlocal::texthash (  
                                    0 => 'No',  
                                    1 => 'Yes',  
                                    2 => 'Yes, and copy existing passwd file to passwd.bak file',  
                                  );  
                 $datatable .= '<table width="100%">';  
                 foreach my $option (@options) {  
                     my $checked = ' ';  
                     if ($defaults{$item} eq $option) {  
                         $checked = ' checked="checked"';  
                     }  
                     $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.  
                                   '<label><input type="radio" name="'.$item.  
                                   '" value="'.$option.'"'.$checked.' />'.  
                                   $optiondesc{$option}.'</label></span></td></tr>';  
                 }  
                 $datatable .= '</table>';  
             } elsif ($item eq 'intauth_check') {  
                 my @options = (0,1,2);  
                 my %optiondesc = &Apache::lonlocal::texthash (  
                                    0 => 'No',  
                                    1 => 'Yes, allow login then update passwd file using default cost (if higher)',  
                                    2 => 'Yes, disallow login if stored cost is less than domain default',  
                                  );  
                 $datatable .= '<table width="100%">';  
                 foreach my $option (@options) {  
                     my $checked = ' ';  
                     my $onclick;  
                     if ($defaults{$item} eq $option) {  
                         $checked = ' checked="checked"';  
                     }  
                     if ($option == 2) {  
                         $onclick = ' onclick="javascript:warnIntAuth(this);"';  
                     }  
                     $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.  
                                   '<label><input type="radio" name="'.$item.  
                                   '" value="'.$option.'"'.$checked.$onclick.' />'.  
                                   $optiondesc{$option}.'</label></span></td></tr>';  
                 }  
                 $datatable .= '</table>';  
             } else {  
                 $datatable .= '<input type="text" name="'.$item.'" value="'.  
                               $defaults{$item}.'" size="3" onblur="javascript:warnIntAuth(this);" />';  
             }  
             $datatable .= '</td></tr>';  
             $itemcount ++;  
         }  
     } elsif ($position eq 'lower') {  
         my ($min,$max,%chars,$numsaved);  
         $min = $Apache::lonnet::passwdmin;  
         if (ref($settings) eq 'HASH') {  
             if ($settings->{min}) {  
                 $min = $settings->{min};  
             }  
             if ($settings->{max}) {  
                 $max = $settings->{max};  
             }  
             if (ref($settings->{chars}) eq 'ARRAY') {  
                 map { $chars{$_} = 1; } (@{$settings->{chars}});  
             }  
             if ($settings->{numsaved}) {  
                 $numsaved = $settings->{numsaved};  
             }  
         }  
         my %rulenames = &Apache::lonlocal::texthash(  
                                                      uc => 'At least one upper case letter',  
                                                      lc => 'At least one lower case letter',  
                                                      num => 'At least one number',  
                                                      spec => 'At least one non-alphanumeric',  
                                                    );  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'min'}.'</td>'.  
                       '<td class="LC_left_item"><span class="LC_nobreak">'.  
                       '<input type="text" name="passwords_min" value="'.$min.'" size="3" '.  
                       'onblur="javascript:warnIntPass(this);" />'.  
                       '<span class="LC_fontsize_small"> '.&mt('(Enter an integer: 7 or larger)').'</span>'.  
                       '</span></td></tr>';  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'max'}.'</td>'.  
                       '<td class="LC_left_item"><span class="LC_nobreak">'.  
                       '<input type="text" name="passwords_max" value="'.$max.'" size="3" '.  
                       'onblur="javascript:warnIntPass(this);" />'.  
                       '<span class="LC_fontsize_small"> '.&mt('(Leave blank for no maximum)').'</span>'.  
                       '</span></td></tr>';  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'chars'}.'<br />'.  
                       '<span class="LC_nobreak LC_fontsize_small">'.&mt('(Leave unchecked if not required)').  
                       '</span></td>';  
         my $numinrow = 2;  
         my @possrules = ('uc','lc','num','spec');  
         $datatable .= '<td class="LC_left_item"><table>';  
         for (my $i=0; $i<@possrules; $i++) {  
             my ($rem,$checked);  
             if ($chars{$possrules[$i]}) {  
                 $checked = ' checked="checked"';  
             }  
             $rem = $i%($numinrow);  
             if ($rem == 0) {  
                 if ($i > 0) {  
                     $datatable .= '</tr>';  
                 }  
                 $datatable .= '<tr>';  
             }  
             $datatable .= '<td><span class="LC_nobreak"><label>'.  
                           '<input type="checkbox" name="passwords_chars" value="'.$possrules[$i].'"'.$checked.' />'.  
                           $rulenames{$possrules[$i]}.'</label></span></td>';  
         }  
         my $rem = @possrules%($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 .='</table></td></tr>';  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'numsaved'}.'</td>'.  
                       '<td class="LC_left_item"><span class="LC_nobreak">'.  
                       '<input type="text" name="passwords_numsaved" value="'.$numsaved.'" size="3" '.  
                       'onblur="javascript:warnIntPass(this);" />'.  
                       '<span class="LC_fontsize_small"> '.&mt('(Leave blank to not save previous passwords)').'</span>'.  
                       '</span></td></tr>';  
     } else {  
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
         my %ownerchg = (  
                           by  => {},  
                           for => {},  
                        );  
         my %ownertitles = &Apache::lonlocal::texthash (  
                             by  => 'Course owner status(es) allowed',  
                             for => 'Student status(es) allowed',  
                           );  
         if (ref($settings) eq 'HASH') {  
             if (ref($settings->{crsownerchg}) eq 'HASH') {  
                 if (ref($settings->{crsownerchg}{'by'}) eq 'ARRAY') {  
                     map { $ownerchg{by}{$_} = 1; } (@{$settings->{crsownerchg}{'by'}});  
                 }  
                 if (ref($settings->{crsownerchg}{'for'}) eq 'ARRAY') {  
                     map { $ownerchg{for}{$_} = 1; } (@{$settings->{crsownerchg}{'for'}});  
                 }  
             }  
         }  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr '.$css_class.'>'.  
                       '<td>'.  
                       &mt('Requirements').'<ul>'.  
                       '<li>'.&mt("Course 'type' is not a Community").'</li>'.  
                       '<li>'.&mt('User is Course Coordinator and also course owner').'</li>'.  
                       '<li>'.&mt("Student's only active roles are student role(s) in course(s) owned by this user").'</li>'.  
                       '<li>'.&mt('User, course, and student share same domain').'</li>'.  
                       '</ul>'.  
                       '</td>'.  
                       '<td class="LC_left_item">';  
         foreach my $item ('by','for') {  
             $datatable .= '<fieldset style="display: inline-block;">'.  
                           '<legend>'.$ownertitles{$item}.'</legend>';  
             if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {  
                 foreach my $type (@{$types}) {  
                     my $checked;  
                     if ($ownerchg{$item}{$type}) {  
                         $checked = ' checked="checked"';  
                     }  
                     $datatable .= '<span class="LC_nobreak"><label>'.  
                                   '<input type="checkbox" name="passwords_crsowner_'.$item.'" value="'.  
                                   $type.'"'.$checked.' />'.$usertypes->{$type}.'</label>'.  
                                   '</span>&nbsp;&nbsp; ';  
                 }  
             }  
             my $checked;  
             if ($ownerchg{$item}{'default'}) {  
                 $checked = ' checked="checked"';  
             }  
             $datatable .= '<span class="LC_nobreak"><label><input type="checkbox" '.  
                           'name="passwords_crsowner_'.$item.'" value="default"'.$checked.' />'.  
                           $othertitle.'</label></span></fieldset>';  
         }  
         $datatable .= '</td></tr>';  
     }      }
     return $datatable;      return $datatable;
 }  }
Line 4653  sub print_usersessions { Line 2355  sub print_usersessions {
     if ($position eq 'top') {      if ($position eq 'top') {
         if (keys(%serverhomes) > 1) {          if (keys(%serverhomes) > 1) {
             my %spareid = &current_offloads_to($dom,$settings,\%servers);              my %spareid = &current_offloads_to($dom,$settings,\%servers);
             my ($curroffloadnow,$curroffloadoth);              $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$rowtotal);
             if (ref($settings) eq 'HASH') {  
                 if (ref($settings->{'offloadnow'}) eq 'HASH') {  
                     $curroffloadnow = $settings->{'offloadnow'};  
                 }  
                 if (ref($settings->{'offloadoth'}) eq 'HASH') {  
                     $curroffloadoth = $settings->{'offloadoth'};  
                 }  
             }  
             my $other_insts = scalar(keys(%by_location));  
             $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,  
                                       $other_insts,$curroffloadnow,$curroffloadoth,$rowtotal);  
         } else {          } else {
             $datatable .= '<tr'.$css_class.'><td colspan="2">'.              $datatable .= '<tr'.$css_class.'><td colspan="2">'.
                           &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.');                            &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.');
Line 4914  sub current_offloads_to { Line 2605  sub current_offloads_to {
 }  }
   
 sub spares_row {  sub spares_row {
     my ($dom,$servers,$spareid,$serverhomes,$altids,$other_insts,      my ($dom,$servers,$spareid,$serverhomes,$altids,$rowtotal) = @_;
         $curroffloadnow,$curroffloadoth,$rowtotal) = @_;  
     my $css_class;      my $css_class;
     my $numinrow = 4;      my $numinrow = 4;
     my $itemcount = 1;      my $itemcount = 1;
Line 4935  sub spares_row { Line 2625  sub spares_row {
                 }                  }
             }              }
             next unless (ref($spareid->{$server}) eq 'HASH');              next unless (ref($spareid->{$server}) eq 'HASH');
             my ($checkednow,$checkedoth);  
             if (ref($curroffloadnow) eq 'HASH') {  
                 if ($curroffloadnow->{$server}) {  
                     $checkednow = ' checked="checked"';  
                 }  
             }  
             if (ref($curroffloadoth) eq 'HASH') {  
                 if ($curroffloadoth->{$server}) {  
                     $checkedoth = ' checked="checked"';  
                 }  
             }  
             $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 rowspan="2">                             <td rowspan="2">
                             <span class="LC_nobreak">'.                              <span class="LC_nobreak"><b>'.$server.'</b> when busy, offloads to:</span></td>'."\n";
                           &mt('[_1] when busy, offloads to:'  
                               ,'<b>'.$server.'</b>').'</span><br />'.  
                           '<span class="LC_nobreak">'."\n".  
                           '<label><input type="checkbox" name="offloadnow" value="'.$server.'"'.$checkednow.' />'.  
                           '&nbsp;'.&mt('Switch any active user on next access').'</label></span>'.  
                           "\n";  
             if ($other_insts) {  
                 $datatable .= '<br />'.  
                               '<span class="LC_nobreak">'."\n".  
                           '<label><input type="checkbox" name="offloadoth" value="'.$server.'"'.$checkedoth.' />'.  
                           '&nbsp;'.&mt('Switch other institutions on next access').'</label></span>'.  
                           "\n";  
             }  
             my (%current,%canselect);              my (%current,%canselect);
             my @choices =               my @choices = 
                 &possible_newspares($server,$spareid->{$server},$serverhomes,$altids);                  &possible_newspares($server,$spareid->{$server},$serverhomes,$altids);
Line 5086  sub print_loadbalancing { Line 2752  sub print_loadbalancing {
     my $numinrow = 1;      my $numinrow = 1;
     my $datatable;      my $datatable;
     my %servers = &Apache::lonnet::internet_dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
     my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);      my ($currbalancer,$currtargets,$currrules);
     if (ref($settings) eq 'HASH') {      if (keys(%servers) > 1) {
         %existing = %{$settings};          if (ref($settings) eq 'HASH') {
     }              $currbalancer = $settings->{'lonhost'};
     if ((keys(%servers) > 1) || (keys(%existing) > 0)) {              $currtargets = $settings->{'targets'};
         &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,              $currrules = $settings->{'rules'};
                                   \%currtargets,\%currrules,\%currcookies);          } else {
               ($currbalancer,$currtargets) = 
                   &Apache::lonnet::get_lonbalancer_config(\%servers);
           }
     } else {      } else {
         return;          return;
     }      }
     my ($othertitle,$usertypes,$types) =      my ($othertitle,$usertypes,$types) =
         &Apache::loncommon::sorted_inst_types($dom);          &Apache::loncommon::sorted_inst_types($dom);
     my $rownum = 8;      my $rownum = 6;
     if (ref($types) eq 'ARRAY') {      if (ref($types) eq 'ARRAY') {
         $rownum += scalar(@{$types});          $rownum += scalar(@{$types});
     }      }
     my @css_class = ('LC_odd_row','LC_even_row');      my $css_class = ' class="LC_odd_row"';
     my $balnum = 0;      my $targets_div_style = 'display: none';
     my $islast;      my $disabled_div_style = 'display: block';
     my (@toshow,$disabledtext);      my $homedom_div_style = 'display: none';
     if (keys(%currbalancer) > 0) {      $datatable = '<tr'.$css_class.'>'.
         @toshow = sort(keys(%currbalancer));                   '<td rowspan="'.$rownum.'" valign="top">'.
         if (scalar(@toshow) < scalar(keys(%servers)) + 1) {                   '<p><select name="loadbalancing_lonhost" onchange="toggleTargets();">'."\n".
             push(@toshow,'');                   '<option value=""';
         }      if (($currbalancer eq '') || (!grep(/^\Q$currbalancer\E$/,keys(%servers)))) {
     } else {          $datatable .= ' selected="selected"';
         @toshow = ('');      } else {
         $disabledtext = &mt('No existing load balancer');          $targets_div_style = 'display: block';
     }          $disabled_div_style = 'display: none';
     foreach my $lonhost (@toshow) {          if ($dom eq &Apache::lonnet::host_domain($currbalancer)) {
         if ($balnum == scalar(@toshow)-1) {              $homedom_div_style = 'display: block'; 
             $islast = 1;          }
         } else {      }
             $islast = 0;      $datatable .= '>'.&mt('None').'</option>'."\n";
         }      foreach my $lonhost (sort(keys(%servers))) {
         my $cssidx = $balnum%2;          my $selected;
         my $targets_div_style = 'display: none';          if ($lonhost eq $currbalancer) {
         my $disabled_div_style = 'display: block';              $selected .= ' selected="selected"';
         my $homedom_div_style = 'display: none';          }
         $datatable .= '<tr class="'.$css_class[$cssidx].'">'.          $datatable .= '<option value="'.$lonhost.'"'.$selected.'>'.$lonhost.'</option>'."\n";
                       '<td rowspan="'.$rownum.'" valign="top">'.      }
                       '<p>';      $datatable .= '</select></p></td><td rowspan="'.$rownum.'" valign="top">'.
         if ($lonhost eq '') {                    '<div id="loadbalancing_disabled" style="'.$disabled_div_style.'">'.&mt('No dedicated Load Balancer').'</div>'."\n".
             $datatable .= '<span class="LC_nobreak">';                    '<div id="loadbalancing_targets" style="'.$targets_div_style.'">'.&mt('Offloads to:').'<br />';
             if (keys(%currbalancer) > 0) {      my ($numspares,@spares) = &count_servers($currbalancer,%servers);
                 $datatable .= &mt('Add balancer:');      my @sparestypes = ('primary','default');
             } else {      my %typetitles = &sparestype_titles();
                 $datatable .= &mt('Enable balancer:');      foreach my $sparetype (@sparestypes) {
             }          my $targettable;
             $datatable .= '&nbsp;'.          for (my $i=0; $i<$numspares; $i++) {
                           '<select name="loadbalancing_lonhost_'.$balnum.'"'.              my $checked;
                           ' id="loadbalancing_lonhost_'.$balnum.'"'.              if (ref($currtargets) eq 'HASH') {
                           ' onchange="toggleTargets('."'$balnum'".');">'."\n".                  if (ref($currtargets->{$sparetype}) eq 'ARRAY') {
                           '<option value="" selected="selected">'.&mt('None').                      if (grep(/^\Q$spares[$i]\E$/,@{$currtargets->{$sparetype}})) {
                           '</option>'."\n";                          $checked = ' checked="checked"';
             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();  
         my %hostherechecked = (  
                                   no => ' checked="checked"',  
                               );  
         my %balcookiechecked = (  
                                   no => ' checked="checked"',  
                                );  
         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><span class="LC_nobreak"><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></span></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 />';  
             }  
             $hostherechecked{$sparetype} = '';  
             if (ref($currtargets{$lonhost}) eq 'HASH') {  
                 if (ref($currtargets{$lonhost}{$sparetype}) eq 'ARRAY') {  
                     if (grep(/^\Q$lonhost\E$/,@{$currtargets{$lonhost}{$sparetype}})) {  
                         $hostherechecked{$sparetype} = ' checked="checked"';  
                         $hostherechecked{'no'} = '';  
                     }                      }
                 }                  }
             }              }
         }              my $chkboxval;
         if ($currcookies{$lonhost}) {              if (($currbalancer ne '') && (grep((/^\Q$currbalancer\E$/,keys(%servers))))) {
             %balcookiechecked = (                  $chkboxval = $spares[$i];
                                     yes => ' checked="checked"',              }
                                 );              $targettable .= '<td><label><input type="checkbox" name="loadbalancing_target_'.$sparetype.'"'.
         }                        $checked.' value="'.$chkboxval.'" id="loadbalancing_target_'.$sparetype.'_'.$i.'" onclick="checkOffloads('."this,'$sparetype'".');" /><span id="loadbalancing_targettxt_'.$sparetype.'_'.$i.'">&nbsp;'.$chkboxval.
         $datatable .= &mt('Hosting on balancer itself').'<br />'.                        '</span></label></td>';
                       '<label><input type="radio" name="loadbalancing_target_'.$balnum.'_hosthere" value="no"'.              my $rem = $i%($numinrow);
                       $hostherechecked{'no'}.' />'.&mt('No').'</label><br />';              if ($rem == 0) {
         foreach my $sparetype (@sparestypes) {                  if ($i > 0) {
             $datatable .= '<label><input type="radio" name="loadbalancing_target_'.$balnum.'_hosthere" '.                      $targettable .= '</tr>';
                           'value="'.$sparetype.'"'.$hostherechecked{$sparetype}.' /><i>'.$typetitles{$sparetype}.  
                           '</i></label><br />';  
         }  
         $datatable .= &mt('Use balancer cookie').'<br />'.  
                       '<label><input type="radio" name="loadbalancing_cookie_'.$balnum.'" value="1"'.  
                       $balcookiechecked{'yes'}.' />'.&mt('Yes').'</label><br />'.  
                       '<label><input type="radio" name="loadbalancing_cookie_'.$balnum.'" value="0"'.  
                       $balcookiechecked{'no'}.' />'.&mt('No').'</label><br />'.  
                       '</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,$currcookies) = @_;  
     return unless ((ref($servers) eq 'HASH') &&  
                    (ref($existing) eq 'HASH') && (ref($currbalancer) eq 'HASH') &&  
                    (ref($currtargets) eq 'HASH') && (ref($currrules) eq 'HASH') &&  
                    (ref($currcookies) 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'};  
                 if ($existing->{$key}{'cookie'}) {  
                     $currcookies->{$key} = 1;  
                 }                  }
                   $targettable .= '<tr>';
             }              }
         }          }
     } else {          if ($targettable ne '') {
         my ($balancerref,$targetsref) =              my $rem = $numspares%($numinrow);
                 &Apache::lonnet::get_lonbalancer_config($servers);              my $colsleft = $numinrow - $rem;
         if ((ref($balancerref) eq 'HASH') && (ref($targetsref) eq 'HASH')) {              if ($colsleft > 1 ) {
             foreach my $server (sort(keys(%{$balancerref}))) {                  $targettable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                 $currbalancer->{$server} = 1;                                  '&nbsp;</td>';
                 $currtargets->{$server} = $targetsref->{$server};              } elsif ($colsleft == 1) {
                   $targettable .= '<td class="LC_left_item">&nbsp;</td>';
             }              }
               $datatable .=  '<i>'.$typetitles{$sparetype}.'</i><br />'.
                              '<table><tr>'.$targettable.'</table><br />';
         }          }
     }      }
     return;      $datatable .= '</div></td></tr>'.
                     &loadbalancing_rules($dom,$intdom,$currrules,$othertitle,
                                          $usertypes,$types,\%servers,$currbalancer,
                                          $targets_div_style,$homedom_div_style,$css_class);
       $$rowtotal += $rownum;
       return $datatable;
 }  }
   
 sub loadbalancing_rules {  sub loadbalancing_rules {
     my ($dom,$intdom,$currrules,$othertitle,$usertypes,$types,$servers,      my ($dom,$intdom,$currrules,$othertitle,$usertypes,$types,$servers,
         $currbalancer,$lonhost,$targets_div_style,$homedom_div_style,          $currbalancer,$targets_div_style,$homedom_div_style,$css_class) = @_;
         $css_class,$balnum,$islast) = @_;  
     my $output;      my $output;
     my $num = 0;      my ($alltypes,$othertypes,$titles) = 
     my ($alltypes,$othertypes,$titles) =  
         &loadbalancing_titles($dom,$intdom,$usertypes,$types);          &loadbalancing_titles($dom,$intdom,$usertypes,$types);
     if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH'))  {      if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH'))  {
         foreach my $type (@{$alltypes}) {          foreach my $type (@{$alltypes}) {
             $num ++;  
             my $current;              my $current;
             if (ref($currrules) eq 'HASH') {              if (ref($currrules) eq 'HASH') {
                 $current = $currrules->{$type};                  $current = $currrules->{$type};
             }              }
             if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {              if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {
                 if ($dom ne &Apache::lonnet::host_domain($lonhost)) {                  if ($dom ne &Apache::lonnet::host_domain($currbalancer)) {
                     $current = '';                      $current = '';
                 }                  }
             }              }
             $output .= &loadbalance_rule_row($type,$titles->{$type},$current,              $output .= &loadbalance_rule_row($type,$titles->{$type},$current,
                                              $servers,$currbalancer,$lonhost,$dom,                                               $servers,$currbalancer,$dom,
                                              $targets_div_style,$homedom_div_style,                                               $targets_div_style,$homedom_div_style,$css_class);
                                              $css_class,$balnum,$num,$islast);  
         }          }
     }      }
     return $output;      return $output;
Line 5336  sub loadbalancing_titles { Line 2881  sub loadbalancing_titles {
            '_LC_author'      => &mt('Users from [_1] with author role',$dom),             '_LC_author'      => &mt('Users from [_1] with author role',$dom),
            '_LC_internetdom' => &mt('Users not from [_1], but from [_2]',$dom,$intdom),             '_LC_internetdom' => &mt('Users not from [_1], but from [_2]',$dom,$intdom),
            '_LC_external'    => &mt('Users not from [_1]',$intdom),             '_LC_external'    => &mt('Users not from [_1]',$intdom),
            '_LC_ipchangesso' => &mt('SSO users from [_1], with IP mismatch',$dom),  
            '_LC_ipchange'    => &mt('Non-SSO users with IP mismatch'),  
                      );                       );
     my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external','_LC_ipchangesso','_LC_ipchange');      my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external');
     my @available;  
     if (ref($types) eq 'ARRAY') {      if (ref($types) eq 'ARRAY') {
         @available = @{$types};          unshift(@alltypes,@{$types},'default');
     }  
     unless (grep(/^default$/,@available)) {  
         push(@available,'default');  
     }      }
     unshift(@alltypes,@available);  
     my %titles;      my %titles;
     foreach my $type (@alltypes) {      foreach my $type (@alltypes) {
         if ($type =~ /^_LC_/) {          if ($type =~ /^_LC_/) {
Line 5367  sub loadbalancing_titles { Line 2905  sub loadbalancing_titles {
 }  }
   
 sub loadbalance_rule_row {  sub loadbalance_rule_row {
     my ($type,$title,$current,$servers,$currbalancer,$lonhost,$dom,      my ($type,$title,$current,$servers,$currbalancer,$dom,$targets_div_style,
         $targets_div_style,$homedom_div_style,$css_class,$balnum,$num,$islast) = @_;          $homedom_div_style,$css_class) = @_;
     my @rulenames;      my @rulenames = ('default','homeserver');
     my %ruletitles = &offloadtype_text();      my %ruletitles = &offloadtype_text();
     if (($type eq '_LC_ipchangesso') || ($type eq '_LC_ipchange')) {      if ($type eq '_LC_external') {
         @rulenames = ('balancer','offloadedto','specific');          push(@rulenames,'externalbalancer');
     } else {      } else {
         @rulenames = ('default','homeserver');          push(@rulenames,'specific');
         if ($type eq '_LC_external') {  
             push(@rulenames,'externalbalancer');  
         } else {  
             push(@rulenames,'specific');  
         }  
         push(@rulenames,'none');  
     }      }
       push(@rulenames,'none');
     my $style = $targets_div_style;      my $style = $targets_div_style;
     if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {      if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {
         $style = $homedom_div_style;          $style = $homedom_div_style;
     }      }
     my $space;      my $output = 
     if ($islast && $num == 1) {          '<tr'.$css_class.'><td valign="top"><div id="balanceruletitle_'.$type.'" style="'.$style.'">'.$title.'</div></td>'."\n".
         $space = '<div display="inline-block">&nbsp;</div>';          '<td><div id="balancerule_'.$type.'" style="'.$style.'">'."\n";
     }  
     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++) {      for (my $i=0; $i<@rulenames; $i++) {
         my $rule = $rulenames[$i];          my $rule = $rulenames[$i];
         my ($checked,$extra);          my ($checked,$extra);
Line 5410  sub loadbalance_rule_row { Line 2937  sub loadbalance_rule_row {
                 unless ($checked) {                  unless ($checked) {
                     $default = ' selected="selected"';                      $default = ' selected="selected"';
                 }                  }
                 $extra =                  $extra = ':&nbsp;<select name="loadbalancing_singleserver_'.$type.
                     ':&nbsp;<select name="loadbalancing_singleserver_'.$balnum.'_'.$type.                           '" id="loadbalancing_singleserver_'.$type.
                     '" id="loadbalancing_singleserver_'.$balnum.'_'.$type.                           '" onchange="singleServerToggle('."'$type'".')">'."\n".
                     '" onchange="singleServerToggle('."'$balnum','$type'".')">'."\n".                           '<option value=""'.$default.'></option>'."\n";
                     '<option value=""'.$default.'></option>'."\n";                  foreach my $lonhost (sort(keys(%{$servers}))) {
                 foreach my $server (sort(keys(%{$servers}))) {                      next if ($lonhost eq $currbalancer);
                     if (ref($currbalancer) eq 'HASH') {  
                         next if (exists($currbalancer->{$server}));  
                     }  
                     my $selected;                      my $selected;
                     if ($server eq $current) {                      if ($lonhost eq $current) {
                         $selected = ' selected="selected"';                          $selected = ' selected="selected"';
                     }                      }
                     $extra .= '<option value="'.$server.'"'.$selected.'>'.$server.'</option>';                      $extra .= '<option value="'.$lonhost.'"'.$selected.'>'.$lonhost.'</option>';
                 }                  }
                 $extra .= '</select>';                  $extra .= '</select>';
             }              }
Line 5431  sub loadbalance_rule_row { Line 2955  sub loadbalance_rule_row {
             $checked = ' checked="checked"';              $checked = ' checked="checked"';
         }          }
         $output .= '<span class="LC_nobreak"><label>'.          $output .= '<span class="LC_nobreak"><label>'.
                    '<input type="radio" name="loadbalancing_rules_'.$balnum.'_'.$type.                     '<input type="radio" name="loadbalancing_rules_'.$type.
                    '" id="loadbalancing_rules_'.$balnum.'_'.$type.'_'.$i.'" value="'.                     '" id="loadbalancing_rules_'.$type.'_'.$i.'" value="'.
                    $rule.'" onclick="balanceruleChange('."this.form,'$balnum','$type'".                     $rule.'" onclick="balanceruleChange('."this.form,'$type'".
                    ')"'.$checked.' />&nbsp;';                     ')"'.$checked.' />&nbsp;'.$ruletitles{$rulenames[$i]}.
         if (($rulenames[$i] eq 'specific') && ($type =~ /^_LC_ipchange/)) {                     '</label>'.$extra.'</span><br />'."\n";
             $output .= $ruletitles{'particular'};  
         } else {  
             $output .= $ruletitles{$rulenames[$i]};  
         }  
         $output .= '</label>'.$extra.'</span><br />'."\n";  
     }      }
     $output .= '</div></td></tr>'."\n";      $output .= '</div></td></tr>'."\n";
     return $output;      return $output;
Line 5453  sub offloadtype_text { Line 2972  sub offloadtype_text {
            'externalbalancer' => "Offloads to Load Balancer in user's domain",             'externalbalancer' => "Offloads to Load Balancer in user's domain",
            'specific'         => 'Offloads to specific server',             'specific'         => 'Offloads to specific server',
            'none'             => 'No offload',             'none'             => 'No offload',
            'balancer'         => 'Session hosted on Load Balancer, after re-authentication',  
            'offloadedto'      => 'Session hosted on offload server, after re-authentication',  
            'particular'       => 'Session hosted (after re-auth) on server:',  
     );      );
     return %ruletitles;      return %ruletitles;
 }  }
Line 5470  sub sparestype_titles { Line 2986  sub sparestype_titles {
   
 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 from all users in this domain",                     'helpdeskmail' => 'Helpdesk requests to be e-mailed to',
                    'otherdomsmail'   => 'Helpdesk requests from users in other (unconfigured) domains',                     'lonstatusmail' => 'E-mail from nightly status check (warnings/errors)',
                    'lonstatusmail'   => 'E-mail from nightly status check (warnings/errors)',                     'requestsmail' => 'E-mail from course requests requiring approval',
                    'requestsmail'    => 'E-mail from course requests requiring approval',  
                    'updatesmail'     => 'E-mail from nightly check of LON-CAPA module integrity/updates',  
                    'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID',  
                    'hostipmail'      => 'E-mail from nightly check of hostname/IP network changes',  
                  );                   );
     my %short_titles = &Apache::lonlocal::texthash (      my %short_titles = &Apache::lonlocal::texthash (
                            adminemail   => 'Admin E-mail address',                             adminemail   => 'Admin E-mail address',
Line 5489  sub contact_titles { Line 3001  sub contact_titles {
     return (\%titles,\%short_titles);      return (\%titles,\%short_titles);
 }  }
   
 sub helpform_fields {  
     my %titles =  &Apache::lonlocal::texthash (  
                        'username'   => 'Name',  
                        'user'       => 'Username/domain',  
                        'phone'      => 'Phone',  
                        'cc'         => 'Cc e-mail',  
                        'course'     => 'Course Details',  
                        'section'    => 'Sections',  
                        'screenshot' => 'File upload',  
     );  
     my @fields = ('username','phone','user','course','section','cc','screenshot');  
     my %possoptions = (  
                         username     => ['yes','no','req'],  
                         phone        => ['yes','no','req'],  
                         user         => ['yes','no'],  
                         cc           => ['yes','no'],  
                         course       => ['yes','no'],  
                         section      => ['yes','no'],  
                         screenshot   => ['yes','no'],  
                       );  
     my %fieldoptions = &Apache::lonlocal::texthash (  
                          'yes'  => 'Optional',  
                          'req'  => 'Required',  
                          'no'   => "Not shown",  
     );  
     return (\@fields,\%titles,\%fieldoptions,\%possoptions);  
 }  
   
 sub tool_titles {  sub tool_titles {
     my %titles = &Apache::lonlocal::texthash (      my %titles = &Apache::lonlocal::texthash (
                      aboutme    => 'Personal web page',                       aboutme    => 'Personal web page',
Line 5526  sub tool_titles { Line 3010  sub tool_titles {
                      official   => 'Official courses (with institutional codes)',                       official   => 'Official courses (with institutional codes)',
                      unofficial => 'Unofficial courses',                       unofficial => 'Unofficial courses',
                      community  => 'Communities',                       community  => 'Communities',
                      textbook   => 'Textbook courses',  
                  );                   );
     return %titles;      return %titles;
 }  }
Line 5536  sub courserequest_titles { Line 3019  sub courserequest_titles {
                                    official   => 'Official',                                     official   => 'Official',
                                    unofficial => 'Unofficial',                                     unofficial => 'Unofficial',
                                    community  => 'Communities',                                     community  => 'Communities',
                                    textbook   => 'Textbook',  
                                    norequest  => 'Not allowed',                                     norequest  => 'Not allowed',
                                    approval   => 'Approval by Dom. Coord.',                                     approval   => 'Approval by Dom. Coord.',
                                    validate   => 'With validation',                                     validate   => 'With validation',
Line 5546  sub courserequest_titles { Line 3028  sub courserequest_titles {
     return %titles;      return %titles;
 }  }
   
 sub authorrequest_titles {  
     my %titles = &Apache::lonlocal::texthash (  
                                    norequest  => 'Not allowed',  
                                    approval   => 'Approval by Dom. Coord.',  
                                    automatic  => 'Automatic approval',  
                  );  
     return %titles;  
 }  
   
 sub courserequest_conditions {  sub courserequest_conditions {
     my %conditions = &Apache::lonlocal::texthash (      my %conditions = &Apache::lonlocal::texthash (
        approval    => '(Processing of request subject to approval by Domain Coordinator).',         approval    => '(Processing of request subject to approval by Domain Coordinator).',
        validate   => '(Processing of request subject to institutional validation).',         validate   => '(Processing of request subject to instittutional validation).',
                  );                   );
     return %conditions;      return %conditions;
 }  }
Line 5589  sub print_usercreation { Line 3062  sub print_usercreation {
                 $rowcount ++;                  $rowcount ++;
             }              }
         }          }
           my ($emailrules,$emailruleorder) = 
               &Apache::lonnet::inst_userrules($dom,'email');
           if (ref($emailrules) eq 'HASH') {
               if (keys(%{$emailrules}) > 0) {
                   $datatable .= &user_formats_row('email',$settings,$emailrules,
                                                   $emailruleorder,$numinrow,$rowcount);
                   $$rowtotal ++;
                   $rowcount ++;
               }
           }
         if ($rowcount == 0) {          if ($rowcount == 0) {
             $datatable .= '<tr><td colspan="2">'.&mt('No format rules have been defined for usernames or IDs in this domain.').'</td></tr>';                $datatable .= '<tr><td colspan="2">'.&mt('No format rules have been defined for usernames or IDs in this domain.').'</td></tr>';  
             $$rowtotal ++;              $$rowtotal ++;
             $rowcount ++;              $rowcount ++;
         }          }
     } elsif ($position eq 'middle') {      } elsif ($position eq 'middle') {
         my @creators = ('author','course','requestcrs');          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();
         my %checked;          my %checked;
           my @selfcreate; 
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if (ref($settings->{'cancreate'}) eq 'HASH') {              if (ref($settings->{'cancreate'}) eq 'HASH') {
                 foreach my $item (@creators) {                  foreach my $item (@creators) {
                     $checked{$item} = $settings->{'cancreate'}{$item};                      $checked{$item} = $settings->{'cancreate'}{$item};
                 }                  }
                   if (ref($settings->{'cancreate'}{'selfcreate'}) eq 'ARRAY') {
                       @selfcreate = @{$settings->{'cancreate'}{'selfcreate'}};
                   } elsif ($settings->{'cancreate'}{'selfcreate'} ne '') {
                       if ($settings->{'cancreate'}{'selfcreate'} eq 'any') {
                           @selfcreate = ('email','login','sso');
                       } elsif ($settings->{'cancreate'}{'selfcreate'} ne 'none') {
                           @selfcreate = ($settings->{'cancreate'}{'selfcreate'});
                       }
                   }
             } elsif (ref($settings->{'cancreate'}) eq 'ARRAY') {              } elsif (ref($settings->{'cancreate'}) eq 'ARRAY') {
                 foreach my $item (@creators) {                  foreach my $item (@creators) {
                     if (grep(/^\Q$item\E$/,@{$settings->{'cancreate'}})) {                      if (grep(/^\Q$item\E$/,@{$settings->{'cancreate'}})) {
Line 5616  sub print_usercreation { Line 3109  sub print_usercreation {
         my $rownum = 0;          my $rownum = 0;
         foreach my $item (@creators) {          foreach my $item (@creators) {
             $rownum ++;              $rownum ++;
             if ($checked{$item} eq '') {              if ($item ne 'selfcreate') {  
                 $checked{$item} = 'any';                  if ($checked{$item} eq '') {
                       $checked{$item} = 'any';
                   }
             }              }
             my $css_class;              my $css_class;
             if ($rownum%2) {              if ($rownum%2) {
Line 5628  sub print_usercreation { Line 3123  sub print_usercreation {
             $datatable .= '<tr'.$css_class.'>'.              $datatable .= '<tr'.$css_class.'>'.
                          '<td><span class="LC_nobreak">'.$lt{$item}.                           '<td><span class="LC_nobreak">'.$lt{$item}.
                          '</span></td><td align="right">';                           '</span></td><td align="right">';
             my @options = ('any');              my @options;
             if (ref($rules) eq 'HASH') {              if ($item eq 'selfcreate') {
                 if (keys(%{$rules}) > 0) {                  push(@options,('email','login','sso'));
                     push(@options,('official','unofficial'));              } else {
                   @options = ('any');
                   if (ref($rules) eq 'HASH') {
                       if (keys(%{$rules}) > 0) {
                           push(@options,('official','unofficial'));
                       }
                 }                  }
                   push(@options,'none');
             }              }
             push(@options,'none');  
             foreach my $option (@options) {              foreach my $option (@options) {
                 my $type = 'radio';                  my $type = 'radio';
                 my $check = ' ';                  my $check = ' ';
                 if ($checked{$item} eq $option) {                  if ($item eq 'selfcreate') {
                     $check = ' checked="checked" ';                      $type = 'checkbox';
                       if (grep(/^\Q$option\E$/,@selfcreate)) {
                           $check = ' checked="checked" ';
                       }
                   } else {
                       if ($checked{$item} eq $option) {
                           $check = ' checked="checked" ';
                       }
                 }                   } 
                 $datatable .= '<span class="LC_nobreak"><label>'.                  $datatable .= '<span class="LC_nobreak"><label>'.
                               '<input type="'.$type.'" name="can_createuser_'.                                '<input type="'.$type.'" name="can_createuser_'.
Line 5648  sub print_usercreation { Line 3155  sub print_usercreation {
             }              }
             $datatable .= '</td></tr>';              $datatable .= '</td></tr>';
         }          }
           my ($othertitle,$usertypes,$types) =
               &Apache::loncommon::sorted_inst_types($dom);
           if (ref($usertypes) eq 'HASH') {
               if (keys(%{$usertypes}) > 0) {
                   my $createsettings;
                   if (ref($settings) eq 'HASH') {
                       $createsettings = $settings->{cancreate};
                   }
                   $datatable .= &insttypes_row($createsettings,$types,$usertypes,
                                                $dom,$numinrow,$othertitle,
                                                'statustocreate');
                   $$rowtotal ++;
               }
           }
     } else {      } else {
         my @contexts = ('author','course','domain');          my @contexts = ('author','course','domain');
         my @authtypes = ('int','krb4','krb5','loc');          my @authtypes = ('int','krb4','krb5','loc');
Line 5699  sub print_usercreation { Line 3220  sub print_usercreation {
     return $datatable;      return $datatable;
 }  }
   
 sub print_selfcreation {  
     my ($position,$dom,$settings,$rowtotal) = @_;  
     my (@selfcreate,$createsettings,$processing,$emailoptions,$emailverified,  
         $emaildomain,$datatable);  
     if (ref($settings) eq 'HASH') {  
         if (ref($settings->{'cancreate'}) eq 'HASH') {  
             $createsettings = $settings->{'cancreate'};  
             if (ref($createsettings) eq 'HASH') {  
                 if (ref($createsettings->{'selfcreate'}) eq 'ARRAY') {  
                     @selfcreate = @{$createsettings->{'selfcreate'}};  
                 } elsif ($createsettings->{'selfcreate'} ne '') {  
                     if ($settings->{'cancreate'}{'selfcreate'} eq 'any') {  
                         @selfcreate = ('email','login','sso');  
                     } elsif ($createsettings->{'selfcreate'} ne 'none') {  
                         @selfcreate = ($createsettings->{'selfcreate'});  
                     }  
                 }  
                 if (ref($createsettings->{'selfcreateprocessing'}) eq 'HASH') {  
                     $processing = $createsettings->{'selfcreateprocessing'};  
                 }  
                 if (ref($createsettings->{'emailoptions'}) eq 'HASH') {  
                     $emailoptions = $createsettings->{'emailoptions'};  
                 }  
                 if (ref($createsettings->{'emailverified'}) eq 'HASH') {  
                     $emailverified = $createsettings->{'emailverified'};  
                 }  
                 if (ref($createsettings->{'emaildomain'}) eq 'HASH') {  
                     $emaildomain = $createsettings->{'emaildomain'};  
                 }  
             }  
         }  
     }  
     my %radiohash;  
     my $numinrow = 4;  
     map { $radiohash{'cancreate_'.$_} = 1; } @selfcreate;  
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
     if ($position eq 'top') {  
         my %choices = &Apache::lonlocal::texthash (  
                                                       cancreate_login      => 'Institutional Login',  
                                                       cancreate_sso        => 'Institutional Single Sign On',  
                                                   );  
         my @toggles = sort(keys(%choices));  
         my %defaultchecked = (  
                                'cancreate_login' => 'off',  
                                'cancreate_sso'   => 'off',  
                              );  
         my ($onclick,$itemcount);  
         ($datatable,$itemcount) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,  
                                                      \%choices,$itemcount,$onclick);  
         $$rowtotal += $itemcount;  
   
         if (ref($usertypes) eq 'HASH') {  
             if (keys(%{$usertypes}) > 0) {  
                 $datatable .= &insttypes_row($createsettings,$types,$usertypes,  
                                              $dom,$numinrow,$othertitle,  
                                              'statustocreate',$rowtotal);  
                 $$rowtotal ++;  
             }  
         }  
         my @fields = ('lastname','firstname','middlename','permanentemail','id','inststatus');  
         my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();  
         $fieldtitles{'inststatus'} = &mt('Institutional status');  
         my $rem;  
         my $numperrow = 2;  
         my $css_class = $$rowtotal%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'>'.  
                      '<td class="LC_left_item">'.&mt('Mapping of Shibboleth environment variable names to user data fields (SSO auth)').'</td>'.  
                      '<td class="LC_left_item">'."\n".  
                      '<table>'."\n";  
         for (my $i=0; $i<@fields; $i++) {  
             $rem = $i%($numperrow);  
             if ($rem == 0) {  
                 if ($i > 0) {  
                     $datatable .= '</tr>';  
                 }  
                 $datatable .= '<tr>';  
             }  
             my $currval;  
             if (ref($createsettings) eq 'HASH') {  
                 if (ref($createsettings->{'shibenv'}) eq 'HASH') {  
                     $currval = $createsettings->{'shibenv'}{$fields[$i]};  
                 }  
             }  
             $datatable .= '<td class="LC_left_item">'.  
                           '<span class="LC_nobreak">'.  
                           '<input type="text" name="shibenv_'.$fields[$i].'" '.  
                           'value="'.$currval.'" size="10" />&nbsp;'.  
                           $fieldtitles{$fields[$i]}.'</span></td>';  
         }  
         my $colsleft = $numperrow - $rem;  
         if ($colsleft > 1 ) {  
             $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.  
                          '&nbsp;</td>';  
         } elsif ($colsleft == 1) {  
             $datatable .= '<td class="LC_left_item">&nbsp;</td>';  
         }  
         $datatable .= '</tr></table></td></tr>';  
         $$rowtotal ++;  
     } elsif ($position eq 'middle') {  
         my %domconf = &Apache::lonnet::get_dom('configuration',['usermodification'],$dom);  
         my @posstypes;  
         if (ref($types) eq 'ARRAY') {  
             @posstypes = @{$types};  
         }  
         unless (grep(/^default$/,@posstypes)) {  
             push(@posstypes,'default');  
         }  
         my %usertypeshash;  
         if (ref($usertypes) eq 'HASH') {  
             %usertypeshash = %{$usertypes};  
         }  
         $usertypeshash{'default'} = $othertitle;  
         foreach my $status (@posstypes) {  
             $datatable .= &modifiable_userdata_row('selfcreate',$status,$domconf{'usermodification'},  
                                                    $numinrow,$$rowtotal,\%usertypeshash);  
             $$rowtotal ++;  
         }  
     } else {  
         my %choices = &Apache::lonlocal::texthash (  
                           'cancreate_email' => 'Non-institutional username (via e-mail verification)',  
                                                   );  
         my @toggles = sort(keys(%choices));  
         my %defaultchecked = (  
                                'cancreate_email' => 'off',  
                              );  
         my $customclass = 'LC_selfcreate_email';  
         my $classprefix = 'LC_canmodify_emailusername_';  
         my $optionsprefix = 'LC_options_emailusername_';  
         my $display = 'none';  
         my $rowstyle = 'display:none';  
         if (grep(/^\Qemail\E$/,@selfcreate)) {  
             $display = 'block';  
             $rowstyle = 'display:table-row';  
         }  
         my $onclick = "toggleRows(this.form,'cancreate_email','selfassign','$customclass','$classprefix','$optionsprefix');";  
         ($datatable,$$rowtotal) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,  
                                                      \%choices,$$rowtotal,$onclick);  
         $datatable .= &print_requestmail($dom,'selfcreation',$createsettings,$rowtotal,$customclass,  
                                          $rowstyle);  
         $$rowtotal ++;  
         $datatable .= &captcha_choice('cancreate',$createsettings,$$rowtotal,$customclass,  
                                       $rowstyle);  
         $$rowtotal ++;  
         my (@ordered,@posstypes,%usertypeshash);  
         my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);  
         my ($emailrules,$emailruleorder) =  
             &Apache::lonnet::inst_userrules($dom,'email');  
         my $primary_id = &Apache::lonnet::domain($dom,'primary');  
         my $intdom = &Apache::lonnet::internet_dom($primary_id);  
         if (ref($types) eq 'ARRAY') {  
             @posstypes = @{$types};  
         }  
         if (@posstypes) {  
             unless (grep(/^default$/,@posstypes)) {  
                 push(@posstypes,'default');  
             }  
             if (ref($usertypes) eq 'HASH') {  
                 %usertypeshash = %{$usertypes};  
             }  
             my $currassign;  
             if (ref($domdefaults{'inststatusguest'}) eq 'ARRAY') {  
                 $currassign = {  
                                   selfassign => $domdefaults{'inststatusguest'},  
                               };  
                 @ordered = @{$domdefaults{'inststatusguest'}};  
             } else {  
                 $currassign = { selfassign => [] };  
             }  
             my $onclicktypes = "toggleDataRow(this.form,'selfassign','$customclass','$optionsprefix',);".  
                                "toggleDataRow(this.form,'selfassign','$customclass','$classprefix',1);";  
             $datatable .= &insttypes_row($currassign,$types,$usertypes,$dom,  
                                          $numinrow,$othertitle,'selfassign',  
                                          $rowtotal,$onclicktypes,$customclass,  
                                          $rowstyle);  
             $$rowtotal ++;  
             $usertypeshash{'default'} = $othertitle;  
             foreach my $status (@posstypes) {  
                 my $css_class;  
                 if ($$rowtotal%2) {  
                     $css_class = 'LC_odd_row ';  
                 }  
                 $css_class .= $customclass;  
                 my $rowid = $optionsprefix.$status;  
                 my $hidden = 1;  
                 my $currstyle = 'display:none';  
                 if (grep(/^\Q$status\E$/,@ordered)) {  
                     $currstyle = $rowstyle;  
                     $hidden = 0;  
                 }  
                 $datatable .= &noninst_users($processing,$emailverified,$emailoptions,$emaildomain,  
                                              $emailrules,$emailruleorder,$settings,$status,$rowid,  
                                              $usertypeshash{$status},$css_class,$currstyle,$intdom);  
                 unless ($hidden) {  
                     $$rowtotal ++;  
                 }  
             }  
         } else {  
             my $css_class;  
             if ($$rowtotal%2) {  
                 $css_class = 'LC_odd_row ';  
             }  
             $css_class .= $customclass;  
             $usertypeshash{'default'} = $othertitle;  
             $datatable .= &noninst_users($processing,$emailverified,$emailoptions,$emaildomain,  
                                          $emailrules,$emailruleorder,$settings,'default','',  
                                          $othertitle,$css_class,$rowstyle,$intdom);  
             $$rowtotal ++;  
         }  
         my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();  
         $numinrow = 1;  
         if (@posstypes) {  
             foreach my $status (@posstypes) {  
                 my $rowid = $classprefix.$status;  
                 my $datarowstyle = 'display:none';  
                 if (grep(/^\Q$status\E$/,@ordered)) {  
                     $datarowstyle = $rowstyle;  
                 }  
                 $datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,  
                                                        $numinrow,$$rowtotal,\%usertypeshash,$infofields,  
                                                        $infotitles,$rowid,$customclass,$datarowstyle);  
                 unless ($datarowstyle eq 'display:none') {  
                     $$rowtotal ++;  
                 }  
             }  
         } else {  
             $datatable .= &modifiable_userdata_row('cancreate','emailusername_default',$settings,  
                                                    $numinrow,$$rowtotal,\%usertypeshash,$infofields,  
                                                    $infotitles,'',$customclass,$rowstyle);  
         }  
     }  
     return $datatable;  
 }  
   
 sub selfcreate_javascript {  
     return <<"ENDSCRIPT";  
   
 <script type="text/javascript">  
 // <![CDATA[  
   
 function toggleRows(form,radio,checkbox,target,prefix,altprefix) {  
     var x = document.getElementsByClassName(target);  
     var insttypes = 0;  
     var insttypeRegExp = new RegExp(prefix);  
     if ((x.length != undefined) && (x.length > 0)) {  
         if (form.elements[radio].length != undefined) {  
             for (var i=0; i<form.elements[radio].length; i++) {  
                 if (form.elements[radio][i].checked) {  
                     if (form.elements[radio][i].value == 1) {  
                         for (var j=0; j<x.length; j++) {  
                             if (x[j].id == 'undefined') {  
                                 x[j].style.display = 'table-row';  
                             } else if (insttypeRegExp.test(x[j].id)) {  
                                 insttypes ++;  
                             } else {  
                                 x[j].style.display = 'table-row';  
                             }  
                         }  
                     } else {  
                         for (var j=0; j<x.length; j++) {  
                             x[j].style.display = 'none';  
                         }  
                     }  
                     break;  
                 }  
             }  
             if (insttypes > 0) {  
                 toggleDataRow(form,checkbox,target,altprefix);  
                 toggleDataRow(form,checkbox,target,prefix,1);  
             }  
         }  
     }  
     return;  
 }  
   
 function toggleDataRow(form,checkbox,target,prefix,docount) {  
     if (form.elements[checkbox].length != undefined) {  
         var count = 0;  
         if (docount) {  
             for (var i=0; i<form.elements[checkbox].length; i++) {  
                 if (form.elements[checkbox][i].checked) {  
                     count ++;  
                 }  
             }  
         }  
         for (var i=0; i<form.elements[checkbox].length; i++) {  
             var type = form.elements[checkbox][i].value;  
             if (document.getElementById(prefix+type)) {  
                 if (form.elements[checkbox][i].checked) {  
                     document.getElementById(prefix+type).style.display = 'table-row';  
                     if (count % 2 == 1) {  
                         document.getElementById(prefix+type).className = target+' LC_odd_row';  
                     } else {  
                         document.getElementById(prefix+type).className = target;  
                     }  
                     count ++;  
                 } else {  
                     document.getElementById(prefix+type).style.display = 'none';  
                 }  
             }  
         }  
     }  
     return;  
 }  
   
 function toggleEmailOptions(form,radio,prefix,altprefix,status) {  
     var caller = radio+'_'+status;  
     if (form.elements[caller].length != undefined) {  
         for (var i=0; i<form.elements[caller].length; i++) {  
             if (form.elements[caller][i].checked) {  
                 if (document.getElementById(altprefix+'_inst_'+status)) {  
                     var curr = form.elements[caller][i].value;  
                     if (prefix) {  
                         document.getElementById(prefix+'_'+status).style.display = 'none';  
                     }  
                     document.getElementById(altprefix+'_inst_'+status).style.display = 'none';  
                     document.getElementById(altprefix+'_noninst_'+status).style.display = 'none';  
                     if (curr == 'custom') {  
                         if (prefix) {  
                             document.getElementById(prefix+'_'+status).style.display = 'inline';  
                         }  
                     } else if (curr == 'inst') {  
                         document.getElementById(altprefix+'_inst_'+status).style.display = 'inline';  
                     } else if (curr == 'noninst') {  
                         document.getElementById(altprefix+'_noninst_'+status).style.display = 'inline';  
                     }  
                     break;  
                 }  
             }  
         }  
     }  
 }  
   
 // ]]>  
 </script>  
   
 ENDSCRIPT  
 }  
   
 sub noninst_users {  
     my ($processing,$emailverified,$emailoptions,$emaildomain,$emailrules,  
         $emailruleorder,$settings,$type,$rowid,$typetitle,$css_class,$rowstyle,$intdom) = @_;  
     my $class = 'LC_left_item';  
     if ($css_class) {  
         $css_class = ' class="'.$css_class.'"';  
     }  
     if ($rowid) {  
         $rowid = ' id="'.$rowid.'"';  
     }  
     if ($rowstyle) {  
         $rowstyle = ' style="'.$rowstyle.'"';  
     }  
     my ($output,$description);  
     if ($type eq 'default') {  
         $description = &mt('Requests for: [_1]',$typetitle);  
     } else {  
         $description = &mt('Requests for: [_1] (status self-reported)',$typetitle);  
     }  
     $output = '<tr'.$css_class.$rowid.$rowstyle.'>'.  
               "<td>$description</td>\n".  
               '<td class="'.$class.'" colspan="2">'.  
               '<table><tr>';  
     my %headers = &Apache::lonlocal::texthash(  
               approve  => 'Processing',  
               email    => 'E-mail',  
               username => 'Username',  
     );  
     foreach my $item ('approve','email','username') {  
         $output .= '<th>'.$headers{$item}.'</th>';  
     }  
     $output .= '</tr><tr>';  
     foreach my $item ('approve','email','username') {  
         $output .= '<td valign="top">';  
         my (%choices,@options,$hashref,$defoption,$name,$onclick,$hascustom);  
         if ($item eq 'approve') {  
             %choices = &Apache::lonlocal::texthash (  
                                                      automatic => 'Automatically approved',  
                                                      approval  => 'Queued for approval',  
                                                    );  
             @options = ('automatic','approval');  
             $hashref = $processing;  
             $defoption = 'automatic';  
             $name = 'cancreate_emailprocess_'.$type;  
         } elsif ($item eq 'email') {  
             %choices = &Apache::lonlocal::texthash (  
                                                      any     => 'Any e-mail',  
                                                      inst    => 'Institutional only',  
                                                      noninst => 'Non-institutional only',  
                                                      custom  => 'Custom restrictions',  
                                                    );  
             @options = ('any','inst','noninst');  
             my $showcustom;  
             if (ref($emailrules) eq 'HASH') {  
                 if (keys(%{$emailrules}) > 0) {  
                     push(@options,'custom');  
                     $showcustom = 'cancreate_emailrule';  
                     if (ref($settings) eq 'HASH') {  
                         if (ref($settings->{'email_rule'}) eq 'ARRAY') {  
                             foreach my $rule (@{$settings->{'email_rule'}}) {  
                                 if (exists($emailrules->{$rule})) {  
                                     $hascustom ++;  
                                 }  
                             }  
                         } elsif (ref($settings->{'email_rule'}) eq 'HASH') {  
                             if (ref($settings->{'email_rule'}{$type}) eq 'ARRAY') {  
                                 foreach my $rule (@{$settings->{'email_rule'}{$type}}) {  
                                     if (exists($emailrules->{$rule})) {  
                                         $hascustom ++;  
                                     }  
                                 }  
                             }  
                         }  
                     }  
                 }  
             }  
             $onclick = ' onclick="toggleEmailOptions(this.form,'."'cancreate_emailoptions','$showcustom',".  
                                                      "'cancreate_emaildomain','$type'".');"';  
             $hashref = $emailoptions;  
             $defoption = 'any';  
             $name = 'cancreate_emailoptions_'.$type;  
         } elsif ($item eq 'username') {  
             %choices = &Apache::lonlocal::texthash (  
                                                      all    => 'Same as e-mail',  
                                                      first  => 'Omit @domain',  
                                                      free   => 'Free to choose',  
                                                    );  
             @options = ('all','first','free');  
             $hashref = $emailverified;  
             $defoption = 'all';  
             $name = 'cancreate_usernameoptions_'.$type;  
         }  
         foreach my $option (@options) {  
             my $checked;  
             if (ref($hashref) eq 'HASH') {  
                 if ($type eq '') {  
                     if (!exists($hashref->{'default'})) {  
                         if ($option eq $defoption) {  
                             $checked = ' checked="checked"';  
                         }  
                     } else {  
                         if ($hashref->{'default'} eq $option) {  
                             $checked = ' checked="checked"';  
                         }  
                     }  
                 } else {  
                     if (!exists($hashref->{$type})) {  
                         if ($option eq $defoption) {  
                             $checked = ' checked="checked"';  
                         }  
                     } else {  
                         if ($hashref->{$type} eq $option) {  
                             $checked = ' checked="checked"';  
                         }  
                     }  
                 }  
             } elsif (($item eq 'email') && ($hascustom)) {  
                 if ($option eq 'custom') {  
                     $checked = ' checked="checked"';  
                 }  
             } elsif ($option eq $defoption) {  
                 $checked = ' checked="checked"';  
             }  
             $output .= '<span class="LC_nobreak"><label>'.  
                        '<input type="radio" name="'.$name.'"'.  
                        $checked.' value="'.$option.'"'.$onclick.' />'.  
                        $choices{$option}.'</label></span><br />';  
             if ($item eq 'email') {  
                 if ($option eq 'custom') {  
                     my $id = 'cancreate_emailrule_'.$type;  
                     my $display = 'none';  
                     if ($checked) {  
                         $display = 'inline';  
                     }  
                     my $numinrow = 2;  
                     $output .= '<fieldset id="'.$id.'" style="display:'.$display.';">'.  
                                '<legend>'.&mt('Disallow').'</legend><table>'.  
                                &user_formats_row('email',$settings,$emailrules,  
                                                  $emailruleorder,$numinrow,'',$type);  
                               '</table></fieldset>';  
                 } elsif (($option eq 'inst') || ($option eq 'noninst')) {  
                     my %text = &Apache::lonlocal::texthash (  
                                                              inst    => 'must end:',  
                                                              noninst => 'cannot end:',  
                                                            );  
                     my $value;  
                     if (ref($emaildomain) eq 'HASH') {  
                         if (ref($emaildomain->{$type}) eq 'HASH') {  
                             $value = $emaildomain->{$type}->{$option};  
                         }  
                     }  
                     if ($value eq '') {  
                         $value = '@'.$intdom;  
                     }  
                     my $condition = 'cancreate_emaildomain_'.$option.'_'.$type;  
                     my $display = 'none';  
                     if ($checked) {  
                         $display = 'inline';  
                     }  
                     $output .= '<div id="'.$condition.'" style="display:'.$display.';">'.  
                                '<span class="LC_domprefs_email">'.$text{$option}.'</span> '.  
                                '<input type="text" name="'.$condition.'" value="'.$value.'" size="10" />'.  
                                '</div>';  
                 }  
             }  
         }  
         $output .= '</td>'."\n";  
     }  
     $output .= "</tr></table></td></tr>\n";  
     return $output;  
 }  
   
 sub captcha_choice {  
     my ($context,$settings,$itemcount,$customcss,$rowstyle) = @_;  
     my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext,  
         $vertext,$currver);   
     my %lt = &captcha_phrases();  
     $keyentry = 'hidden';  
     my $colspan=2;  
     if ($context eq 'cancreate') {  
         $rowname = &mt('CAPTCHA validation');  
     } elsif ($context eq 'login') {  
         $rowname =  &mt('"Contact helpdesk" CAPTCHA validation');  
     } elsif ($context eq 'passwords') {  
         $rowname = &mt('"Forgot Password" CAPTCHA validation');  
         $colspan=1;  
     }  
     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';  
             $vertext = $lt{'ver'};  
             $currver = $settings->{'recaptchaversion'};  
             if ($currver ne '2') {  
                 $currver = 1;  
             }  
         }  
         if (ref($settings->{'recaptchakeys'}) eq 'HASH') {  
             $currpub = $settings->{'recaptchakeys'}{'public'};  
             $currpriv = $settings->{'recaptchakeys'}{'private'};  
         }  
     } else {  
         $checked{'original'} = ' checked="checked"';  
     }  
     my $css_class;  
     if ($itemcount%2) {  
         $css_class = 'LC_odd_row';  
     }  
     if ($customcss) {  
         $css_class .= " $customcss";  
     }  
     $css_class =~ s/^\s+//;  
     if ($css_class) {  
         $css_class = ' class="'.$css_class.'"';  
     }  
     if ($rowstyle) {  
         $css_class .= ' style="'.$rowstyle.'"';  
     }  
     my $output = '<tr'.$css_class.'>'.  
                  '<td class="LC_left_item">'.$rowname.'</td><td class="LC_left_item" colspan="'.$colspan.'">'."\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 class="LC_zero_height">'."\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><br />'.  
                '<span class="LC_nobreak"><span id="'.$context.'_recaptchavertxt">'.$vertext.'</span>&nbsp;'."\n".  
                '<input type="'.$keyentry.'" id="'.$context.'_recaptchaversion" name="'.$context.'_recaptchaversion" value="'.  
                $currver.'" size="3" /></span><br />'.  
                '</td></tr></table>'."\n".  
                '</td></tr>';  
     return $output;  
 }  
   
 sub user_formats_row {  sub user_formats_row {
     my ($type,$settings,$rules,$ruleorder,$numinrow,$rowcount,$status) = @_;      my ($type,$settings,$rules,$ruleorder,$numinrow,$rowcount) = @_;
     my $output;      my $output;
     my %text = (      my %text = (
                    'username' => 'new usernames',                     'username' => 'new usernames',
                    'id'       => 'IDs',                     'id'       => 'IDs',
                      'email'    => 'self-created accounts (e-mail)',
                );                 );
     unless ($type eq 'email') {      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">'.      if ($type eq 'email') {
                   &mt("Format rules to check for $text{$type}: ").          $output .= &mt("Formats disallowed for $text{$type}: ");
                   '</td><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 6325  sub user_formats_row { Line 3255  sub user_formats_row {
                         if (grep(/^\Q$ruleorder->[$i]\E$/,@{$settings->{$type.'_rule'}})) {                          if (grep(/^\Q$ruleorder->[$i]\E$/,@{$settings->{$type.'_rule'}})) {
                             $check = ' checked="checked" ';                              $check = ' checked="checked" ';
                         }                          }
                     } elsif ((ref($settings->{$type.'_rule'}) eq 'HASH') && ($status ne '')) {  
                         if (ref($settings->{$type.'_rule'}->{$status}) eq 'ARRAY') {  
                             if (grep(/^\Q$ruleorder->[$i]\E$/,@{$settings->{$type.'_rule'}->{$status}})) {  
                                 $check = ' checked="checked" ';  
                             }  
                         }  
                     }                      }
                 }                  }
                 my $name = $type.'_rule';  
                 if ($type eq 'email') {  
                     $name .= '_'.$status;  
                 }  
                 $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="'.$name.'" '.                             '<input type="checkbox" name="'.$type.'_rule" '.
                            'value="'.$ruleorder->[$i].'"'.$check.'/>'.                             'value="'.$ruleorder->[$i].'"'.$check.'/>'.
                            $rules->{$ruleorder->[$i]}{'name'}.'</label></span></td>';                             $rules->{$ruleorder->[$i]}{'name'}.'</label></span></td>';
             }              }
         }          }
         $rem = @{$ruleorder}%($numinrow);          $rem = @{$ruleorder}%($numinrow);
     }      }
     my $colsleft;      my $colsleft = $numinrow - $rem;
     if ($rem) {  
         $colsleft = $numinrow - $rem;  
     }  
     if ($colsleft > 1 ) {      if ($colsleft > 1 ) {
         $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.          $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                    '&nbsp;</td>';                     '&nbsp;</td>';
     } elsif ($colsleft == 1) {      } elsif ($colsleft == 1) {
         $output .= '<td class="LC_left_item">&nbsp;</td>';          $output .= '<td class="LC_left_item">&nbsp;</td>';
     }      }
     $output .= '</tr></table>';      $output .= '</tr></table></td></tr>';
     unless ($type eq 'email') {  
         $output .= '</td></tr>';  
     }  
     return $output;      return $output;
 }  }
   
Line 6368  sub usercreation_types { Line 3282  sub usercreation_types {
                     author     => 'When adding a co-author',                      author     => 'When adding a co-author',
                     course     => 'When adding a user to a course',                      course     => 'When adding a user to a course',
                     requestcrs => 'When requesting a course',                      requestcrs => 'When requesting a course',
                       selfcreate => 'User creates own account', 
                     any        => 'Any',                      any        => 'Any',
                     official   => 'Institutional only ',                      official   => 'Institutional only ',
                     unofficial => 'Non-institutional only',                      unofficial => 'Non-institutional only',
                       email      => 'E-mail address',
                       login      => 'Institutional Login',
                       sso        => 'SSO', 
                     none       => 'None',                      none       => 'None',
     );      );
     return %lt;      return %lt;
 }  }
   
 sub selfcreation_types {  
     my %lt = &Apache::lonlocal::texthash (  
                     selfcreate => 'User creates own account',  
                     any        => 'Any',  
                     official   => 'Institutional only ',  
                     unofficial => 'Non-institutional only',  
                     email      => 'E-mail address',  
                     login      => 'Institutional Login',  
                     sso        => 'SSO',  
              );  
 }  
   
 sub authtype_names {  sub authtype_names {
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
                       int    => 'Internal',                        int    => 'Internal',
Line 6420  sub print_usermodification { Line 3326  sub print_usermodification {
             $$rowtotal ++;              $$rowtotal ++;
             $rowcount ++;              $rowcount ++;
         }          }
     } elsif ($position eq 'bottom') {      } 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 6429  sub print_usermodification { Line 3335  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 ($position,$dom,$settings,$rowtotal) = @_;      my ($dom,$rowtotal) = @_;
       my @items = ('auth_def','auth_arg_def','lang_def','timezone_def',
                    'datelocale_def','portal_def');
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
       my $titles = &defaults_titles($dom);
     my $rownum = 0;      my $rownum = 0;
     my ($datatable,$css_class,$titles);      my ($datatable,$css_class);
     unless ($position eq 'bottom') {      foreach my $item (@items) {
         $titles = &defaults_titles($dom);          if ($rownum%2) {
     }              $css_class = '';
     if ($position eq 'top') {  
         my @items = ('auth_def','auth_arg_def','lang_def','timezone_def',  
                      'datelocale_def','portal_def');  
         my %defaults;  
         if (ref($settings) eq 'HASH') {  
             %defaults = %{$settings};  
         } else {          } else {
             my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);              $css_class = ' class="LC_odd_row" ';
             foreach my $item (@items) {  
                 $defaults{$item} = $domdefaults{$item};  
             }  
         }          }
         foreach my $item (@items) {          $datatable .= '<tr'.$css_class.'>'.
             if ($rownum%2) {                    '<td><span class="LC_nobreak">'.$titles->{$item}.
                 $css_class = '';                    '</span></td><td class="LC_right_item">';
             } else {          if ($item eq 'auth_def') {
                 $css_class = ' class="LC_odd_row" ';              my @authtypes = ('internal','krb4','krb5','localauth');
             }              my %shortauth = (
             $datatable .= '<tr'.$css_class.'>'.                               internal => 'int',
                           '<td><span class="LC_nobreak">'.$titles->{$item}.                               krb4 => 'krb4',
                           '</span></td><td class="LC_right_item" colspan="3">';                               krb5 => 'krb5',
             if ($item eq 'auth_def') {                               localauth  => 'loc'
                 my @authtypes = ('internal','krb4','krb5','localauth');                             );
                 my %shortauth = (              my %authnames = &authtype_names();
                                  internal => 'int',              foreach my $auth (@authtypes) {
                                  krb4 => 'krb4',                  my $checked = ' ';
                                  krb5 => 'krb5',                  if ($domdefaults{$item} eq $auth) {
                                  localauth  => 'loc'                      $checked = ' checked="checked" ';
                                 );                  }
                 my %authnames = &authtype_names();                  $datatable .= '<label><input type="radio" name="'.$item.
                 foreach my $auth (@authtypes) {                                '" value="'.$auth.'"'.$checked.'/>'.
                     my $checked = ' ';                                $authnames{$shortauth{$auth}}.'</label>&nbsp;&nbsp;';
                     if ($defaults{$item} eq $auth) {  
                         $checked = ' checked="checked" ';  
                     }  
                     $datatable .= '<label><input type="radio" name="'.$item.  
                                   '" value="'.$auth.'"'.$checked.'/>'.  
                                   $authnames{$shortauth{$auth}}.'</label>&nbsp;&nbsp;';  
                 }  
             } elsif ($item eq 'timezone_def') {  
                 my $includeempty = 1;  
                 $datatable .= &Apache::loncommon::select_timezone($item,$defaults{$item},undef,$includeempty);  
             } elsif ($item eq 'datelocale_def') {  
                 my $includeempty = 1;  
                 $datatable .= &Apache::loncommon::select_datelocale($item,$defaults{$item},undef,$includeempty);  
             } elsif ($item eq 'lang_def') {  
                 my $includeempty = 1;  
                 $datatable .= &Apache::loncommon::select_language($item,$defaults{$item},$includeempty);  
             } else {  
                 my $size;  
                 if ($item eq 'portal_def') {  
                     $size = ' size="25"';  
                 }  
                 $datatable .= '<input type="text" name="'.$item.'" value="'.  
                               $defaults{$item}.'"'.$size.' />';  
             }              }
             $datatable .= '</td></tr>';          } elsif ($item eq 'timezone_def') {
             $rownum ++;              my $includeempty = 1;
         }              $datatable .= &Apache::loncommon::select_timezone($item,$domdefaults{$item},undef,$includeempty);
     } else {          } elsif ($item eq 'datelocale_def') {
         my %defaults;              my $includeempty = 1;
         if (ref($settings) eq 'HASH') {              $datatable .= &Apache::loncommon::select_datelocale($item,$domdefaults{$item},undef,$includeempty);
             if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {          } else {
                 my $maxnum = @{$settings->{'inststatusorder'}};              my $size;
                 for (my $i=0; $i<$maxnum; $i++) {              if ($item eq 'portal_def') {
                     $css_class = $rownum%2?' class="LC_odd_row"':'';                  $size = ' size="25"';
                     my $item = $settings->{'inststatusorder'}->[$i];  
                     my $title = $settings->{'inststatustypes'}->{$item};  
                     my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'$item'".');"';  
                     $datatable .= '<tr'.$css_class.'>'.  
                                   '<td><span class="LC_nobreak">'.  
                                   '<select name="inststatus_pos_'.$item.'"'.$chgstr.'>';  
                     for (my $k=0; $k<=$maxnum; $k++) {  
                         my $vpos = $k+1;  
                         my $selstr;  
                         if ($k == $i) {  
                             $selstr = ' selected="selected" ';  
                         }  
                         $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';  
                     }  
                     $datatable .= '</select>&nbsp;'.&mt('Internal ID:').'&nbsp;<b>'.$item.'</b>&nbsp;'.  
                                   '<input type="checkbox" name="inststatus_delete" value="'.$item.'" />'.  
                                   &mt('delete').'</span></td>'.  
                                   '<td class="LC_left_item"><span class="LC_nobreak">'.&mt('Name displayed:').  
                                   '<input type="text" size="20" name="inststatus_title_'.$item.'" value="'.$title.'" />'.  
                                   '</span></td></tr>';  
                 }  
                 $css_class = $rownum%2?' class="LC_odd_row"':'';  
                 my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'addinststatus_pos'".');"';  
                 $datatable .= '<tr '.$css_class.'>'.  
                               '<td><span class="LC_nobreak"><select name="addinststatus_pos"'.$chgstr.'>';  
                 for (my $k=0; $k<=$maxnum; $k++) {  
                     my $vpos = $k+1;  
                     my $selstr;  
                     if ($k == $maxnum) {  
                         $selstr = ' selected="selected" ';  
                     }  
                     $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';  
                 }  
                 $datatable .= '</select>&nbsp;'.&mt('Internal ID:').  
                               '<input type="text" size="10" name="addinststatus" value="" />'.  
                               '&nbsp;'.&mt('(new)').  
                               '</span></td><td class="LC_left_item"><span class="LC_nobreak">'.  
                               &mt('Name displayed:').  
                               '<input type="text" size="20" name="addinststatus_title" value="" /></span></td>'.  
                               '</tr>'."\n";  
                 $rownum ++;  
             }              }
               $datatable .= '<input type="text" name="'.$item.'" value="'.
                             $domdefaults{$item}.'"'.$size.' />';
         }          }
           $datatable .= '</td></tr>';
           $rownum ++;
     }      }
     $$rowtotal += $rownum;      $$rowtotal += $rownum;
     return $datatable;      return $datatable;
 }  }
   
 sub get_languages_hash {  
     my %langchoices;  
     foreach my $id (&Apache::loncommon::languageids()) {  
         my $code = &Apache::loncommon::supportedlanguagecode($id);  
         if ($code ne '') {  
             $langchoices{$code} =  &Apache::loncommon::plainlanguagedescription($id);  
         }  
     }  
     return %langchoices;  
 }  
   
 sub defaults_titles {  sub defaults_titles {
     my ($dom) = @_;      my ($dom) = @_;
     my %titles = &Apache::lonlocal::texthash (      my %titles = &Apache::lonlocal::texthash (
Line 6574  sub defaults_titles { Line 3418  sub defaults_titles {
                    'timezone_def'  => 'Default timezone',                     'timezone_def'  => 'Default timezone',
                    'datelocale_def' => 'Default locale for dates',                     'datelocale_def' => 'Default locale for dates',
                    'portal_def'     => 'Portal/Default URL',                     'portal_def'     => 'Portal/Default URL',
                    'intauth_cost'   => 'Encryption cost for bcrypt (positive integer)',  
                    'intauth_check'  => 'Check bcrypt cost if authenticated',  
                    'intauth_switch' => 'Existing crypt-based switched to bcrypt on authentication',  
                  );                   );
     if ($dom) {      if ($dom) {
         my $uprimary_id = &Apache::lonnet::domain($dom,'primary');          my $uprimary_id = &Apache::lonnet::domain($dom,'primary');
Line 6591  sub defaults_titles { Line 3432  sub defaults_titles {
     return (\%titles);      return (\%titles);
 }  }
   
 sub print_scantron {  
     my ($r,$position,$dom,$confname,$settings,$rowtotal) = @_;  
     if ($position eq 'top') {  
         return &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);  
     } else {  
         return &print_scantronconfig($dom,$settings,\$rowtotal);  
     }  
 }  
   
 sub scantron_javascript {  
     return <<"ENDSCRIPT";  
   
 <script type="text/javascript">  
 // <![CDATA[  
   
 function toggleScantron(form) {  
     var csvfieldset = new Array();  
     if (document.getElementById('scantroncsv_cols')) {  
         csvfieldset.push(document.getElementById('scantroncsv_cols'));  
     }  
     if (document.getElementById('scantroncsv_options')) {  
         csvfieldset.push(document.getElementById('scantroncsv_options'));  
     }  
     if (csvfieldset.length) {  
         if (document.getElementById('scantronconfcsv')) {  
             var scantroncsv = document.getElementById('scantronconfcsv');  
             if (scantroncsv.checked) {  
                 for (var i=0; i<csvfieldset.length; i++) {  
                     csvfieldset[i].style.display = 'block';  
                 }  
             } else {  
                 for (var i=0; i<csvfieldset.length; i++) {  
                     csvfieldset[i].style.display = 'none';  
                 }  
                 var csvselects = document.getElementsByClassName('scantronconfig_csv');  
                 if (csvselects.length) {  
                     for (var j=0; j<csvselects.length; j++) {  
                         csvselects[j].selectedIndex = 0;  
                     }  
                 }  
             }  
         }  
     }  
     return;  
 }  
 // ]]>  
 </script>  
   
 ENDSCRIPT  
   
 }  
   
 sub print_scantronformat {  sub print_scantronformat {
     my ($r,$dom,$confname,$settings,$rowtotal) = @_;      my ($r,$dom,$confname,$settings,$rowtotal) = @_;
     my $itemcount = 1;      my $itemcount = 1;
Line 6669  sub print_scantronformat { Line 3458  sub print_scantronformat {
             if ($configuserok eq 'ok') {              if ($configuserok eq 'ok') {
                 if ($author_ok eq 'ok') {                  if ($author_ok eq 'ok') {
                     my %legacyfile = (                      my %legacyfile = (
  default => $Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab',   default => $Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab', 
  custom  => $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab',   custom  => $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab', 
                     );                      );
                     my %md5chk;                      my %md5chk;
                     foreach my $type (keys(%legacyfile)) {                      foreach my $type (keys(%legacyfile)) {
Line 6679  sub print_scantronformat { Line 3468  sub print_scantronformat {
                     }                      }
                     if ($md5chk{'default'} ne $md5chk{'custom'}) {                      if ($md5chk{'default'} ne $md5chk{'custom'}) {
                         foreach my $type (keys(%legacyfile)) {                          foreach my $type (keys(%legacyfile)) {
                             ($scantronurls{$type},my $error) =                              ($scantronurls{$type},my $error) = 
                                 &legacy_scantronformat($r,$dom,$confname,                                  &legacy_scantronformat($r,$dom,$confname,
                                                  $type,$legacyfile{$type},                                                   $type,$legacyfile{$type},
                                                  $scantronurls{$type},                                                   $scantronurls{$type},
Line 6690  sub print_scantronformat { Line 3479  sub print_scantronformat {
                         }                          }
                         if (keys(%error) == 0) {                          if (keys(%error) == 0) {
                             $is_custom = 1;                              $is_custom = 1;
                             $confhash{'scantron'}{'scantronformat'} =                              $confhash{'scantron'}{'scantronformat'} = 
                                 $scantronurls{'custom'};                                  $scantronurls{'custom'};
                             my $putresult =                              my $putresult = 
                                 &Apache::lonnet::put_dom('configuration',                                  &Apache::lonnet::put_dom('configuration',
                                                          \%confhash,$dom);                                                           \%confhash,$dom);
                             if ($putresult ne 'ok') {                              if ($putresult ne 'ok') {
                                 $error{'custom'} =                                  $error{'custom'} = 
                                     '<span class="LC_error">'.                                      '<span class="LC_error">'.
                                     &mt('An error occurred updating the domain configuration: [_1]',$putresult).'</span>';                                      &mt('An error occurred updating the domain configuration: [_1]',$putresult).'</span>';
                             }                              }
Line 6752  sub print_scantronformat { Line 3541  sub print_scantronformat {
         $datatable .= '<td>'.&mt('Default in use:').'<br />'.          $datatable .= '<td>'.&mt('Default in use:').'<br />'.
                       '<span class="LC_nobreak">';                        '<span class="LC_nobreak">';
         if ($scantronurl) {          if ($scantronurl) {
             $datatable .= &Apache::loncommon::modal_link($scantronurl,&mt('Default bubblesheet format file'),600,500,              $datatable .= '<a href="'.$scantronurl.'" target="_blank">'.
                                                          undef,undef,undef,undef,'background-color:#ffffff');                            &mt('Default bubblesheet format file').'</a>';
         } else {          } else {
             $datatable = &mt('File unavailable for display');              $datatable = &mt('File unavailable for display');
         }          }
Line 6778  sub print_scantronformat { Line 3567  sub print_scantronformat {
             }               } 
             $datatable .= '<td>'.$errorstr.'</td><td>&nbsp;';              $datatable .= '<td>'.$errorstr.'</td><td>&nbsp;';
         } elsif ($scantronurl) {          } elsif ($scantronurl) {
             my $link =  &Apache::loncommon::modal_link($scantronurl,&mt('Custom bubblesheet format file'),600,500,  
                                                        undef,undef,undef,undef,'background-color:#ffffff');  
             $datatable .= '<td><span class="LC_nobreak">'.              $datatable .= '<td><span class="LC_nobreak">'.
                           $link.                            '<a href="'.$scantronurl.'" target="_blank">'.
                           '<label><input type="checkbox" name="scantronformat_del"'.                            &mt('Custom bubblesheet format file').'</a><label>'.
                           ' value="1" />'.&mt('Delete?').'</label></span></td>'.                            '<input type="checkbox" name="scantronformat_del"'.
                             '" value="1" />'.&mt('Delete?').'</label></span></td>'.
                           '<td><span class="LC_nobreak">&nbsp;'.                            '<td><span class="LC_nobreak">&nbsp;'.
                           &mt('Replace:').'</span><br />';                            &mt('Replace:').'</span><br />';
         }          }
Line 6816  sub legacy_scantronformat { Line 3604  sub legacy_scantronformat {
     return ($url,$error);      return ($url,$error);
 }  }
   
 sub print_scantronconfig {  
     my ($dom,$settings,$rowtotal) = @_;  
     my $itemcount = 2;  
     my $is_checked = ' checked="checked"';  
     my %optionson = (  
                      hdr => ' checked="checked"',  
                      pad => ' checked="checked"',  
                      rem => ' checked="checked"',  
                     );  
     my %optionsoff = (  
                       hdr => '',  
                       pad => '',  
                       rem => '',  
                      );  
     my $currcsvsty = 'none';  
     my ($datatable,%csvfields,%checked,%onclick,%csvoptions);  
     my @fields = &scantroncsv_fields();  
     my %titles = &scantronconfig_titles();  
     if (ref($settings) eq 'HASH') {  
         if (ref($settings->{config}) eq 'HASH') {  
             if ($settings->{config}->{dat}) {  
                 $checked{'dat'} = $is_checked;  
             }  
             if (ref($settings->{config}->{csv}) eq 'HASH') {  
                 if (ref($settings->{config}->{csv}->{fields}) eq 'HASH') {  
                     %csvfields = %{$settings->{config}->{csv}->{fields}};  
                     if (keys(%csvfields) > 0) {  
                         $checked{'csv'} = $is_checked;  
                         $currcsvsty = 'block';  
                     }  
                 }  
                 if (ref($settings->{config}->{csv}->{options}) eq 'HASH') {  
                     %csvoptions = %{$settings->{config}->{csv}->{options}};  
                     foreach my $option (keys(%optionson)) {  
                         unless ($csvoptions{$option}) {  
                             $optionsoff{$option} = $optionson{$option};  
                             $optionson{$option} = '';  
                         }  
                     }  
                 }  
             }  
         } else {  
             $checked{'dat'} = $is_checked;  
         }  
     } else {  
         $checked{'dat'} = $is_checked;  
     }  
     $onclick{'csv'} = ' onclick="toggleScantron(this.form);"';  
     my $css_class = $itemcount%2? ' class="LC_odd_row"':'';  
     $datatable = '<tr '.$css_class.'><td>'.&mt('Supported formats').'</td>'.  
                  '<td class="LC_left_item" valign="top"><span class="LC_nobreak">';  
     foreach my $item ('dat','csv') {  
         my $id;  
         if ($item eq 'csv') {  
             $id = 'id="scantronconfcsv" ';  
         }  
         $datatable .= '<label><input type="checkbox" name="scantronconfig" '.$id.'value="'.$item.'"'.$checked{$item}.$onclick{$item}.' />'.  
                       $titles{$item}.'</label>'.('&nbsp;'x3);  
         if ($item eq 'csv') {  
             $datatable .= '<fieldset style="display:'.$currcsvsty.'" id="scantroncsv_cols">'.  
                           '<legend>'.&mt('CSV Column Mapping').'</legend>'.  
                           '<table><tr><th>'.&mt('Field').'</th><th>'.&mt('Location').'</th></tr>'."\n";  
             foreach my $col (@fields) {  
                 my $selnone;  
                 if ($csvfields{$col} eq '') {  
                     $selnone = ' selected="selected"';  
                 }  
                 $datatable .= '<tr><td>'.$titles{$col}.'</td>'.  
                               '<td><select name="scantronconfig_csv_'.$col.'" class="scantronconfig_csv">'.  
                               '<option value=""'.$selnone.'></option>';  
                 for (my $i=0; $i<20; $i++) {  
                     my $shown = $i+1;  
                     my $sel;  
                     unless ($selnone) {  
                         if (exists($csvfields{$col})) {  
                             if ($csvfields{$col} == $i) {  
                                 $sel = ' selected="selected"';  
                             }  
                         }  
                     }  
                     $datatable .= '<option value="'.$i.'"'.$sel.'>'.$shown.'</option>';  
                 }  
                 $datatable .= '</select></td></tr>';  
            }  
            $datatable .= '</table></fieldset>'.  
                          '<fieldset style="display:'.$currcsvsty.'" id="scantroncsv_options">'.  
                          '<legend>'.&mt('CSV Options').'</legend>';  
            foreach my $option ('hdr','pad','rem') {  
                $datatable .= '<span class="LC_nobreak">'.$titles{$option}.':'.  
                          '<label><input type="radio" name="scantroncsv_'.$option.'" value="1"'.$optionson{$option}.' />'.  
                          &mt('Yes').'</label>'.('&nbsp;'x2)."\n".  
                          '<label><input type="radio" name="scantroncsv_'.$option.'" value="0"'.$optionsoff{$option}.' />'.&mt('No').'</label></span><br />';  
            }  
            $datatable .= '</fieldset>';  
            $itemcount ++;  
         }  
     }  
     $datatable .= '</td></tr>';  
     $$rowtotal ++;  
     return $datatable;  
 }  
   
 sub scantronconfig_titles {  
     return &Apache::lonlocal::texthash(  
                                           dat => 'Standard format (.dat)',  
                                           csv => 'Comma separated values (.csv)',  
                                           hdr => 'Remove first line in file (contains column titles)',  
                                           pad => 'Prepend 0s to PaperID',  
                                           rem => 'Remove leading spaces (except Question Response columns)',  
                                           CODE => 'CODE',  
                                           ID   => 'Student ID',  
                                           PaperID => 'Paper ID',  
                                           FirstName => 'First Name',  
                                           LastName => 'Last Name',  
                                           FirstQuestion => 'First Question Response',  
                                           Section => 'Section',  
     );  
 }  
   
 sub scantroncsv_fields {  
     return ('PaperID','LastName','FirstName','ID','Section','CODE','FirstQuestion');  
 }  
   
 sub print_coursecategories {  sub print_coursecategories {
     my ($position,$dom,$hdritem,$settings,$rowtotal) = @_;      my ($position,$dom,$hdritem,$settings,$rowtotal) = @_;
     my $datatable;      my $datatable;
     if ($position eq 'top') {      if ($position eq 'top') {
         my (%checked);  
         my @catitems = ('unauth','auth');  
         my @cattypes = ('std','domonly','codesrch','none');  
         $checked{'unauth'} = 'std';  
         $checked{'auth'} = 'std';  
         if (ref($settings) eq 'HASH') {  
             foreach my $type (@cattypes) {  
                 if ($type eq $settings->{'unauth'}) {  
                     $checked{'unauth'} = $type;  
                 }  
                 if ($type eq $settings->{'auth'}) {  
                     $checked{'auth'} = $type;  
                 }  
             }  
         }  
         my %lt = &Apache::lonlocal::texthash (  
                                                unauth   => 'Catalog type for unauthenticated users',  
                                                auth     => 'Catalog type for authenticated users',  
                                                none     => 'No catalog',  
                                                std      => 'Standard catalog',  
                                                domonly  => 'Domain-only catalog',  
                                                codesrch => "Code search form",  
                                              );  
        my $itemcount = 0;  
        foreach my $item (@catitems) {  
            my $css_class = $itemcount%2? ' class="LC_odd_row"':'';  
            $datatable .= '<tr '.$css_class.'>'.  
                          '<td>'.$lt{$item}.'</td>'.  
                          '<td class="LC_right_item"><span class="LC_nobreak">';  
            foreach my $type (@cattypes) {  
                my $ischecked;  
                if ($checked{$item} eq $type) {  
                    $ischecked=' checked="checked"';  
                }  
                $datatable .= '<label>'.  
                              '<input type="radio" name="coursecat_'.$item.'" value="'.$type.'"'.$ischecked.  
                              ' />'.$lt{$type}.'</label>&nbsp;';  
            }  
            $datatable .= '</span></td></tr>';  
            $itemcount ++;  
         }  
         $$rowtotal += $itemcount;  
     } elsif ($position eq 'middle') {  
         my $toggle_cats_crs = ' ';          my $toggle_cats_crs = ' ';
         my $toggle_cats_dom = ' checked="checked" ';          my $toggle_cats_dom = ' checked="checked" ';
         my $can_cat_crs = ' ';          my $can_cat_crs = ' ';
Line 7103  sub print_coursecategories { Line 3725  sub print_coursecategories {
                             }                              }
                             $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';                              $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                         }                          }
                         $datatable .= '</select></span></td><td>';                          $datatable .= '</select></td><td>';
                         if ($parent eq 'instcode' || $parent eq 'communities') {                          if ($parent eq 'instcode' || $parent eq 'communities') {
                             $datatable .=  '<span class="LC_nobreak">'                              $datatable .=  '<span class="LC_nobreak">'
                                            .$default_names{$parent}.'</span>';                                             .$default_names{$parent}.'</span>';
Line 7133  sub print_coursecategories { Line 3755  sub print_coursecategories {
                             $datatable .= '</td>';                              $datatable .= '</td>';
                         } else {                          } else {
                             $datatable .= $parent                              $datatable .= $parent
                                           .'&nbsp;<span class="LC_nobreak"><label>'                                            .'&nbsp;<label><input type="checkbox" name="deletecategory" '
                                           .'<input type="checkbox" name="deletecategory" '  
                                           .'value="'.$item.'" />'.&mt('Delete').'</label></span></td>';                                            .'value="'.$item.'" />'.&mt('Delete').'</label></span></td>';
                         }                          }
                         my $depth = 1;                          my $depth = 1;
Line 7192  sub print_coursecategories { Line 3813  sub print_coursecategories {
                 $datatable .= &initialize_categories($itemcount);                  $datatable .= &initialize_categories($itemcount);
             }              }
         } else {          } else {
             $datatable .= '<tr><td class="LC_right_item">'.$hdritem->{'header'}->[1]->{'col2'}.'</td></tr>'              $datatable .= '<td class="LC_right_item">'.$hdritem->{'header'}->[0]->{'col2'}.'</td>'
                           .&initialize_categories($itemcount);                            .&initialize_categories($itemcount);
         }          }
         $$rowtotal += $itemcount;          $$rowtotal += $itemcount;
Line 7240  sub print_serverstatuses { Line 3861  sub print_serverstatuses {
                       '<span class="LC_nobreak">'.                        '<span class="LC_nobreak">'.
                       '<input type="text" name="'.$type.'_machines" '.                        '<input type="text" name="'.$type.'_machines" '.
                       'value="'.$machineaccess{$type}.'" size="10" />'.                        'value="'.$machineaccess{$type}.'" size="10" />'.
                       '</span></td></tr>'."\n";                        '</td></tr>'."\n";
     }      }
     $$rowtotal += $rownum;      $$rowtotal += $rownum;
     return $datatable;      return $datatable;
Line 7248  sub print_serverstatuses { Line 3869  sub print_serverstatuses {
   
 sub serverstatus_pages {  sub serverstatus_pages {
     return ('userstatus','lonstatus','loncron','server-status','codeversions',      return ('userstatus','lonstatus','loncron','server-status','codeversions',
             'checksums','clusterstatus','metadata_keywords','metadata_harvest',              'clusterstatus','metadata_keywords','metadata_harvest',
             'takeoffline','takeonline','showenv','toggledebug','ping','domconf',              'takeoffline','takeonline','showenv','toggledebug','ping','domconf');
             'uniquecodes','diskusage','coursecatalog');  
 }  
   
 sub defaults_javascript {  
     my ($settings) = @_;  
     return unless (ref($settings) eq 'HASH');  
     if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {  
         my $maxnum = scalar(@{$settings->{'inststatusorder'}});  
         if ($maxnum eq '') {  
             $maxnum = 0;  
         }  
         $maxnum ++;  
         my $jstext = '    var inststatuses = Array('."'".join("','",@{$settings->{'inststatusorder'}})."'".');';    
         return <<"ENDSCRIPT";  
 <script type="text/javascript">  
 // <![CDATA[  
 function reorderTypes(form,caller) {  
     var changedVal;  
 $jstext   
     var newpos = 'addinststatus_pos';  
     var current = new Array;  
     var maxh = $maxnum;  
     var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;  
     var oldVal;  
     if (caller == newpos) {  
         changedVal = newitemVal;  
     } else {  
         var curritem = 'inststatus_pos_'+caller;  
         changedVal = form.elements[curritem].options[form.elements[curritem].selectedIndex].value;  
         current[newitemVal] = newpos;  
     }  
     for (var i=0; i<inststatuses.length; i++) {  
         if (inststatuses[i] != caller) {  
             var elementName = 'inststatus_pos_'+inststatuses[i];  
             if (form.elements[elementName]) {  
                 var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;  
                 current[currVal] = elementName;  
             }  
         }  
     }  
     for (var j=0; j<maxh; j++) {  
         if (current[j] == undefined) {  
             oldVal = j;  
         }  
     }  
     if (oldVal < changedVal) {  
         for (var k=oldVal+1; k<=changedVal ; k++) {  
            var elementName = current[k];  
            form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;  
         }  
     } else {  
         for (var k=changedVal; k<oldVal; k++) {  
             var elementName = current[k];  
             form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;  
         }  
     }  
     return;  
 }  
   
 // ]]>  
 </script>  
   
 ENDSCRIPT  
     }  
 }  
   
 sub passwords_javascript {  
     my %intalert = &Apache::lonlocal::texthash (  
         authcheck => 'Warning: disallowing login for an authenticated user if the stored cost is less than the default will require a password reset by/for the user.',  
         authcost => 'Warning: bcrypt encryption cost for internal authentication must be an integer.',  
         passmin => 'Warning: minimum password length must be a positive integer greater than 6.',  
         passmax => 'Warning: maximum password length must be a positive integer (or blank).',  
         passexp => 'Warning: days before password expiration must be a positive integer (or blank).',  
         passnum => 'Warning: number of previous passwords to save must be a positive integer (or blank).',  
     );  
     &js_escape(\%intalert);  
     my $defmin = $Apache::lonnet::passwdmin;  
     my $intauthjs = <<"ENDSCRIPT";  
   
 function warnIntAuth(field) {  
     if (field.name == 'intauth_check') {  
         if (field.value == '2') {  
             alert('$intalert{authcheck}');  
         }  
     }  
     if (field.name == 'intauth_cost') {  
         field.value.replace(/\s/g,'');  
         if (field.value != '') {  
             var regexdigit=/^\\d+\$/;  
             if (!regexdigit.test(field.value)) {  
                 alert('$intalert{authcost}');  
             }  
         }  
     }  
     return;  
 }  
   
 function warnIntPass(field) {  
     field.value.replace(/^\s+/,'');  
     field.value.replace(/\s+\$/,'');  
     var regexdigit=/^\\d+\$/;  
     if (field.name == 'passwords_min') {  
         if (field.value == '') {  
             alert('$intalert{passmin}');  
             field.value = '$defmin';  
         } else {  
             if (!regexdigit.test(field.value)) {  
                 alert('$intalert{passmin}');  
                 field.value = '$defmin';  
             }  
             var minval = parseInt(field.value,10);  
             if (minval < $defmin) {  
                 alert('$intalert{passmin}');  
                 field.value = '$defmin';  
             }  
         }  
     } else {  
         if (field.value == '0') {  
             field.value = '';  
         }  
         if (field.value != '') {  
             if (field.name == 'passwords_expire') {  
                 var regexpposnum=/^\\d+(|\\.\\d*)\$/;  
                 if (!regexpposnum.test(field.value)) {  
                     alert('$intalert{passexp}');  
                     field.value = '';  
                 } else {  
                     var expval = parseFloat(field.value);  
                     if (expval == 0) {  
                         alert('$intalert{passexp}');  
                         field.value = '';  
                     }  
                 }  
             } else {  
                 if (!regexdigit.test(field.value)) {  
                     if (field.name == 'passwords_max') {  
                         alert('$intalert{passmax}');  
                     } else {  
                         if (field.name == 'passwords_numsaved') {  
                             alert('$intalert{passnum}');  
                         }  
                     }  
                     field.value = '';  
                 }  
             }  
         }  
     }  
     return;  
 }  
   
 ENDSCRIPT  
     return &Apache::lonhtmlcommon::scripttag($intauthjs);  
 }  }
   
 sub coursecategories_javascript {  sub coursecategories_javascript {
Line 7426  sub coursecategories_javascript { Line 3895  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: [_1] is a reserved category.','"instcode"');      my $instcode_reserved = &mt('The name: "instcode" is a reserved category');
     my $communities_reserved = &mt('The name: [_1] is a reserved category.','"communities"');      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.');       my $choose_again = '\\n'.&mt('Please use a different name for the new top level category'); 
     &js_escape(\$instcode_reserved);  
     &js_escape(\$communities_reserved);  
     &js_escape(\$choose_again);  
     $output = <<"ENDSCRIPT";      $output = <<"ENDSCRIPT";
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
Line 7439  function reorderCats(form,parent,item,id Line 3905  function reorderCats(form,parent,item,id
     var changedVal;      var changedVal;
 $jstext  $jstext
     var newpos = 'addcategory_pos';      var newpos = 'addcategory_pos';
       var current = new Array;
     if (parent == '') {      if (parent == '') {
         var has_instcode = 0;          var has_instcode = 0;
         var maxtop = categories[idx].length;          var maxtop = categories[idx].length;
Line 7521  sub initialize_categories { Line 3988  sub initialize_categories {
     my $select1 = '';      my $select1 = '';
     foreach my $default ('instcode','communities') {      foreach my $default ('instcode','communities') {
         $css_class = $itemcount%2?' class="LC_odd_row"':'';          $css_class = $itemcount%2?' class="LC_odd_row"':'';
         $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','0'".');"';          $chgstr = ' onchange="javascript:reorderCats(this.form,'."'',$default"."_pos','0'".');"';
         if ($default eq 'communities') {          if ($default eq 'communities') {
             $select1 = $select0;              $select1 = $select0;
             $select0 = '';              $select0 = '';
Line 7546  sub initialize_categories { Line 4013  sub initialize_categories {
                   .'<option value="0">1</option>'                    .'<option value="0">1</option>'
                   .'<option value="1">2</option>'                    .'<option value="1">2</option>'
                   .'<option value="2" selected="selected">3</option></select>&nbsp;'                    .'<option value="2" selected="selected">3</option></select>&nbsp;'
                   .&mt('Add category').'</span></td><td><span class="LC_nobreak">'.&mt('Name:')                    .&mt('Add category').'</td><td>'.&mt('Name:')
                   .'&nbsp;<input type="text" size="20" name="addcategory_name" value="" /></span>'                    .'&nbsp;<input type="text" size="20" name="addcategory_name" value="" /></td></tr>';
                   .'</td></tr>';  
     return $datatable;      return $datatable;
 }  }
   
Line 7561  sub build_category_rows { Line 4027  sub build_category_rows {
             if (ref($cats->[$depth]{$parent}) eq 'ARRAY') {              if (ref($cats->[$depth]{$parent}) eq 'ARRAY') {
                 my $numchildren = @{$cats->[$depth]{$parent}};                  my $numchildren = @{$cats->[$depth]{$parent}};
                 my $css_class = $itemcount%2?' class="LC_odd_row"':'';                  my $css_class = $itemcount%2?' class="LC_odd_row"':'';
                 $text .= '<td><table class="LC_data_table">';                  $text .= '<td><table class="LC_datatable">';
                 my ($idxnum,$parent_name,$parent_item);                  my ($idxnum,$parent_name,$parent_item);
                 my $higher = $depth - 1;                  my $higher = $depth - 1;
                 if ($higher == 0) {                  if ($higher == 0) {
Line 7603  sub build_category_rows { Line 4069  sub build_category_rows {
                             pop(@{$path});                              pop(@{$path});
                         }                          }
                     } else {                      } else {
                         $text .= &mt('Add subcategory:').'&nbsp;</span><input type="text" 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 7626  sub build_category_rows { Line 4092  sub build_category_rows {
                 my $colspan;                  my $colspan;
                 if ($parent ne 'instcode') {                  if ($parent ne 'instcode') {
                     $colspan = $maxdepth - $depth - 1;                      $colspan = $maxdepth - $depth - 1;
                     $text .= '<td colspan="'.$colspan.'">'.&mt('Add subcategory:').'<input type="text" size="20" name="subcat_'.$name.'" value="" /></td>';                      $text .= '<td colspan="'.$colspan.'">'.&mt('Add subcategory:').'<input type="textbox" size="20" name="subcat_'.$name.'" value="" /></td>';
                 }                  }
             }              }
         }          }
Line 7635  sub build_category_rows { Line 4101  sub build_category_rows {
 }  }
   
 sub modifiable_userdata_row {  sub modifiable_userdata_row {
     my ($context,$item,$settings,$numinrow,$rowcount,$usertypes,$fieldsref,$titlesref,      my ($context,$role,$settings,$numinrow,$rowcount,$usertypes) = @_;
         $rowid,$customcss,$rowstyle) = @_;      my $rolename;
     my ($role,$rolename,$statustype);      if ($context eq 'selfcreate') {
     $role = $item;  
     if ($context eq 'cancreate') {  
         if ($item =~ /^(emailusername)_(.+)$/) {  
             $role = $1;  
             $statustype = $2;  
             if (ref($usertypes) eq 'HASH') {  
                 if ($usertypes->{$statustype}) {  
                     $rolename = &mt('Data provided by [_1]',$usertypes->{$statustype});  
                 } else {  
                     $rolename = &mt('Data provided by user');  
                 }  
             }  
         }  
     } elsif ($context eq 'selfcreate') {  
         if (ref($usertypes) eq 'HASH') {          if (ref($usertypes) eq 'HASH') {
             $rolename = $usertypes->{$role};              $rolename = $usertypes->{$role};
         } else {          } else {
Line 7664  sub modifiable_userdata_row { Line 4116  sub modifiable_userdata_row {
             $rolename = &Apache::lonnet::plaintext($role);              $rolename = &Apache::lonnet::plaintext($role);
         }          }
     }      }
     my (@fields,%fieldtitles);      my @fields = ('lastname','firstname','middlename','generation',
     if (ref($fieldsref) eq 'ARRAY') {                    'permanentemail','id');
         @fields = @{$fieldsref};      my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
     } else {  
         @fields = ('lastname','firstname','middlename','generation',  
                    'permanentemail','id');  
     }  
     if ((ref($titlesref) eq 'HASH')) {  
         %fieldtitles = %{$titlesref};  
     } else {  
         %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();  
     }  
     my $output;      my $output;
     my $css_class;      my $css_class = $rowcount%2?' class="LC_odd_row"':'';
     if ($rowcount%2) {      $output = '<tr '.$css_class.'>'.
         $css_class = 'LC_odd_row';  
     }  
     if ($customcss) {  
         $css_class .= " $customcss";  
     }  
     $css_class =~ s/^\s+//;  
     if ($css_class) {  
         $css_class = ' class="'.$css_class.'"';  
     }  
     if ($rowstyle) {  
         $css_class .= ' style="'.$rowstyle.'"';  
     }  
     if ($rowid) {  
         $rowid = ' id="'.$rowid.'"';  
     }  
   
     $output = '<tr '.$css_class.$rowid.'>'.  
               '<td><span class="LC_nobreak">'.$rolename.'</span></td>'.                '<td><span class="LC_nobreak">'.$rolename.'</span></td>'.
               '<td class="LC_left_item" colspan="2"><table>';                '<td class="LC_left_item" colspan="2"><table>';
     my $rem;      my $rem;
Line 7703  sub modifiable_userdata_row { Line 4129  sub modifiable_userdata_row {
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{$context}) eq 'HASH') {          if (ref($settings->{$context}) eq 'HASH') {
             if (ref($settings->{$context}->{$role}) eq 'HASH') {              if (ref($settings->{$context}->{$role}) eq 'HASH') {
                 my $hashref = $settings->{$context}->{$role};                  foreach my $field (@fields) {
                 if ($role eq 'emailusername') {                      if ($settings->{$context}->{$role}->{$field}) {
                     if ($statustype) {                          $checks{$field} = ' checked="checked" ';
                         if (ref($settings->{$context}->{$role}->{$statustype}) eq 'HASH') {  
                             $hashref = $settings->{$context}->{$role}->{$statustype};  
                             if (ref($hashref) eq 'HASH') {   
                                 foreach my $field (@fields) {  
                                     if ($hashref->{$field}) {  
                                         $checks{$field} = $hashref->{$field};  
                                     }  
                                 }  
                             }  
                         }  
                     }  
                 } else {  
                     if (ref($hashref) eq 'HASH') {  
                         foreach my $field (@fields) {  
                             if ($hashref->{$field}) {  
                                 $checks{$field} = ' checked="checked" ';  
                             }  
                         }  
                     }                      }
                 }                  }
             }              }
         }          }
     }      }
       for (my $i=0; $i<@fields; $i++) {
     my $total = scalar(@fields);          my $rem = $i%($numinrow);
     for (my $i=0; $i<$total; $i++) {  
         $rem = $i%($numinrow);  
         if ($rem == 0) {          if ($rem == 0) {
             if ($i > 0) {              if ($i > 0) {
                 $output .= '</tr>';                  $output .= '</tr>';
Line 7740  sub modifiable_userdata_row { Line 4146  sub modifiable_userdata_row {
             $output .= '<tr>';              $output .= '<tr>';
         }          }
         my $check = ' ';          my $check = ' ';
         unless ($role eq 'emailusername') {          if (exists($checks{$fields[$i]})) {
             if (exists($checks{$fields[$i]})) {              $check = $checks{$fields[$i]}
                 $check = $checks{$fields[$i]};          } else {
             } else {              if ($role eq 'st') {
                 if ($role eq 'st') {                  if (ref($settings) ne 'HASH') {
                     if (ref($settings) ne 'HASH') {                      $check = ' checked="checked" '; 
                         $check = ' checked="checked" ';   
                     }  
                 }                  }
             }              }
         }          }
         $output .= '<td class="LC_left_item">'.          $output .= '<td class="LC_left_item">'.
                    '<span class="LC_nobreak">';                     '<span class="LC_nobreak"><label>'.
         if ($role eq 'emailusername') {                     '<input type="checkbox" name="canmodify_'.$role.'" '.
             unless ($checks{$fields[$i]} =~ /^(required|optional)$/) {                     'value="'.$fields[$i].'"'.$check.'/>'.$fieldtitles{$fields[$i]}.
                 $checks{$fields[$i]} = 'omit';                     '</label></span></td>';
             }          $rem = @fields%($numinrow);
             foreach my $option ('required','optional','omit') {  
                 my $checked='';  
                 if ($checks{$fields[$i]} eq $option) {  
                     $checked='checked="checked" ';  
                 }  
                 $output .= '<label>'.  
                            '<input type="radio" name="canmodify_'.$item.'_'.$fields[$i].'" value="'.$option.'" '.$checked.'/>'.  
                            &mt($option).'</label>'.('&nbsp;' x2);  
             }  
             $output .= '<i>'.$fieldtitles{$fields[$i]}.'</i>';  
         } else {  
             $output .= '<label>'.  
                        '<input type="checkbox" name="canmodify_'.$role.'" '.  
                        'value="'.$fields[$i].'"'.$check.'/>'.$fieldtitles{$fields[$i]}.  
                        '</label>';  
         }  
         $output .= '</span></td>';  
     }  
     $rem = $total%$numinrow;  
     my $colsleft;  
     if ($rem) {  
         $colsleft = $numinrow - $rem;  
     }      }
     if ($colsleft > 1) {      my $colsleft = $numinrow - $rem;
       if ($colsleft > 1 ) {
         $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.          $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                    '&nbsp;</td>';                     '&nbsp;</td>';
     } elsif ($colsleft == 1) {      } elsif ($colsleft == 1) {
Line 7791  sub modifiable_userdata_row { Line 4174  sub modifiable_userdata_row {
 }  }
   
 sub insttypes_row {  sub insttypes_row {
     my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context,$rowtotal,$onclick,      my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context) = @_;
         $customcss,$rowstyle) = @_;  
     my %lt = &Apache::lonlocal::texthash (      my %lt = &Apache::lonlocal::texthash (
                       cansearch => 'Users allowed to search',                        cansearch => 'Users allowed to search',
                       statustocreate => 'Institutional affiliation(s) able to create own account (login/SSO)',                        statustocreate => 'Institutional affiliation(s) able to create own account (login/SSO)',
                       lockablenames => 'User preference to lock name',                        lockablenames => 'User preference to lock name',
                       selfassign    => 'Self-reportable affiliations',  
                       overrides     => "Override domain's helpdesk settings based on requester's affiliation",  
              );               );
     my $showdom;      my $showdom;
     if ($context eq 'cansearch') {      if ($context eq 'cansearch') {
         $showdom = ' ('.$dom.')';          $showdom = ' ('.$dom.')';
     }      }
     my $class = 'LC_left_item';      my $output =  '<tr class="LC_odd_row">'.
     if ($context eq 'statustocreate') {                    '<td>'.$lt{$context}.$showdom.
         $class = 'LC_right_item';                    '</td><td class="LC_left_item" colspan="2"><table>';
     }  
     my $css_class;  
     if ($$rowtotal%2) {  
         $css_class = 'LC_odd_row';  
     }  
     if ($customcss) {  
         $css_class .= ' '.$customcss;  
     }  
     $css_class =~ s/^\s+//;  
     if ($css_class) {  
         $css_class = ' class="'.$css_class.'"';  
     }  
     if ($rowstyle) {  
         $css_class .= ' style="'.$rowstyle.'"';  
     }  
     if ($onclick) {  
         $onclick = 'onclick="'.$onclick.'" ';  
     }  
     my $output = '<tr'.$css_class.'>'.  
                  '<td>'.$lt{$context}.$showdom.  
                  '</td><td class="'.$class.'" colspan="2"><table>';  
     my $rem;      my $rem;
     if (ref($types) eq 'ARRAY') {      if (ref($types) eq 'ARRAY') {
         for (my $i=0; $i<@{$types}; $i++) {          for (my $i=0; $i<@{$types}; $i++) {
Line 7845  sub insttypes_row { Line 4204  sub insttypes_row {
                         if (grep(/^\Q$types->[$i]\E$/,@{$settings->{$context}})) {                          if (grep(/^\Q$types->[$i]\E$/,@{$settings->{$context}})) {
                             $check = ' checked="checked" ';                              $check = ' checked="checked" ';
                         }                          }
                     } elsif (ref($settings->{$context}) eq 'HASH') {  
                         if (ref($settings->{$context}->{$types->[$i]}) eq 'HASH') {  
                             $check = ' checked="checked" ';  
                         }  
                     } elsif ($context eq 'statustocreate') {                      } elsif ($context eq 'statustocreate') {
                         $check = ' checked="checked" ';                          $check = ' checked="checked" ';
                     }                      }
Line 7856  sub insttypes_row { Line 4211  sub insttypes_row {
                 $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="'.$context.'" '.                             '<input type="checkbox" name="'.$context.'" '.
                            'value="'.$types->[$i].'"'.$check.$onclick.'/>'.                             '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 ($context eq 'overrides') {      if (($rem == 0) && (@{$types} > 0)) {
         if ($colsleft > 1) {          $output .= '<tr>';
             $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">';      }
         } else {      if ($colsleft > 1) {
             $output .= '<td class="LC_left_item">';          $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
         }  
         $output .= '&nbsp;';  
     } else {      } else {
         if ($rem == 0) {          $output .= '<td class="LC_left_item">';
             $output .= '<tr>';      }
         }      my $defcheck = ' ';
         if ($colsleft > 1) {      if (ref($settings) eq 'HASH') {  
             $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">';          if (ref($settings->{$context}) eq 'ARRAY') {
         } else {              if (grep(/^default$/,@{$settings->{$context}})) {
             $output .= '<td class="LC_left_item">';  
         }  
         my $defcheck = ' ';  
         if (ref($settings) eq 'HASH') {    
             if (ref($settings->{$context}) eq 'ARRAY') {  
                 if (grep(/^default$/,@{$settings->{$context}})) {  
                     $defcheck = ' checked="checked" ';  
                 }  
             } elsif ($context eq 'statustocreate') {  
                 $defcheck = ' checked="checked" ';                  $defcheck = ' checked="checked" ';
             }              }
           } elsif ($context eq 'statustocreate') {
               $defcheck = ' checked="checked" ';
         }          }
         $output .= '<span class="LC_nobreak"><label>'.  
                    '<input type="checkbox" name="'.$context.'" '.  
                    'value="default"'.$defcheck.$onclick.' />'.  
                    $othertitle.'</label></span>';  
     }      }
     $output .= '</td></tr></table></td></tr>';      $output .= '<span class="LC_nobreak"><label>'.
                  '<input type="checkbox" name="'.$context.'" '.
                  'value="default"'.$defcheck.'/>'.
                  $othertitle.'</label></span></td>'.
                  '</tr></table></td></tr>';
     return $output;      return $output;
 }  }
   
Line 7969  sub usertype_update_row { Line 4315  sub usertype_update_row {
 }  }
   
 sub modify_login {  sub modify_login {
     my ($r,$dom,$confname,$lastactref,%domconfig) = @_;      my ($r,$dom,$confname,%domconfig) = @_;
     my ($resulttext,$errors,$colchgtext,%changes,%colchanges,%newfile,%newurl,      my ($resulttext,$errors,$colchgtext,%changes,%colchanges);
         %curr_loginvia,%loginhash,@currlangs,@newlangs,$addedfile,%title,@offon);      my %title = ( coursecatalog => 'Display course catalog',
     %title = ( coursecatalog => 'Display course catalog',                    adminmail => 'Display administrator E-mail address',
                adminmail => 'Display administrator E-mail address',                    newuser => 'Link for visitors to create a user account',
                helpdesk  => 'Display "Contact Helpdesk" link',                    loginheader => 'Log-in box header');
                newuser => 'Link for visitors to create a user account',      my @offon = ('off','on');
                loginheader => 'Log-in box header');      my %curr_loginvia;
     @offon = ('off','on');  
     if (ref($domconfig{login}) eq 'HASH') {      if (ref($domconfig{login}) eq 'HASH') {
         if (ref($domconfig{login}{loginvia}) eq 'HASH') {          if (ref($domconfig{login}{loginvia}) eq 'HASH') {
             foreach my $lonhost (keys(%{$domconfig{login}{loginvia}})) {              foreach my $lonhost (keys(%{$domconfig{login}{loginvia}})) {
Line 7985  sub modify_login { Line 4330  sub modify_login {
             }              }
         }          }
     }      }
       my %loginhash;
     ($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'],      ($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'],
                                            \%domconfig,\%loginhash);                                             \%domconfig,\%loginhash);
     my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');      my @toggles = ('coursecatalog','adminmail','newuser');
     foreach my $item (@toggles) {      foreach my $item (@toggles) {
         $loginhash{login}{$item} = $env{'form.'.$item};          $loginhash{login}{$item} = $env{'form.'.$item};
     }      }
Line 7998  sub modify_login { Line 4344  sub modify_login {
     }      }
   
     my %servers = &Apache::lonnet::internet_dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
     my %domservers = &Apache::lonnet::get_servers($dom);  
     my @loginvia_attribs = ('serverpath','custompath','exempt');      my @loginvia_attribs = ('serverpath','custompath','exempt');
     if (keys(%servers) > 1) {      if (keys(%servers) > 1) {
         foreach my $lonhost (keys(%servers)) {          foreach my $lonhost (keys(%servers)) {
Line 8041  sub modify_login { Line 4386  sub modify_login {
                             $changes{'loginvia'}{$lonhost} = 1;                              $changes{'loginvia'}{$lonhost} = 1;
                         }                          }
                         if ($item eq 'exempt') {                          if ($item eq 'exempt') {
                             $new = &check_exempt_addresses($new);                              $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;                          $loginhash{login}{loginvia}{$lonhost}{$item} = $new;
                     }                      }
                 }                  }
Line 8068  sub modify_login { Line 4429  sub modify_login {
         }          }
     }      }
   
     my $servadm = $r->dir_config('lonAdmEMail');  
     my %langchoices = &Apache::lonlocal::texthash(&get_languages_hash());  
     if (ref($domconfig{'login'}) eq 'HASH') {  
         if (ref($domconfig{'login'}{'helpurl'}) eq 'HASH') {  
             foreach my $lang (sort(keys(%{$domconfig{'login'}{'helpurl'}}))) {  
                 if ($lang eq 'nolang') {  
                     push(@currlangs,$lang);  
                 } elsif (defined($langchoices{$lang})) {  
                     push(@currlangs,$lang);  
                 } else {  
                     next;  
                 }  
             }  
         }  
     }  
     my @delurls = &Apache::loncommon::get_env_multiple('form.loginhelpurl_del');  
     if (@currlangs > 0) {  
         foreach my $lang (@currlangs) {  
             if (grep(/^\Q$lang\E$/,@delurls)) {  
                 $changes{'helpurl'}{$lang} = 1;  
             } elsif ($env{'form.loginhelpurl_'.$lang.'.filename'}) {  
                 $changes{'helpurl'}{$lang} = 1;  
                 $newfile{$lang} = $env{'form.loginhelpurl_'.$lang.'.filename'};  
                 push(@newlangs,$lang);  
             } else {  
                 $loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang};  
             }  
         }  
     }  
     unless (grep(/^nolang$/,@currlangs)) {  
         if ($env{'form.loginhelpurl_nolang.filename'}) {  
             $changes{'helpurl'}{'nolang'} = 1;  
             $newfile{'nolang'} = $env{'form.loginhelpurl_nolang.filename'};  
             push(@newlangs,'nolang');  
         }  
     }  
     if ($env{'form.loginhelpurl_add_lang'}) {  
         if ((defined($langchoices{$env{'form.loginhelpurl_add_lang'}})) &&  
             ($env{'form.loginhelpurl_add_file.filename'})) {  
             $newfile{$env{'form.loginhelpurl_add_lang'}} = $env{'form.loginhelpurl_add_file.filename'};  
             $addedfile = $env{'form.loginhelpurl_add_lang'};  
         }  
     }  
     if ((@newlangs > 0) || ($addedfile)) {  
         my $error;  
         my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);  
         if ($configuserok eq 'ok') {  
             if ($switchserver) {  
                 $error = &mt("Upload of custom help file is not permitted to this server: [_1]",$switchserver);  
             } elsif ($author_ok eq 'ok') {  
                 my @allnew = @newlangs;  
                 if ($addedfile ne '') {  
                     push(@allnew,$addedfile);  
                 }  
                 foreach my $lang (@allnew) {  
                     my $formelem = 'loginhelpurl_'.$lang;  
                     if ($lang eq $env{'form.loginhelpurl_add_lang'}) {  
                         $formelem = 'loginhelpurl_add_file';  
                     }  
                     (my $result,$newurl{$lang}) = &publishlogo($r,'upload',$formelem,$dom,$confname,  
                                                                "help/$lang",'','',$newfile{$lang});  
                     if ($result eq 'ok') {  
                         $loginhash{'login'}{'helpurl'}{$lang} = $newurl{$lang};  
                         $changes{'helpurl'}{$lang} = 1;  
                     } else {  
                         my $puberror = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$newfile{$lang},$result);  
                         $errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';  
                         if ((grep(/^\Q$lang\E$/,@currlangs)) &&  
                             (!grep(/^\Q$lang\E$/,@delurls))) {  
                             $loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang};  
                         }  
                     }  
                 }  
             } else {  
                 $error = &mt("Upload of custom log-in help file(s) failed because an author role could not be assigned to a Domain Configuration user ([_1]) in domain: [_2].  Error was: [_3].",$confname,$dom,$author_ok);  
             }  
         } else {  
             $error = &mt("Upload of custom log-in help file(s) failed because a Domain Configuration user ([_1]) could not be created in domain: [_2].  Error was: [_3].",$confname,$dom,$configuserok);  
         }  
         if ($error) {  
             &Apache::lonnet::logthis($error);  
             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';  
         }  
     }  
   
     my (%currheadtagurls,%currexempt,@newhosts,%newheadtagurls,%possexempt);  
     if (ref($domconfig{'login'}) eq 'HASH') {  
         if (ref($domconfig{'login'}{'headtag'}) eq 'HASH') {  
             foreach my $lonhost (keys(%{$domconfig{'login'}{'headtag'}})) {  
                 if ($domservers{$lonhost}) {  
                     if (ref($domconfig{'login'}{'headtag'}{$lonhost}) eq 'HASH') {  
                         $currheadtagurls{$lonhost} = $domconfig{'login'}{'headtag'}{$lonhost}{'url'};  
                         $currexempt{$lonhost} = $domconfig{'login'}{'headtag'}{$lonhost}{'exempt'};  
                     }  
                 }  
             }  
         }  
     }  
     my @delheadtagurls = &Apache::loncommon::get_env_multiple('form.loginheadtag_del');  
     foreach my $lonhost (sort(keys(%domservers))) {  
         if (grep(/^\Q$lonhost\E$/,@delheadtagurls)) {  
             $changes{'headtag'}{$lonhost} = 1;  
         } else {  
             if ($env{'form.loginheadtagexempt_'.$lonhost}) {  
                 $possexempt{$lonhost} = &check_exempt_addresses($env{'form.loginheadtagexempt_'.$lonhost});  
             }  
             if ($env{'form.loginheadtag_'.$lonhost.'.filename'}) {  
                 push(@newhosts,$lonhost);  
             } elsif ($currheadtagurls{$lonhost}) {  
                 $loginhash{'login'}{'headtag'}{$lonhost}{'url'} = $currheadtagurls{$lonhost};  
                 if ($currexempt{$lonhost}) {  
                     if ((!exists($possexempt{$lonhost})) || ($possexempt{$lonhost} ne $currexempt{$lonhost})) {  
                         $changes{'headtag'}{$lonhost} = 1;  
                     }  
                 } elsif ($possexempt{$lonhost}) {  
                     $changes{'headtag'}{$lonhost} = 1;  
                 }  
                 if ($possexempt{$lonhost}) {  
                     $loginhash{'login'}{'headtag'}{$lonhost}{'exempt'} = $possexempt{$lonhost};  
                 }  
             }  
         }  
     }  
     if (@newhosts) {  
         my $error;  
         my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);  
         if ($configuserok eq 'ok') {  
             if ($switchserver) {  
                 $error = &mt("Upload of custom markup is not permitted to this server: [_1]",$switchserver);  
             } elsif ($author_ok eq 'ok') {  
                 foreach my $lonhost (@newhosts) {  
                     my $formelem = 'loginheadtag_'.$lonhost;  
                     (my $result,$newheadtagurls{$lonhost}) = &publishlogo($r,'upload',$formelem,$dom,$confname,  
                                                                           "login/headtag/$lonhost",'','',  
                                                                           $env{'form.loginheadtag_'.$lonhost.'.filename'});  
                     if ($result eq 'ok') {  
                         $loginhash{'login'}{'headtag'}{$lonhost}{'url'} = $newheadtagurls{$lonhost};  
                         $changes{'headtag'}{$lonhost} = 1;  
                         if ($possexempt{$lonhost}) {  
                             $loginhash{'login'}{'headtag'}{$lonhost}{'exempt'} = $possexempt{$lonhost};  
                         }  
                     } else {  
                         my $puberror = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",  
                                            $newheadtagurls{$lonhost},$result);  
                         $errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';  
                         if ((grep(/^\Q$lonhost\E$/,keys(%currheadtagurls))) &&  
                             (!grep(/^\Q$lonhost\E$/,@delheadtagurls))) {  
                             $loginhash{'login'}{'headtag'}{$lonhost} = $currheadtagurls{$lonhost};  
                         }  
                     }  
                 }  
             } else {  
                 $error = &mt("Upload of custom markup 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 markup file(s) failed because a Domain Configuration user ([_1]) could not be created in domain: [_2].  Error was: [_3].",$confname,$dom,$configuserok);  
         }  
         if ($error) {  
             &Apache::lonnet::logthis($error);  
             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';  
         }  
     }  
     &process_captcha('login',\%changes,$loginhash{'login'},$domconfig{'login'});  
   
     my $defaulthelpfile = '/adm/loginproblems.html';  
     my $defaulttext = &mt('Default in use');  
   
     my $putresult = &Apache::lonnet::put_dom('configuration',\%loginhash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%loginhash,
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');          my @toggles = ('coursecatalog','adminmail','newuser');
         my %defaultchecked = (          my %defaultchecked = (
                     'coursecatalog' => 'on',                      'coursecatalog' => 'on',
                     'helpdesk'      => 'on',  
                     'adminmail'     => 'off',                      'adminmail'     => 'off',
                     'newuser'       => 'off',                      'newuser'       => 'off',
         );          );
Line 8270  sub modify_login { Line 4463  sub modify_login {
         }          }
         if (keys(%changes) > 0 || $colchgtext) {          if (keys(%changes) > 0 || $colchgtext) {
             &Apache::loncommon::devalidate_domconfig_cache($dom);              &Apache::loncommon::devalidate_domconfig_cache($dom);
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'domainconfig'} = 1;  
             }  
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
                 if ($item eq 'loginvia') {                  if ($item eq 'loginvia') {
Line 8304  sub modify_login { Line 4494  sub modify_login {
                         }                          }
                         $resulttext .= '</ul></li>';                          $resulttext .= '</ul></li>';
                     }                      }
                 } elsif ($item eq 'helpurl') {  
                     if (ref($changes{$item}) eq 'HASH') {  
                         foreach my $lang (sort(keys(%{$changes{$item}}))) {  
                             if (grep(/^\Q$lang\E$/,@delurls)) {  
                                 my ($chg,$link);  
                                 $link = &Apache::loncommon::modal_link($defaulthelpfile,$defaulttext,600,500);  
                                 if ($lang eq 'nolang') {  
                                     $chg = &mt('custom log-in help file removed for no preferred language; [_1]',$link);  
                                 } else {  
                                     $chg = &mt('custom log-in help file removed for specific language: [_1]; [_2]',$langchoices{$lang},$link);  
                                 }  
                                 $resulttext .= '<li>'.$chg.'</li>';  
                             } else {  
                                 my $chg;  
                                 if ($lang eq 'nolang') {  
                                     $chg = &mt('custom log-in help file for no preferred language');  
                                 } else {  
                                     $chg = &mt('custom log-in help file for specific language: [_1]',$langchoices{$lang});  
                                 }  
                                 $resulttext .= '<li>'.&Apache::loncommon::modal_link(  
                                                       $loginhash{'login'}{'helpurl'}{$lang}.  
                                                       '?inhibitmenu=yes',$chg,600,500).  
                                                '</li>';  
                             }  
                         }  
                     }  
                 } elsif ($item eq 'headtag') {  
                     if (ref($changes{$item}) eq 'HASH') {  
                         foreach my $lonhost (sort(keys(%{$changes{$item}}))) {  
                             if (grep(/^\Q$lonhost\E$/,@delheadtagurls)) {  
                                 $resulttext .= '<li>'.&mt('custom markup file removed for [_1]',$domservers{$lonhost}).'</li>';  
                             } elsif (ref($loginhash{'login'}{'headtag'}{$lonhost}) eq 'HASH') {  
                                 $resulttext .= '<li><a href="'.  
                                                "javascript:void(open('$loginhash{'login'}{'headtag'}{$lonhost}{'url'}?inhibitmenu=yes','Custom_HeadTag',  
                                                'menubar=0,toolbar=1,scrollbars=1,width=600,height=500,resizable=yes'))".  
                                                '">'.&mt('custom markup').'</a> '.&mt('(for [_1])',$servers{$lonhost}).' ';  
                                 if ($possexempt{$lonhost}) {  
                                     $resulttext .= &mt('not included for client IP(s): [_1]',$possexempt{$lonhost});  
                                 } else {  
                                     $resulttext .= &mt('included for any client IP');  
                                 }  
                                 $resulttext .= '</li>';  
                             }  
                         }  
                     }  
                 } elsif ($item eq 'captcha') {  
                     if (ref($loginhash{'login'}) eq 'HASH') {  
                         my $chgtxt;  
                         if ($loginhash{'login'}{$item} eq 'notused') {  
                             $chgtxt .= &mt('No CAPTCHA validation in use for helpdesk form.');  
                         } else {  
                             my %captchas = &captcha_phrases();  
                             if ($captchas{$loginhash{'login'}{$item}}) {  
                                 $chgtxt .= &mt("Validation for helpdesk form set to $captchas{$loginhash{'login'}{$item}}.");  
                             } else {  
                                 $chgtxt .= &mt('Validation for helpdesk form set to unknown type.');  
                             }  
                         }  
                         $resulttext .= '<li>'.$chgtxt.'</li>';  
                     }  
                 } elsif ($item eq 'recaptchakeys') {  
                     if (ref($loginhash{'login'}) eq 'HASH') {  
                         my ($privkey,$pubkey);  
                         if (ref($loginhash{'login'}{$item}) eq 'HASH') {  
                             $pubkey = $loginhash{'login'}{$item}{'public'};  
                             $privkey = $loginhash{'login'}{$item}{'private'};  
                         }  
                         my $chgtxt .= &mt('ReCAPTCHA keys changes').'<ul>';  
                         if (!$pubkey) {  
                             $chgtxt .= '<li>'.&mt('Public key deleted').'</li>';  
                         } else {  
                             $chgtxt .= '<li>'.&mt('Public key set to [_1]',$pubkey).'</li>';  
                         }  
                         if (!$privkey) {  
                             $chgtxt .= '<li>'.&mt('Private key deleted').'</li>';  
                         } else {  
                             $chgtxt .= '<li>'.&mt('Private key set to [_1]',$privkey).'</li>';  
                         }  
                         $chgtxt .= '</ul>';  
                         $resulttext .= '<li>'.$chgtxt.'</li>';  
                     }  
                 } elsif ($item eq 'recaptchaversion') {  
                     if (ref($loginhash{'login'}) eq 'HASH') {  
                         if ($loginhash{'login'}{'captcha'} eq 'recaptcha') {  
                             $resulttext .= '<li>'.&mt('ReCAPTCHA for helpdesk form set to version [_1]',$loginhash{'login'}{'recaptchaversion'}).  
                                            '</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 8411  sub modify_login { Line 4513  sub modify_login {
     return $resulttext;      return $resulttext;
 }  }
   
 sub check_exempt_addresses {  
     my ($iplist) = @_;  
     $iplist =~ s/^\s+//;  
     $iplist =~ s/\s+$//;  
     my @poss_ips = split(/\s*[,:]\s*/,$iplist);  
     my (@okips,$new);  
     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 = '';  
     }  
     return $new;  
 }  
   
 sub color_font_choices {  sub color_font_choices {
     my %choices =      my %choices =
         &Apache::lonlocal::texthash (          &Apache::lonlocal::texthash (
Line 8440  sub color_font_choices { Line 4521  sub color_font_choices {
             links => "Link colors",              links => "Link colors",
             images => "Images",              images => "Images",
             font => "Font color",              font => "Font color",
             fontmenu => "Font menu",              fontmenu => "Font Menu",
             pgbg => "Page",              pgbg => "Page",
             tabbg => "Header",              tabbg => "Header",
             sidebg => "Border",              sidebg => "Border",
Line 8452  sub color_font_choices { Line 4533  sub color_font_choices {
 }  }
   
 sub modify_rolecolors {  sub modify_rolecolors {
     my ($r,$dom,$confname,$roles,$lastactref,%domconfig) = @_;      my ($r,$dom,$confname,$roles,%domconfig) = @_;
     my ($resulttext,%rolehash);      my ($resulttext,%rolehash);
     $rolehash{'rolecolors'} = {};      $rolehash{'rolecolors'} = {};
     if (ref($domconfig{'rolecolors'}) ne 'HASH') {      if (ref($domconfig{'rolecolors'}) ne 'HASH') {
Line 8467  sub modify_rolecolors { Line 4548  sub modify_rolecolors {
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             &Apache::loncommon::devalidate_domconfig_cache($dom);              &Apache::loncommon::devalidate_domconfig_cache($dom);
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'domainconfig'} = 1;  
             }  
             $resulttext = &display_colorchgs($dom,\%changes,$roles,              $resulttext = &display_colorchgs($dom,\%changes,$roles,
                                              $rolehash{'rolecolors'});                                               $rolehash{'rolecolors'});
         } else {          } else {
Line 8495  sub modify_colors { Line 4573  sub modify_colors {
     my @images;      my @images;
     my $servadm = $r->dir_config('lonAdmEMail');      my $servadm = $r->dir_config('lonAdmEMail');
     my $errors;      my $errors;
     my %defaults;  
     foreach my $role (@{$roles}) {      foreach my $role (@{$roles}) {
         if ($role eq 'login') {          if ($role eq 'login') {
             %choices = &login_choices();              %choices = &login_choices();
             @logintext = ('textcol','bgcol');              @logintext = ('textcol','bgcol');
         } else {          } else {
             %choices = &color_font_choices();              %choices = &color_font_choices();
               $confhash->{$role}{'fontmenu'} = $env{'form.'.$role.'_fontmenu'};
         }          }
         if ($role eq 'login') {          if ($role eq 'login') {
             @images = ('img','logo','domlogo','login');              @images = ('img','logo','domlogo','login');
             @bgs = ('pgbg','mainbg','sidebg');              @bgs = ('pgbg','mainbg','sidebg');
         } else {          } else {
             @images = ('img');              @images = ('img');
             @bgs = ('pgbg','tabbg','sidebg');              @bgs = ('pgbg','tabbg','sidebg'); 
         }  
         my %defaults = &role_defaults($role,\@bgs,\@links,\@images,\@logintext);  
         unless ($env{'form.'.$role.'_font'} eq $defaults{'font'}) {  
             $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'};  
         }  
         if ($role eq 'login') {  
             foreach my $item (@logintext) {  
                 $env{'form.'.$role.'_'.$item} = lc($env{'form.'.$role.'_'.$item});  
                 if ($env{'form.'.$role.'_'.$item} =~ /^\w+/) {  
                     $env{'form.'.$role.'_'.$item} = '#'.$env{'form.'.$role.'_'.$item};  
                 }  
                 unless ($env{'form.'.$role.'_'.$item} eq lc($defaults{'logintext'}{$item})) {  
                     $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};  
                 }  
             }  
         } else {  
             $env{'form.'.$role.'_fontmenu'} = lc($env{'form.'.$role.'_fontmenu'});  
             if ($env{'form.'.$role.'_fontmenu'} =~ /^\w+/) {  
                 $env{'form.'.$role.'_fontmenu'} = '#'.$env{'form.'.$role.'_fontmenu'};  
             }  
             unless($env{'form.'.$role.'_fontmenu'} eq lc($defaults{'fontmenu'})) {  
                 $confhash->{$role}{'fontmenu'} = $env{'form.'.$role.'_fontmenu'};  
             }  
         }  
         foreach my $item (@bgs) {  
             $env{'form.'.$role.'_'.$item} = lc($env{'form.'.$role.'_'.$item});  
             if ($env{'form.'.$role.'_'.$item} =~ /^\w+/) {  
                 $env{'form.'.$role.'_'.$item} = '#'.$env{'form.'.$role.'_'.$item};  
             }  
             unless ($env{'form.'.$role.'_'.$item} eq lc($defaults{'bgs'}{$item})) {  
                 $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};  
             }  
         }          }
         foreach my $item (@links) {          $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'};
             $env{'form.'.$role.'_'.$item} = lc($env{'form.'.$role.'_'.$item});          foreach my $item (@bgs,@links,@logintext) {
             if ($env{'form.'.$role.'_'.$item} =~ /^\w+/) {              $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
                 $env{'form.'.$role.'_'.$item} = '#'.$env{'form.'.$role.'_'.$item};  
             }  
             unless ($env{'form.'.$role.'_'.$item} eq lc($defaults{'links'}{$item})) {  
                 $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};  
             }  
         }          }
         my ($configuserok,$author_ok,$switchserver) =           my ($configuserok,$author_ok,$switchserver) = 
             &config_check($dom,$confname,$servadm);              &config_check($dom,$confname,$servadm);
Line 8854  sub check_configuser { Line 4895  sub check_configuser {
     my ($configuserok,%currroles);      my ($configuserok,%currroles);
     if ($uhome eq 'no_host') {      if ($uhome eq 'no_host') {
         srand( time() ^ ($$ + ($$ << 15))  ); # Seed rand.          srand( time() ^ ($$ + ($$ << 15))  ); # Seed rand.
         my $configpass = &LONCAPA::Enrollment::create_password($dom);          my $configpass = &LONCAPA::Enrollment::create_password();
         $configuserok =           $configuserok = 
             &Apache::lonnet::modifyuser($dom,$confname,'','internal',              &Apache::lonnet::modifyuser($dom,$confname,'','internal',
                              $configpass,'','','','','',undef,$servadm);                               $configpass,'','','','','',undef,$servadm);
Line 8897  sub publishlogo { Line 4938  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 $docroot=$r->dir_config('lonDocRoot');      my $filepath=$r->dir_config('lonDocRoot')."/priv/$dom/$confname";
     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/$relpath/$fnamepath");      my @parts=split(/\//,$filepath.'/'.$fnamepath);
     my $count;      my $count;
     for ($count=5;$count<=$#parts;$count++) {      for ($count=4;$count<=$#parts;$count++) {
         $filepath.="/$parts[$count]";          $filepath.="/$parts[$count]";
         if ((-e $filepath)!=1) {          if ((-e $filepath)!=1) {
             mkdir($filepath,02770);              mkdir($filepath,02770);
Line 8917  sub publishlogo { Line 4956  sub publishlogo {
     if ($file=~/\.(\w+)$/ &&      if ($file=~/\.(\w+)$/ &&
         (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {          (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {
         $output =           $output = 
             &mt('Invalid file extension ([_1]) - reserved for internal use.',$1);               &mt('Invalid file extension ([_1]) - reserved for LONCAPA use.',$1); 
     } elsif ($file=~/\.(\w+)$/ &&      } elsif ($file=~/\.(\w+)$/ &&
         !defined(&Apache::loncommon::fileembstyle($1))) {          !defined(&Apache::loncommon::fileembstyle($1))) {
         $output = &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1);          $output = &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1);
     } elsif ($file=~/\.(\d+)\.(\w+)$/) {      } elsif ($file=~/\.(\d+)\.(\w+)$/) {
         $output = &mt('Filename not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2);          $output = &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2);
     } elsif (-d "$filepath/$file") {      } elsif (-d "$filepath/$file") {
         $output = &mt('Filename is a directory name - rename the file and re-upload');          $output = &mt('File name is a directory name - rename the file and re-upload');
     } else {      } else {
         my $source = $filepath.'/'.$file;          my $source = $filepath.'/'.$file;
         my $logfile;          my $logfile;
         if (!open($logfile,">>",$source.'.log')) {          if (!open($logfile,">>$source".'.log')) {
             return (&mt('No write permission to Authoring Space'));              return (&mt('No write permission to Construction Space'));
         }          }
         print $logfile          print $logfile
 "\n================= Publish ".localtime()." ================\n".  "\n================= Publish ".localtime()." ================\n".
 $env{'user.name'}.':'.$env{'user.domain'}."\n";  $env{'user.name'}.':'.$env{'user.domain'}."\n";
 # Save the file  # Save the file
         if (!open(FH,">",$source)) {          if (!open(FH,'>'.$source)) {
             &Apache::lonnet::logthis('Failed to create '.$source);              &Apache::lonnet::logthis('Failed to create '.$source);
             return (&mt('Failed to create file'));              return (&mt('Failed to create file'));
         }          }
Line 8954  $env{'user.name'}.':'.$env{'user.domain' Line 4993  $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 8996  $env{'user.name'}.':'.$env{'user.domain' Line 5036  $env{'user.name'}.':'.$env{'user.domain'
                 if ($fullwidth ne '' && $fullheight ne '') {                   if ($fullwidth ne '' && $fullheight ne '') { 
                     if ($fullwidth > $thumbwidth && $fullheight > $thumbheight) {                      if ($fullwidth > $thumbwidth && $fullheight > $thumbheight) {
                         my $thumbsize = $thumbwidth.'x'.$thumbheight;                          my $thumbsize = $thumbwidth.'x'.$thumbheight;
                         my @args = ('convert','-sample',$thumbsize,$inputfile,$outfile);                          system("convert -sample $thumbsize $inputfile $outfile");
                         system({$args[0]} @args);  
                         chmod(0660, $filepath.'/tn-'.$file);                          chmod(0660, $filepath.'/tn-'.$file);
                         if (-e $outfile) {                          if (-e $outfile) {
                             my $copyfile=$targetdir.'/tn-'.$file;                              my $copyfile=$targetdir.'/tn-'.$file;
Line 9076  sub write_metadata { Line 5115  sub write_metadata {
     {      {
         print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file;          print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file;
         my $mfh;          my $mfh;
         if (open($mfh,">",$targetdir.'/'.$file.'.meta')) {          if (open($mfh,'>'.$targetdir.'/'.$file.'.meta')) {
             foreach (sort(keys(%metadatafields))) {              foreach (sort keys %metadatafields) {
                 unless ($_=~/\./) {                  unless ($_=~/\./) {
                     my $unikey=$_;                      my $unikey=$_;
                     $unikey=~/^([A-Za-z]+)/;                      $unikey=~/^([A-Za-z]+)/;
Line 9110  sub notifysubscribed { Line 5149  sub notifysubscribed {
         next unless (ref($targetsource) eq 'ARRAY');          next unless (ref($targetsource) eq 'ARRAY');
         my ($target,$source)=@{$targetsource};          my ($target,$source)=@{$targetsource};
         if ($source ne '') {          if ($source ne '') {
             if (open(my $logfh,">>",$source.'.log')) {              if (open(my $logfh,'>>'.$source.'.log')) {
                 print $logfh "\nCleanup phase: Notifications\n";                  print $logfh "\nCleanup phase: Notifications\n";
                 my @subscribed=&subscribed_hosts($target);                  my @subscribed=&subscribed_hosts($target);
                 foreach my $subhost (@subscribed) {                  foreach my $subhost (@subscribed) {
Line 9136  sub notifysubscribed { Line 5175  sub notifysubscribed {
 sub subscribed_hosts {  sub subscribed_hosts {
     my ($target) = @_;      my ($target) = @_;
     my @subscribed;      my @subscribed;
     if (open(my $fh,"<","$target.subscription")) {      if (open(my $fh,"<$target.subscription")) {
         while (my $subline=<$fh>) {          while (my $subline=<$fh>) {
             if ($subline =~ /^($match_lonid):/) {              if ($subline =~ /^($match_lonid):/) {
                 my $host = $1;                  my $host = $1;
Line 9161  sub check_switchserver { Line 5200  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.'&amp;role=dc./'.$dom.'/&amp;destinationurl=/adm/domainprefs">'.&mt('Switch Server').'</a>';   $switchserver='<a href="/adm/switchserver?otherserver='.$home.'&role=dc./'.$dom.'/">'.&mt('Switch Server').'</a>';
     }      }
     return $switchserver;      return $switchserver;
 }  }
   
 sub modify_quotas {  sub modify_quotas {
     my ($r,$dom,$action,$lastactref,%domconfig) = @_;      my ($dom,$action,%domconfig) = @_;
     my ($context,@usertools,@options,%validations,%titles,%confhash,%toolshash,      my ($context,@usertools,@options,%validations,%titles,%confhash,%toolshash,
         %limithash,$toolregexp,%conditions,$resulttext,%changes,$confname,$configuserok,          %limithash,$toolregexp,%conditions,$resulttext,%changes);
         $author_ok,$switchserver,$errors,$validationitemsref,$validationnamesref,  
         $validationfieldsref);  
     if ($action eq 'quotas') {      if ($action eq 'quotas') {
         $context = 'tools';           $context = 'tools'; 
     } else {      } else { 
         $context = $action;          $context = $action;
     }      }
     if ($context eq 'requestcourses') {      if ($context eq 'requestcourses') {
         @usertools = ('official','unofficial','community','textbook');          @usertools = ('official','unofficial','community');
         @options =('norequest','approval','validate','autolimit');          @options =('norequest','approval','validate','autolimit');
         %validations = &Apache::lonnet::auto_courserequest_checks($dom);          %validations = &Apache::lonnet::auto_courserequest_checks($dom);
         %titles = &courserequest_titles();          %titles = &courserequest_titles();
         $toolregexp = join('|',@usertools);          $toolregexp = join('|',@usertools);
         %conditions = &courserequest_conditions();          %conditions = &courserequest_conditions();
         $confname = $dom.'-domainconfig';  
         my $servadm = $r->dir_config('lonAdmEMail');  
         ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);  
         ($validationitemsref,$validationnamesref,$validationfieldsref) =   
             &Apache::loncoursequeueadmin::requestcourses_validation_types();  
     } elsif ($context eq 'requestauthor') {  
         @usertools = ('author');  
         %titles = &authorrequest_titles();  
     } else {      } else {
         @usertools = ('aboutme','blog','webdav','portfolio');          @usertools = ('aboutme','blog','webdav','portfolio');
         %titles = &tool_titles();          %titles = &tool_titles();
     }      }
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);      my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
     foreach my $key (keys(%env)) {      foreach my $key (keys(%env)) {
         if ($context eq 'requestcourses') {          if ($context eq 'requestcourses') {
Line 9209  sub modify_quotas { Line 5238  sub modify_quotas {
                     $confhash{$item}{$type} = $env{$key};                      $confhash{$item}{$type} = $env{$key};
                 }                  }
             }              }
         } elsif ($context eq 'requestauthor') {  
             if ($key =~ /^\Qform.authorreq_\E(.+)$/) {  
                 $confhash{$1} = $env{$key};  
             }  
         } else {          } else {
             if ($key =~ /^form\.quota_(.+)$/) {              if ($key =~ /^form\.quota_(.+)$/) {
                 $confhash{'defaultquota'}{$1} = $env{$key};                  $confhash{'defaultquota'}{$1} = $env{$key};
             } elsif ($key =~ /^form\.authorquota_(.+)$/) {              }
                 $confhash{'authorquota'}{$1} = $env{$key};              if ($key =~ /^form\.\Q$context\E_(.+)$/) {
             } elsif ($key =~ /^form\.\Q$context\E_(.+)$/) {  
                 @{$toolshash{$1}} = &Apache::loncommon::get_env_multiple($key);                  @{$toolshash{$1}} = &Apache::loncommon::get_env_multiple($key);
             }              }
         }          }
     }      }
     if (($context eq 'requestcourses') || ($context eq 'requestauthor')) {      if ($context eq 'requestcourses') {
         my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval');          my @approvalnotify = &Apache::loncommon::get_env_multiple('form.reqapprovalnotify');
         @approvalnotify = sort(@approvalnotify);          @approvalnotify = sort(@approvalnotify);
         $confhash{'notify'}{'approval'} = join(',',@approvalnotify);          $confhash{'notify'}{'approval'} = join(',',@approvalnotify);
         my @crstypes = ('official','unofficial','community','textbook');  
         my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');  
         foreach my $type (@hasuniquecode) {  
             if (grep(/^\Q$type\E$/,@crstypes)) {  
                 $confhash{'uniquecode'}{$type} = 1;  
             }  
         }  
         my (%newbook,%allpos);  
         if ($context eq 'requestcourses') {  
             foreach my $type ('textbooks','templates') {  
                 @{$allpos{$type}} = ();   
                 my $invalid;  
                 if ($type eq 'textbooks') {  
                     $invalid = &mt('Invalid LON-CAPA course for textbook');  
                 } else {  
                     $invalid = &mt('Invalid LON-CAPA course for template');  
                 }  
                 if ($env{'form.'.$type.'_addbook'}) {  
                     if (($env{'form.'.$type.'_addbook_cnum'} =~ /^$match_courseid$/) &&  
                         ($env{'form.'.$type.'_addbook_cdom'} =~ /^$match_domain$/)) {  
                         if (&Apache::lonnet::homeserver($env{'form.'.$type.'_addbook_cnum'},  
                                                         $env{'form.'.$type.'_addbook_cdom'}) eq 'no_host') {  
                             $errors .= '<li><span class="LC_error">'.$invalid.'</span></li>';  
                         } else {  
                             $newbook{$type} = $env{'form.'.$type.'_addbook_cdom'}.'_'.$env{'form.'.$type.'_addbook_cnum'};  
                             my $position = $env{'form.'.$type.'_addbook_pos'};  
                             $position =~ s/\D+//g;  
                             if ($position ne '') {  
                                 $allpos{$type}[$position] = $newbook{$type};  
                             }  
                         }  
                     } else {  
                         $errors .= '<li><span class="LC_error">'.$invalid.'</span></li>';  
                     }  
                 }  
             }   
         }  
         if (ref($domconfig{$action}) eq 'HASH') {          if (ref($domconfig{$action}) eq 'HASH') {
             if (ref($domconfig{$action}{'notify'}) eq 'HASH') {              if (ref($domconfig{$action}{'notify'}) eq 'HASH') {
                 if ($domconfig{$action}{'notify'}{'approval'} ne $confhash{'notify'}{'approval'}) {                  if ($domconfig{$action}{'notify'}{'approval'} ne $confhash{'notify'}{'approval'}) {
Line 9274  sub modify_quotas { Line 5261  sub modify_quotas {
                     $changes{'notify'}{'approval'} = 1;                      $changes{'notify'}{'approval'} = 1;
                 }                  }
             }              }
             if (ref($domconfig{$action}{'uniquecode'}) eq 'HASH') {  
                 if (ref($confhash{'uniquecode'}) eq 'HASH') {  
                     foreach my $crstype (keys(%{$domconfig{$action}{'uniquecode'}})) {  
                         unless ($confhash{'uniquecode'}{$crstype}) {  
                             $changes{'uniquecode'} = 1;  
                         }  
                     }  
                     unless ($changes{'uniquecode'}) {  
                         foreach my $crstype (keys(%{$confhash{'uniquecode'}})) {  
                             unless ($domconfig{$action}{'uniquecode'}{$crstype}) {  
                                 $changes{'uniquecode'} = 1;  
                             }  
                         }  
                     }  
                } else {  
                    $changes{'uniquecode'} = 1;  
                }  
             } elsif (ref($confhash{'uniquecode'}) eq 'HASH') {  
                 $changes{'uniquecode'} = 1;  
             }  
             if ($context eq 'requestcourses') {  
                 foreach my $type ('textbooks','templates') {  
                     if (ref($domconfig{$action}{$type}) eq 'HASH') {  
                         my %deletions;  
                         my @todelete = &Apache::loncommon::get_env_multiple('form.'.$type.'_del');  
                         if (@todelete) {  
                             map { $deletions{$_} = 1; } @todelete;  
                         }  
                         my %imgdeletions;  
                         my @todeleteimages = &Apache::loncommon::get_env_multiple('form.'.$type.'_image_del');  
                         if (@todeleteimages) {  
                             map { $imgdeletions{$_} = 1; } @todeleteimages;  
                         }  
                         my $maxnum = $env{'form.'.$type.'_maxnum'};  
                         for (my $i=0; $i<=$maxnum; $i++) {  
                             my $itemid = $env{'form.'.$type.'_id_'.$i};  
                             my ($key) = ($itemid =~ /^\Q$type\E_(\w+)$/);   
                             if (ref($domconfig{$action}{$type}{$key}) eq 'HASH') {  
                                 if ($deletions{$key}) {  
                                     if ($domconfig{$action}{$type}{$key}{'image'}) {  
                                         #FIXME need to obsolete item in RES space  
                                     }  
                                     next;  
                                 } else {  
                                     my $newpos = $env{'form.'.$itemid};  
                                     $newpos =~ s/\D+//g;  
                                     foreach my $item ('subject','title','publisher','author') {  
                                         next if ((($item eq 'author') || ($item eq 'publisher')) &&  
                                                  ($type eq 'templates'));  
                                         $confhash{$type}{$key}{$item} = $env{'form.'.$type.'_'.$item.'_'.$i};  
                                         if ($domconfig{$action}{$type}{$key}{$item} ne $confhash{$type}{$key}{$item}) {  
                                             $changes{$type}{$key} = 1;  
                                         }  
                                     }  
                                     $allpos{$type}[$newpos] = $key;  
                                 }  
                                 if ($imgdeletions{$key}) {  
                                     $changes{$type}{$key} = 1;  
                                     #FIXME need to obsolete item in RES space  
                                 } elsif ($env{'form.'.$type.'_image_'.$i.'.filename'}) {  
                                     my ($cdom,$cnum) = split(/_/,$key);  
                                     if (&Apache::lonnet::homeserver($cnum,$cdom) eq 'no_host') {  
                                         $errors .= '<li><span class="LC_error">'.&mt('Image not saved: could not find textbook course').'</li>';  
                                     } else {  
                                         my ($imgurl,$error) = &process_textbook_image($r,$dom,$confname,$type.'_image_'.$i,  
                                                                                       $cdom,$cnum,$type,$configuserok,  
                                                                                       $switchserver,$author_ok);  
                                         if ($imgurl) {  
                                             $confhash{$type}{$key}{'image'} = $imgurl;  
                                             $changes{$type}{$key} = 1;   
                                         }  
                                         if ($error) {  
                                             &Apache::lonnet::logthis($error);  
                                             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';  
                                         }  
                                     }   
                                 } elsif ($domconfig{$action}{$type}{$key}{'image'}) {  
                                     $confhash{$type}{$key}{'image'} =   
                                         $domconfig{$action}{$type}{$key}{'image'};  
                                 }  
                             }  
                         }  
                     }  
                 }  
             }  
         } else {          } else {
             if ($confhash{'notify'}{'approval'}) {              if ($confhash{'notify'}{'approval'}) {
                 $changes{'notify'}{'approval'} = 1;                  $changes{'notify'}{'approval'} = 1;
             }              }
             if (ref($confhash{'uniquecode'} eq 'HASH')) {  
                 $changes{'uniquecode'} = 1;  
             }  
         }  
         if ($context eq 'requestcourses') {  
             foreach my $type ('textbooks','templates') {  
                 if ($newbook{$type}) {  
                     $changes{$type}{$newbook{$type}} = 1;  
                     foreach my $item ('subject','title','publisher','author') {  
                         next if ((($item eq 'author') || ($item eq 'publisher')) &&  
                                  ($type eq 'template'));  
                         $env{'form.'.$type.'_addbook_'.$item} =~ s/(`)/'/g;  
                         if ($env{'form.'.$type.'_addbook_'.$item}) {  
                             $confhash{$type}{$newbook{$type}}{$item} = $env{'form.'.$type.'_addbook_'.$item};  
                         }  
                     }  
                     if ($type eq 'textbooks') {  
                         if ($env{'form.'.$type.'_addbook_image.filename'} ne '') {  
                             my ($cdom,$cnum) = split(/_/,$newbook{$type});  
                             if (&Apache::lonnet::homeserver($cnum,$cdom) eq 'no_host') {  
                                 $errors .= '<li><span class="LC_error">'.&mt('Image not saved: could not find textbook course').'</li>';  
                             } else {  
                                 my ($imageurl,$error) =  
                                     &process_textbook_image($r,$dom,$confname,$type.'_addbook_image',$cdom,$cnum,$type,  
                                                             $configuserok,$switchserver,$author_ok);  
                                 if ($imageurl) {  
                                     $confhash{$type}{$newbook{$type}}{'image'} = $imageurl;  
                                 }  
                                 if ($error) {  
                                     &Apache::lonnet::logthis($error);  
                                     $errors .= '<li><span class="LC_error">'.$error.'</span></li>';  
                                 }  
                             }  
                         }  
                     }  
                 }  
                 if (@{$allpos{$type}} > 0) {  
                     my $idx = 0;  
                     foreach my $item (@{$allpos{$type}}) {  
                         if ($item ne '') {  
                             $confhash{$type}{$item}{'order'} = $idx;  
                             if (ref($domconfig{$action}) eq 'HASH') {  
                                 if (ref($domconfig{$action}{$type}) eq 'HASH') {  
                                     if (ref($domconfig{$action}{$type}{$item}) eq 'HASH') {  
                                         if ($domconfig{$action}{$type}{$item}{'order'} ne $idx) {  
                                             $changes{$type}{$item} = 1;  
                                         }  
                                     }  
                                 }  
                             }  
                             $idx ++;  
                         }  
                     }  
                 }  
             }  
             if (ref($validationitemsref) eq 'ARRAY') {  
                 foreach my $item (@{$validationitemsref}) {  
                     if ($item eq 'fields') {  
                         my @changed;  
                         @{$confhash{'validation'}{$item}} = &Apache::loncommon::get_env_multiple('form.requestcourses_validation_'.$item);  
                         if (@{$confhash{'validation'}{$item}} > 0) {  
                             @{$confhash{'validation'}{$item}} = sort(@{$confhash{'validation'}{$item}});  
                         }  
                         if (ref($domconfig{'requestcourses'}) eq 'HASH') {  
                             if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {  
                                 if (ref($domconfig{'requestcourses'}{'validation'}{$item}) eq 'ARRAY') {  
                                     @changed = &Apache::loncommon::compare_arrays($confhash{'validation'}{$item},  
                                                                                   $domconfig{'requestcourses'}{'validation'}{$item});  
                                 } else {  
                                     @changed = @{$confhash{'validation'}{$item}};  
                                 }  
                             } else {  
                                 @changed = @{$confhash{'validation'}{$item}};  
                             }  
                         } else {  
                             @changed = @{$confhash{'validation'}{$item}};  
                         }  
                         if (@changed) {  
                             if ($confhash{'validation'}{$item}) {  
                                 $changes{'validation'}{$item} = join(', ',@{$confhash{'validation'}{$item}});  
                             } else {  
                                 $changes{'validation'}{$item} = &mt('None');  
                             }  
                         }  
                     } else {  
                         $confhash{'validation'}{$item} = $env{'form.requestcourses_validation_'.$item};  
                         if ($item eq 'markup') {  
                             if ($env{'form.requestcourses_validation_'.$item}) {  
                                 $env{'form.requestcourses_validation_'.$item} =~ s/[\n\r\f]+/\s/gs;  
                             }  
                         }  
                         if (ref($domconfig{'requestcourses'}) eq 'HASH') {  
                             if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {  
                                 if ($domconfig{'requestcourses'}{'validation'}{$item} ne $confhash{'validation'}{$item}) {  
                                     $changes{'validation'}{$item} = $confhash{'validation'}{$item};  
                                 }  
                             } else {  
                                 if ($confhash{'validation'}{$item} ne '') {  
                                     $changes{'validation'}{$item} = $confhash{'validation'}{$item};  
                                 }  
                             }  
                         } else {  
                             if ($confhash{'validation'}{$item} ne '') {  
                                 $changes{'validation'}{$item} = $confhash{'validation'}{$item};  
                             }  
                         }  
                     }  
                 }  
             }  
             if ($env{'form.validationdc'}) {  
                 my $newval = $env{'form.validationdc'};  
                 my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);  
                 if (exists($domcoords{$newval})) {  
                     $confhash{'validation'}{'dc'} = $newval;  
                 }  
             }  
             if (ref($confhash{'validation'}) eq 'HASH') {  
                 if (ref($domconfig{'requestcourses'}) eq 'HASH') {  
                     if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {  
                         if ($domconfig{'requestcourses'}{'validation'}{'dc'}) {  
                             unless ($confhash{'validation'}{'dc'} eq $domconfig{'requestcourses'}{'validation'}{'dc'}) {  
                                 if ($confhash{'validation'}{'dc'} eq '') {  
                                     $changes{'validation'}{'dc'} = &mt('None');  
                                 } else {  
                                     $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};  
                                 }  
                             }  
                         } elsif ($confhash{'validation'}{'dc'} ne '') {  
                             $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};  
                         }  
                     } elsif ($confhash{'validation'}{'dc'} ne '') {  
                         $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};  
                     }  
                 } elsif ($confhash{'validation'}{'dc'} ne '') {  
                     $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};  
                 }  
             } else {  
                 if (ref($domconfig{'requestcourses'}) eq 'HASH') {  
                     if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {  
                         if ($domconfig{'requestcourses'}{'validation'}{'dc'}) {  
                             $changes{'validation'}{'dc'} = &mt('None');  
                         }  
                     }  
                 }  
             }  
         }          }
     } else {      } else {
         $confhash{'defaultquota'}{'default'} = $env{'form.defaultquota'};          $confhash{'defaultquota'}{'default'} = $env{'form.defaultquota'};
         $confhash{'authorquota'}{'default'} = $env{'form.authorquota'};  
     }      }
     foreach my $item (@usertools) {      foreach my $item (@usertools) {
         foreach my $type (@{$types},'default','_LC_adv') {          foreach my $type (@{$types},'default','_LC_adv') {
Line 9527  sub modify_quotas { Line 5283  sub modify_quotas {
                         $confhash{$item}{$type} .= $limithash{$item}{$type};                          $confhash{$item}{$type} .= $limithash{$item}{$type};
                     }                      }
                 }                  }
             } elsif ($context eq 'requestauthor') {  
                 $unset = '0';  
                 if ($type eq '_LC_adv') {  
                     $unset = '';  
                 }  
             } else {              } else {
                 if (grep(/^\Q$type\E$/,@{$toolshash{$item}})) {                  if (grep(/^\Q$type\E$/,@{$toolshash{$item}})) {
                     $confhash{$item}{$type} = 1;                      $confhash{$item}{$type} = 1;
Line 9540  sub modify_quotas { Line 5291  sub modify_quotas {
                 }                  }
             }              }
             if (ref($domconfig{$action}) eq 'HASH') {              if (ref($domconfig{$action}) eq 'HASH') {
                 if ($action eq 'requestauthor') {                  if (ref($domconfig{$action}{$item}) eq 'HASH') {
                     if ($domconfig{$action}{$type} ne $confhash{$type}) {  
                         $changes{$type} = 1;  
                     }  
                 } elsif (ref($domconfig{$action}{$item}) eq 'HASH') {  
                     if ($domconfig{$action}{$item}{$type} ne $confhash{$item}{$type}) {                      if ($domconfig{$action}{$item}{$type} ne $confhash{$item}{$type}) {
                         $changes{$item}{$type} = 1;                          $changes{$item}{$type} = 1;
                     }                      }
Line 9564  sub modify_quotas { Line 5311  sub modify_quotas {
                     if ($confhash{$item}{$type} ne $unset) {                      if ($confhash{$item}{$type} ne $unset) {
                         $changes{$item}{$type} = 1;                          $changes{$item}{$type} = 1;
                     }                      }
                 } elsif ($context eq 'requestauthor') {  
                     if ($confhash{$type} ne $unset) {  
                         $changes{$type} = 1;  
                     }  
                 } else {                  } else {
                     if (!$confhash{$item}{$type}) {                      if (!$confhash{$item}{$type}) {
                         $changes{$item}{$type} = 1;                          $changes{$item}{$type} = 1;
Line 9576  sub modify_quotas { Line 5319  sub modify_quotas {
             }              }
         }          }
     }      }
     unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {      unless ($context eq 'requestcourses') {
         if (ref($domconfig{'quotas'}) eq 'HASH') {          if (ref($domconfig{'quotas'}) eq 'HASH') {
             if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') {              if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') {
                 foreach my $key (keys(%{$domconfig{'quotas'}{'defaultquota'}})) {                  foreach my $key (keys(%{$domconfig{'quotas'}{'defaultquota'}})) {
Line 9599  sub modify_quotas { Line 5342  sub modify_quotas {
                     }                      }
                 }                  }
             }              }
             if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') {  
                 foreach my $key (keys(%{$domconfig{'quotas'}{'authorquota'}})) {  
                     if (exists($confhash{'authorquota'}{$key})) {  
                         if ($confhash{'authorquota'}{$key} ne $domconfig{'quotas'}{'authorquota'}{$key}) {  
                             $changes{'authorquota'}{$key} = 1;  
                         }  
                     } else {  
                         $confhash{'authorquota'}{$key} = $domconfig{'quotas'}{'authorquota'}{$key};  
                     }  
                 }  
             }  
         }          }
         if (ref($confhash{'defaultquota'}) eq 'HASH') {          if (ref($confhash{'defaultquota'}) eq 'HASH') {
             foreach my $key (keys(%{$confhash{'defaultquota'}})) {              foreach my $key (keys(%{$confhash{'defaultquota'}})) {
Line 9628  sub modify_quotas { Line 5360  sub modify_quotas {
                 }                  }
             }              }
         }          }
         if (ref($confhash{'authorquota'}) eq 'HASH') {  
             foreach my $key (keys(%{$confhash{'authorquota'}})) {  
                 if (ref($domconfig{'quotas'}) eq 'HASH') {  
                     if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') {  
                         if (!exists($domconfig{'quotas'}{'authorquota'}{$key})) {  
                             $changes{'authorquota'}{$key} = 1;  
                         }  
                     } else {  
                         $changes{'authorquota'}{$key} = 1;  
                     }  
                 } else {  
                     $changes{'authorquota'}{$key} = 1;  
                 }  
             }  
         }  
     }      }
   
     if ($context eq 'requestauthor') {      foreach my $key (keys(%confhash)) {
         $domdefaults{'requestauthor'} = \%confhash;          $domdefaults{$key} = $confhash{$key};
     } else {  
         foreach my $key (keys(%confhash)) {  
             unless (($context eq 'requestcourses') && (($key eq 'textbooks') || ($key eq 'templates'))) {  
                 $domdefaults{$key} = $confhash{$key};  
             }  
         }  
     }      }
      
     my %quotahash = (      my %quotahash = (
                       $action => { %confhash }                        $action => { %confhash }
                     );                      );
Line 9664  sub modify_quotas { Line 5375  sub modify_quotas {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             my $cachetime = 24*60*60;              my $cachetime = 24*60*60;
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);              &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'domdefaults'} = 1;  
             }  
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             unless (($context eq 'requestcourses') ||              unless ($context eq 'requestcourses') {
                     ($context eq 'requestauthor')) {  
                 if (ref($changes{'defaultquota'}) eq 'HASH') {                  if (ref($changes{'defaultquota'}) eq 'HASH') {
                     $resulttext .= '<li>'.&mt('Portfolio default quotas').'<ul>';                      $resulttext .= '<li>'.&mt('Portfolio default quotas').'<ul>';
                     foreach my $type (@{$types},'default') {                      foreach my $type (@{$types},'default') {
Line 9678  sub modify_quotas { Line 5386  sub modify_quotas {
                             if ($type eq 'default') {                              if ($type eq 'default') {
                                 $typetitle = $othertitle;                                  $typetitle = $othertitle;
                             }                              }
                             $resulttext .= '<li>'.&mt('[_1] set to [_2] MB',$typetitle,$confhash{'defaultquota'}{$type}).'</li>';                              $resulttext .= '<li>'.&mt('[_1] set to [_2] Mb',$typetitle,$confhash{'defaultquota'}{$type}).'</li>';
                         }  
                     }  
                     $resulttext .= '</ul></li>';  
                 }  
                 if (ref($changes{'authorquota'}) eq 'HASH') {  
                     $resulttext .= '<li>'.&mt('Authoring Space default quotas').'<ul>';  
                     foreach my $type (@{$types},'default') {  
                         if (defined($changes{'authorquota'}{$type})) {  
                             my $typetitle = $usertypes->{$type};  
                             if ($type eq 'default') {  
                                 $typetitle = $othertitle;  
                             }  
                             $resulttext .= '<li>'.&mt('[_1] set to [_2] MB',$typetitle,$confhash{'authorquota'}{$type}).'</li>';  
                         }                          }
                     }                      }
                     $resulttext .= '</ul></li>';                      $resulttext .= '</ul></li>';
Line 9699  sub modify_quotas { Line 5394  sub modify_quotas {
             }              }
             my %newenv;              my %newenv;
             foreach my $item (@usertools) {              foreach my $item (@usertools) {
                 my (%haschgs,%inconf);                  if (ref($changes{$item}) eq 'HASH') {
                 if ($context eq 'requestauthor') {  
                     %haschgs = %changes;  
                     %inconf = %confhash;  
                 } else {  
                     if (ref($changes{$item}) eq 'HASH') {  
                         %haschgs = %{$changes{$item}};  
                     }  
                     if (ref($confhash{$item}) eq 'HASH') {  
                         %inconf = %{$confhash{$item}};  
                     }  
                 }  
                 if (keys(%haschgs) > 0) {  
                     my $newacc =                       my $newacc = 
                         &Apache::lonnet::usertools_access($env{'user.name'},                          &Apache::lonnet::usertools_access($env{'user.name'},
                                                           $env{'user.domain'},                                                            $env{'user.domain'},
                                                           $item,'reload',$context);                                                            $item,'reload',$context);
                     if (($context eq 'requestcourses') ||                      if ($context eq 'requestcourses') {
                         ($context eq 'requestauthor')) {  
                         if ($env{'environment.canrequest.'.$item} ne $newacc) {                          if ($env{'environment.canrequest.'.$item} ne $newacc) {
                             $newenv{'environment.canrequest.'.$item} = $newacc;                              $newenv{'environment.canrequest.'.$item} = $newacc;
                         }                          }
Line 9726  sub modify_quotas { Line 5408  sub modify_quotas {
                             $newenv{'environment.availabletools.'.$item} = $newacc;                              $newenv{'environment.availabletools.'.$item} = $newacc;
                         }                          }
                     }                      }
                     unless ($context eq 'requestauthor') {                      $resulttext .= '<li>'.$titles{$item}.'<ul>';
                         $resulttext .= '<li>'.$titles{$item}.'<ul>';  
                     }  
                     foreach my $type (@{$types},'default','_LC_adv') {                      foreach my $type (@{$types},'default','_LC_adv') {
                         if ($haschgs{$type}) {                          if ($changes{$item}{$type}) {
                             my $typetitle = $usertypes->{$type};                              my $typetitle = $usertypes->{$type};
                             if ($type eq 'default') {                              if ($type eq 'default') {
                                 $typetitle = $othertitle;                                  $typetitle = $othertitle;
                             } elsif ($type eq '_LC_adv') {                              } elsif ($type eq '_LC_adv') {
                                 $typetitle = 'LON-CAPA Advanced Users';                                   $typetitle = 'LON-CAPA Advanced Users'; 
                             }                              }
                             if ($inconf{$type}) {                              if ($confhash{$item}{$type}) {
                                 if ($context eq 'requestcourses') {                                  if ($context eq 'requestcourses') {
                                     my $cond;                                      my $cond;
                                     if ($inconf{$type} =~ /^autolimit=(\d*)$/) {                                      if ($confhash{$item}{$type} =~ /^autolimit=(\d*)$/) {
                                         if ($1 eq '') {                                          if ($1 eq '') {
                                             $cond = &mt('(Automatic processing of any request).');                                              $cond = &mt('(Automatic processing of any request).');
                                         } else {                                          } else {
                                             $cond = &mt('(Automatic processing of requests up to limit of [quant,_1,request] per user).',$1);                                              $cond = &mt('(Automatic processing of requests up to limit of [quant,_1,request] per user).',$1);
                                         }                                          }
                                     } else {                                       } else { 
                                         $cond = $conditions{$inconf{$type}};                                          $cond = $conditions{$confhash{$item}{$type}};
                                     }                                      }
                                     $resulttext .= '<li>'.&mt('Set to be available to [_1].',$typetitle).' '.$cond.'</li>';                                      $resulttext .= '<li>'.&mt('Set to be available to [_1].',$typetitle).' '.$cond.'</li>';
                                 } elsif ($context eq 'requestauthor') {  
                                     $resulttext .= '<li>'.&mt('Set to "[_1]" for "[_2]".',  
                                                              $titles{$inconf{$type}},$typetitle);  
   
                                 } else {                                  } else {
                                     $resulttext .= '<li>'.&mt('Set to be available to [_1]',$typetitle).'</li>';                                      $resulttext .= '<li>'.&mt('Set to be available to [_1]',$typetitle).'</li>';
                                 }                                  }
                             } else {                              } else {
                                 if ($type eq '_LC_adv') {                                  if ($type eq '_LC_adv') {
                                     if ($inconf{$type} eq '0') {                                      if ($confhash{$item}{$type} eq '0') {
                                         $resulttext .= '<li>'.&mt('Set to be unavailable to [_1]',$typetitle).'</li>';                                          $resulttext .= '<li>'.&mt('Set to be unavailable to [_1]',$typetitle).'</li>';
                                     } else {                                       } else { 
                                         $resulttext .= '<li>'.&mt('No override set for [_1]',$typetitle).'</li>';                                          $resulttext .= '<li>'.&mt('No override set for [_1]',$typetitle).'</li>';
Line 9770  sub modify_quotas { Line 5446  sub modify_quotas {
                             }                              }
                         }                          }
                     }                      }
                     unless ($context eq 'requestauthor') {                      $resulttext .= '</ul></li>';
                         $resulttext .= '</ul></li>';  
                     }  
                 }                  }
             }              }
             if (($action eq 'requestcourses') || ($action eq 'requestauthor')) {              if ($action eq 'requestcourses') {
                 if (ref($changes{'notify'}) eq 'HASH') {                  if (ref($changes{'notify'}) eq 'HASH') {
                     if ($changes{'notify'}{'approval'}) {                      if ($changes{'notify'}{'approval'}) {
                         if (ref($confhash{'notify'}) eq 'HASH') {                          if (ref($confhash{'notify'}) eq 'HASH') {
                             if ($confhash{'notify'}{'approval'}) {                              if ($confhash{'notify'}{'approval'}) {
                                 $resulttext .= '<li>'.&mt('Notification of requests requiring approval will be sent to: ').$confhash{'notify'}{'approval'}.'</li>';                                  $resulttext .= '<li>'.&mt('Notification of requests requiring approval will be sent to: ').$confhash{'notify'}{'approval'}.'</li>';
                             } else {                              } else {
                                 $resulttext .= '<li>'.&mt('No Domain Coordinators will receive notification of requests requiring approval.').'</li>';                                  $resulttext .= '<li>'.&mt('No Domain Coordinators will receive notification of course requests requiring approval.').'</li>';
                             }                              }
                         }                          }
                     }                      }
                 }                  }
             }              }
             if ($action eq 'requestcourses') {  
                 my @offon = ('off','on');  
                 if ($changes{'uniquecode'}) {  
                     if (ref($confhash{'uniquecode'}) eq 'HASH') {  
                         my $codestr = join(' ',map{ &mt($_); } sort(keys(%{$confhash{'uniquecode'}})));  
                         $resulttext .= '<li>'.  
                                        &mt('Generation of six character code as course identifier for distribution to students set to on for: [_1].','<b>'.$codestr.'</b>').  
                                        '</li>';  
                     } else {  
                         $resulttext .= '<li>'.&mt('Generation of six character code as course identifier for distribution to students set to off.').  
                                        '</li>';  
                     }  
                 }  
                 foreach my $type ('textbooks','templates') {  
                     if (ref($changes{$type}) eq 'HASH') {  
                         $resulttext .= '<li>'.&mt("Available $type updated").'<ul>';  
                         foreach my $key (sort(keys(%{$changes{$type}}))) {  
                             my %coursehash = &Apache::lonnet::coursedescription($key);  
                             my $coursetitle = $coursehash{'description'};  
                             my $position = $confhash{$type}{$key}{'order'} + 1;  
                             $resulttext .= '<li>';  
                             foreach my $item ('subject','title','publisher','author') {  
                                 next if ((($item eq 'author') || ($item eq 'publisher')) &&  
                                          ($type eq 'templates'));  
                                 my $name = $item.':';  
                                 $name =~ s/^(\w)/\U$1/;  
                                 $resulttext .= &mt($name).' '.$confhash{$type}{$key}{$item}.'<br />';  
                             }  
                             $resulttext .= ' '.&mt('Order: [_1]',$position).'<br />';  
                             if ($type eq 'textbooks') {  
                                 if ($confhash{$type}{$key}{'image'}) {  
                                     $resulttext .= ' '.&mt('Image: [_1]',  
                                                    '<img src="'.$confhash{$type}{$key}{'image'}.'"'.  
                                                    ' alt="Textbook cover" />').'<br />';  
                                 }  
                             }  
                             $resulttext .= ' '.&mt('LON-CAPA Course: [_1]',$coursetitle).'</li>';  
                         }  
                         $resulttext .= '</ul></li>';  
                     }  
                 }  
                 if (ref($changes{'validation'}) eq 'HASH') {  
                     if ((ref($validationitemsref) eq 'ARRAY') && (ref($validationnamesref) eq 'HASH')) {  
                         $resulttext .= '<li>'.&mt('Validation of courses/communities updated').'<ul>';  
                         foreach my $item (@{$validationitemsref}) {  
                             if (exists($changes{'validation'}{$item})) {  
                                 if ($item eq 'markup') {  
                                     $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$validationnamesref->{$item},  
                                                               '<br /><pre>'.$changes{'validation'}{$item}.'</pre>').'</li>';  
                                 } else {  
                                     $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$validationnamesref->{$item},  
                                                               '<b>'.$changes{'validation'}{$item}.'</b>').'</li>';  
                                 }  
                             }  
                         }  
                         if (exists($changes{'validation'}{'dc'})) {  
                             $resulttext .= '<li>'.&mt('Validated course requests identified as processed by: [_1]',  
                                                      '<b>'.$changes{'validation'}{'dc'}.'</b>').'</li>';  
                         }  
                     }  
                 }  
             }  
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
             if (keys(%newenv)) {              if (keys(%newenv)) {
                 &Apache::lonnet::appenv(\%newenv);                  &Apache::lonnet::appenv(\%newenv);
Line 9857  sub modify_quotas { Line 5469  sub modify_quotas {
         } else {          } else {
             if ($context eq 'requestcourses') {              if ($context eq 'requestcourses') {
                 $resulttext = &mt('No changes made to rights to request creation of courses.');                  $resulttext = &mt('No changes made to rights to request creation of courses.');
             } elsif ($context eq 'requestauthor') {  
                 $resulttext = &mt('No changes made to rights to request author space.');  
             } else {              } else {
                 $resulttext = &mt('No changes made to availability of personal information pages, blogs, portfolios or default quotas');                  $resulttext = &mt('No changes made to availability of personal information pages, blogs, portfolios or default quotas');
             }              }
Line 9867  sub modify_quotas { Line 5477  sub modify_quotas {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
     &mt('An error occurred: [_1]',$putresult).'</span>';      &mt('An error occurred: [_1]',$putresult).'</span>';
     }      }
     if ($errors) {  
         $resulttext .= '<p>'.&mt('The following errors occurred when modifying Textbook settings.').  
                        '<ul>'.$errors.'</ul></p>';  
     }  
     return $resulttext;      return $resulttext;
 }  }
   
 sub process_textbook_image {  
     my ($r,$dom,$confname,$caller,$cdom,$cnum,$type,$configuserok,$switchserver,$author_ok) = @_;  
     my $filename = $env{'form.'.$caller.'.filename'};  
     my ($error,$url);  
     my ($width,$height) = (50,50);  
     if ($configuserok eq 'ok') {  
         if ($switchserver) {  
             $error = &mt('Upload of textbook image is not permitted to this server: [_1]',  
                          $switchserver);  
         } elsif ($author_ok eq 'ok') {  
             my ($result,$imageurl) =  
                 &publishlogo($r,'upload',$caller,$dom,$confname,  
                              "$type/$cdom/$cnum/cover",$width,$height);  
             if ($result eq 'ok') {  
                 $url = $imageurl;  
             } else {  
                 $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$result);  
             }  
         } else {  
             $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3].  Error was: [_4].",$filename,$confname,$dom,$author_ok);  
         }  
     } else {  
         $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3].  Error was: [_4].",$filename,$confname,$dom,$configuserok);  
     }  
     return ($url,$error);  
 }  
   
 sub modify_autoenroll {  sub modify_autoenroll {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%changes);      my ($resulttext,%changes);
     my %currautoenroll;      my %currautoenroll;
     if (ref($domconfig{'autoenroll'}) eq 'HASH') {      if (ref($domconfig{'autoenroll'}) eq 'HASH') {
Line 9913  sub modify_autoenroll { Line 5492  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)',                    coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)');
                   failsafe => 'Failsafe for no drops if institutional data missing for a section');  
     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 9924  sub modify_autoenroll { Line 5502  sub modify_autoenroll {
         $sender_domain = '';          $sender_domain = '';
     }      }
     my $coowners = $env{'form.autoassign_coowners'};      my $coowners = $env{'form.autoassign_coowners'};
     my $failsafe = $env{'form.autoenroll_failsafe'};  
     $failsafe =~ s{^\s+|\s+$}{}g;  
     if ($failsafe =~ /\D/) {  
         undef($failsafe);  
     }  
     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,                                         'co-owners' => $coowners,
                                        'autofailsafe' => $failsafe,  
                                 }                                  }
                      );                       );
     my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,
Line 9961  sub modify_autoenroll { Line 5533  sub modify_autoenroll {
             }              }
         } elsif ($coowners) {          } elsif ($coowners) {
             $changes{'coowners'} = 1;              $changes{'coowners'} = 1;
         }          }      
         if ($currautoenroll{'autofailsafe'} ne $failsafe) {  
             $changes{'autofailsafe'} = 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 9980  sub modify_autoenroll { Line 5549  sub modify_autoenroll {
             if ($changes{'coowners'}) {              if ($changes{'coowners'}) {
                 $resulttext .= '<li>'.&mt("$title{'coowners'} set to $offon[$env{'form.autoassign_coowners'}]").'</li>';                  $resulttext .= '<li>'.&mt("$title{'coowners'} set to $offon[$env{'form.autoassign_coowners'}]").'</li>';
                 &Apache::loncommon::devalidate_domconfig_cache($dom);                  &Apache::loncommon::devalidate_domconfig_cache($dom);
                 if (ref($lastactref) eq 'HASH') {  
                     $lastactref->{'domainconfig'} = 1;  
                 }  
             }  
             if ($changes{'autofailsafe'}) {  
                 if ($failsafe ne '') {  
                     $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section set to: [_1]',$failsafe).'</li>';  
                 } else {  
                     $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section: deleted');  
                 }  
                 &Apache::lonnet::get_domain_defaults($dom,1);  
                 if (ref($lastactref) eq 'HASH') {  
                     $lastactref->{'domdefaults'} = 1;  
                 }  
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
Line 10210  sub modify_autocreate { Line 5765  sub modify_autocreate {
         $newvals{$item} = 0 if ($newvals{$item} eq '');          $newvals{$item} = 0 if ($newvals{$item} eq '');
     }      }
     $newvals{'xmldc'} = $env{'form.autocreate_xmldc'};      $newvals{'xmldc'} = $env{'form.autocreate_xmldc'};
     my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);      my %domcoords = &get_active_dcs($dom);
     unless (exists($domcoords{$newvals{'xmldc'}})) {      unless (exists($domcoords{$newvals{'xmldc'}})) {
         $newvals{'xmldc'} = '';          $newvals{'xmldc'} = '';
     }       } 
Line 10244  sub modify_autocreate { Line 5799  sub modify_autocreate {
             foreach my $item (@types) {              foreach my $item (@types) {
                 if ($changes{$item}) {                  if ($changes{$item}) {
                     my $newtxt = $offon[$newvals{$item}];                      my $newtxt = $offon[$newvals{$item}];
                     $resulttext .= '<li>'.                      $resulttext .= '<li>'.&mt("$title{$item} set to [_1]$newtxt [_2]",'<b>','</b>').'</li>';
                                    &mt("$title{$item} set to [_1]$newtxt [_2]",  
                                        '<b>','</b>').  
                                    '</li>';  
                 }                  }
             }              }
             if ($changes{'xmldc'}) {              if ($changes{'xmldc'}) {
                 my ($dcname,$dcdom) = split(':',$newvals{'xmldc'});                  my ($dcname,$dcdom) = split(':',$newvals{'xmldc'});
                 my $newtxt = &Apache::loncommon::plainname($dcname,$dcdom);                  my $newtxt = &Apache::loncommon::plainname($dcname,$dcdom);
                 $resulttext .= '<li>'.&mt("$title{'xmldc'} set to [_1]",'<b>'.$newtxt.'</b>').'</li>';                   $resulttext .= '<li>'.&mt("$title{'xmldc'} set to [_1]$newtxt [_2]",'<b>','</b>').'</li>'; 
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
Line 10267  sub modify_autocreate { Line 5819  sub modify_autocreate {
 }  }
   
 sub modify_directorysrch {  sub modify_directorysrch {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%changes);      my ($resulttext,%changes);
     my %currdirsrch;      my %currdirsrch;
     if (ref($domconfig{'directorysrch'}) eq 'HASH') {      if (ref($domconfig{'directorysrch'}) eq 'HASH') {
Line 10275  sub modify_directorysrch { Line 5827  sub modify_directorysrch {
             $currdirsrch{$key} = $domconfig{'directorysrch'}{$key};              $currdirsrch{$key} = $domconfig{'directorysrch'}{$key};
         }          }
     }      }
     my %title = ( available => 'Institutional directory search available',      my %title = ( available => 'Directory search available',
                   localonly => 'Other domains can search institution',                    localonly => 'Other domains can search',
                   lcavailable => 'LON-CAPA directory search available',  
                   lclocalonly => 'Other domains can search LON-CAPA domain',  
                   searchby => 'Search types',                    searchby => 'Search types',
                   searchtypes => 'Search latitude');                    searchtypes => 'Search latitude');
     my @offon = ('off','on');      my @offon = ('off','on');
Line 10352  sub modify_directorysrch { Line 5902  sub modify_directorysrch {
     my %dirsrch_hash =  (      my %dirsrch_hash =  (
             directorysrch => { available => $env{'form.dirsrch_available'},              directorysrch => { available => $env{'form.dirsrch_available'},
                                cansearch => \@cansearch,                                 cansearch => \@cansearch,
                                localonly => $env{'form.dirsrch_instlocalonly'},                                 localonly => $env{'form.dirsrch_localonly'},
                                lclocalonly => $env{'form.dirsrch_domlocalonly'},  
                                lcavailable => $env{'form.dirsrch_domavailable'},  
                                searchby => \@searchby,                                 searchby => \@searchby,
                                searchtypes => \@searchtypes,                                 searchtypes => \@searchtypes,
                              }                               }
Line 10371  sub modify_directorysrch { Line 5919  sub modify_directorysrch {
                 $changes{'available'} = 1;                  $changes{'available'} = 1;
             }              }
         }          }
         if (exists($currdirsrch{'lcavailable'})) {  
             if ($currdirsrch{'lcavailable'} ne $env{'form.dirsrch_domavailable'}) {  
                 $changes{'lcavailable'} = 1;  
             }  
         } else {  
             if ($env{'form.dirsrch_lcavailable'} eq '1') {  
                 $changes{'lcavailable'} = 1;  
             }  
         }  
         if (exists($currdirsrch{'localonly'})) {          if (exists($currdirsrch{'localonly'})) {
             if ($currdirsrch{'localonly'} ne $env{'form.dirsrch_instlocalonly'}) {               if ($currdirsrch{'localonly'} ne $env{'form.dirsrch_localonly'}) {
                 $changes{'localonly'} = 1;                   $changes{'localonly'} = 1;
             }               }
         } else {          } else {
             if ($env{'form.dirsrch_instlocalonly'} eq '1') {              if ($env{'form.dirsrch_localonly'} eq '1') {
                 $changes{'localonly'} = 1;                  $changes{'localonly'} = 1;
             }              }
         }          }
         if (exists($currdirsrch{'lclocalonly'})) {  
             if ($currdirsrch{'lclocalonly'} ne $env{'form.dirsrch_domlocalonly'}) {  
                 $changes{'lclocalonly'} = 1;  
             }  
         } else {  
             if ($env{'form.dirsrch_domlocalonly'} eq '1') {  
                 $changes{'lclocalonly'} = 1;  
             }  
         }  
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if ($changes{'available'}) {              if ($changes{'available'}) {
                 $resulttext .= '<li>'.&mt("$title{'available'} set to: $offon[$env{'form.dirsrch_available'}]").'</li>';                  $resulttext .= '<li>'.&mt("$title{'available'} set to: $offon[$env{'form.dirsrch_available'}]").'</li>';
             }              }
             if ($changes{'lcavailable'}) {  
                 $resulttext .= '<li>'.&mt("$title{'lcavailable'} set to: $offon[$env{'form.dirsrch_domavailable'}]").'</li>';  
             }  
             if ($changes{'localonly'}) {              if ($changes{'localonly'}) {
                 $resulttext .= '<li>'.&mt("$title{'localonly'} set to: $otherdoms[$env{'form.dirsrch_instlocalonly'}]").'</li>';                  $resulttext .= '<li>'.&mt("$title{'localonly'} set to: $otherdoms[$env{'form.dirsrch_localonly'}]").'</li>';
             }  
             if ($changes{'lclocalonly'}) {  
                 $resulttext .= '<li>'.&mt("$title{'lclocalonly'} set to: $otherdoms[$env{'form.dirsrch_domlocalonly'}]").'</li>';  
             }              }
   
             if (ref($changes{'cansearch'}) eq 'ARRAY') {              if (ref($changes{'cansearch'}) eq 'ARRAY') {
                 my $chgtext;                  my $chgtext;
                 if (ref($usertypes) eq 'HASH') {                  if (ref($usertypes) eq 'HASH') {
Line 10426  sub modify_directorysrch { Line 5951  sub modify_directorysrch {
                         } else {                          } else {
                             $chgtext =~ s/\; $//;                              $chgtext =~ s/\; $//;
                         }                          }
                         $resulttext .=                          $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>';
                             '<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 10458  sub modify_directorysrch { Line 5979  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>';
             &Apache::lonnet::do_cache_new('directorysrch',$dom,$dirsrch_hash{'directorysrch'},3600);  
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'directorysrch'} = 1;  
             }  
         } else {          } else {
             $resulttext = &mt('No changes made to directory search settings');              $resulttext = &mt('No changes made to institution directory search settings');
         }          }
     } else {      } else {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
Line 10476  sub modify_directorysrch { Line 5993  sub modify_directorysrch {
 }  }
   
 sub modify_contacts {  sub modify_contacts {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%currsetting,%newsetting,%changes,%contacts_hash);      my ($resulttext,%currsetting,%newsetting,%changes,%contacts_hash);
     if (ref($domconfig{'contacts'}) eq 'HASH') {      if (ref($domconfig{'contacts'}) eq 'HASH') {
         foreach my $key (keys(%{$domconfig{'contacts'}})) {          foreach my $key (keys(%{$domconfig{'contacts'}})) {
             $currsetting{$key} = $domconfig{'contacts'}{$key};              $currsetting{$key} = $domconfig{'contacts'}{$key};
         }          }
     }      }
     my (%others,%to,%bcc,%includestr,%includeloc);      my (%others,%to,%bcc);
     my @contacts = ('supportemail','adminemail');      my @contacts = ('supportemail','adminemail');
     my @mailings = ('errormail','packagesmail','helpdeskmail','otherdomsmail',      my @mailings = ('errormail','packagesmail','helpdeskmail','lonstatusmail',
                     'lonstatusmail','requestsmail','updatesmail','idconflictsmail','hostipmail');                      'requestsmail');
     my @toggles = ('reporterrors','reportupdates');  
     my ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();  
     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 10498  sub modify_contacts { Line 6013  sub modify_contacts {
             } else {              } else {
                 $contacts_hash{contacts}{$type}{$item} = 0;                  $contacts_hash{contacts}{$type}{$item} = 0;
             }              }
         }          }  
         $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') || ($type eq 'otherdomsmail')) {          if ($type eq 'helpdeskmail') {
             $bcc{$type} = $env{'form.'.$type.'_bcc'};              $bcc{$type} = $env{'form.'.$type.'_bcc'};
             $contacts_hash{contacts}{$type}{'bcc'} = $bcc{$type};              $contacts_hash{contacts}{$type}{'bcc'} = $bcc{$type};
             if (($env{'form.'.$type.'_includestr'} ne '') && ($env{'form.'.$type.'_includeloc'} =~ /^s|b$/)) {  
                 $includestr{$type} = $env{'form.'.$type.'_includestr'};  
                 $includeloc{$type} = $env{'form.'.$type.'_includeloc'};  
                 $contacts_hash{contacts}{$type}{'include'} = $includeloc{$type}.':'.&escape($includestr{$type});  
             }  
         }          }
     }      }
     foreach my $item (@contacts) {      foreach my $item (@contacts) {
         $to{$item} = $env{'form.'.$item};          $to{$item} = $env{'form.'.$item};
         $contacts_hash{'contacts'}{$item} = $to{$item};          $contacts_hash{'contacts'}{$item} = $to{$item};
     }      }
     foreach my $item (@toggles) {  
         if ($env{'form.'.$item} =~ /^(0|1)$/) {  
             $contacts_hash{'contacts'}{$item} = $env{'form.'.$item};  
         }  
     }  
     if ((ref($fields) eq 'ARRAY') && (ref($possoptions) eq 'HASH')) {  
         foreach my $field (@{$fields}) {  
             if (ref($possoptions->{$field}) eq 'ARRAY') {  
                 my $value = $env{'form.helpform_'.$field};  
                 $value =~ s/^\s+|\s+$//g;  
                 if (grep(/^\Q$value\E$/,@{$possoptions->{$field}})) {  
                     $contacts_hash{'contacts'}{'helpform'}{$field} = $value;  
                     if ($field eq 'screenshot') {  
                         $env{'form.helpform_maxsize'} =~ s/^\s+|\s+$//g;  
                         if ($env{'form.helpform_maxsize'} =~ /^\d+\.?\d*$/) {  
                             $contacts_hash{'contacts'}{'helpform'}{'maxsize'} = $env{'form.helpform_maxsize'};  
                         }  
                     }  
                 }  
             }  
         }  
     }  
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
     my (@statuses,%usertypeshash,@overrides);  
     if ((ref($types) eq 'ARRAY') && (@{$types} > 0)) {  
         @statuses = @{$types};  
         if (ref($usertypes) eq 'HASH') {  
             %usertypeshash = %{$usertypes};  
         }  
     }  
     if (@statuses) {  
         my @possoverrides = &Apache::loncommon::get_env_multiple('form.overrides');  
         foreach my $type (@possoverrides) {  
             if (($type ne '') && (grep(/^\Q$type\E$/,@statuses))) {  
                 push(@overrides,$type);  
             }  
         }  
         if (@overrides) {  
             foreach my $type (@overrides) {  
                 my @standard = &Apache::loncommon::get_env_multiple('form.override_'.$type);  
                 foreach my $item (@contacts) {  
                     if (grep(/^\Q$item\E$/,@standard)) {  
                         $contacts_hash{'contacts'}{'overrides'}{$type}{$item} = 1;  
                         $newsetting{'override_'.$type}{$item} = 1;  
                     } else {  
                         $contacts_hash{'contacts'}{'overrides'}{$type}{$item} = 0;  
                         $newsetting{'override_'.$type}{$item} = 0;  
                     }  
                 }  
                 $contacts_hash{'contacts'}{'overrides'}{$type}{'others'} = $env{'form.override_'.$type.'_others'};  
                 $contacts_hash{'contacts'}{'overrides'}{$type}{'bcc'} = $env{'form.override_'.$type.'_bcc'};  
                 $newsetting{'override_'.$type}{'others'} = $env{'form.override_'.$type.'_others'};  
                 $newsetting{'override_'.$type}{'bcc'} = $env{'form.override_'.$type.'_bcc'};  
                 if (($env{'form.override_'.$type.'_includestr'} ne '') && ($env{'form.override_'.$type.'_includeloc'} =~ /^s|b$/)) {  
                     $includestr{$type} = $env{'form.override_'.$type.'_includestr'};  
                     $includeloc{$type} = $env{'form.override_'.$type.'_includeloc'};  
                     $contacts_hash{'contacts'}{'overrides'}{$type}{'include'} = $includeloc{$type}.':'.&escape($includestr{$type});  
                     $newsetting{'override_'.$type}{'include'} = $contacts_hash{'contacts'}{'overrides'}{$type}{'include'};  
                 }  
             }      
         }  
     }  
     if (keys(%currsetting) > 0) {      if (keys(%currsetting) > 0) {
         foreach my $item (@contacts) {          foreach my $item (@contacts) {
             if ($to{$item} ne $currsetting{$item}) {              if ($to{$item} ne $currsetting{$item}) {
Line 10596  sub modify_contacts { Line 6044  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') || ($type eq 'otherdomsmail')) {              if ($type eq 'helpdeskmail') {   
                 if ($bcc{$type} ne $currsetting{$type}{'bcc'}) {                  if ($bcc{$type} ne $currsetting{$type}{'bcc'}) {
                     push(@{$changes{$type}},'bcc');                       push(@{$changes{$type}},'bcc'); 
                 }                  }
                 my ($currloc,$currstr) = split(/:/,$currsetting{$type}{'include'},2);  
                 if (($includeloc{$type} ne $currloc) || (&escape($includestr{$type}) ne $currstr)) {  
                     push(@{$changes{$type}},'include');  
                 }  
             }  
         }  
         if (ref($fields) eq 'ARRAY') {  
             if (ref($currsetting{'helpform'}) eq 'HASH') {  
                 foreach my $field (@{$fields}) {  
                     if ($currsetting{'helpform'}{$field} ne $contacts_hash{'contacts'}{'helpform'}{$field}) {  
                         push(@{$changes{'helpform'}},$field);  
                     }  
                     if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {  
                         if ($currsetting{'helpform'}{'maxsize'} ne $contacts_hash{'contacts'}{'helpform'}{'maxsize'}) {  
                             push(@{$changes{'helpform'}},'maxsize');  
                         }  
                     }  
                 }  
             } else {  
                 foreach my $field (@{$fields}) {  
                     if ($contacts_hash{'contacts'}{'helpform'}{$field} ne 'yes') {  
                         push(@{$changes{'helpform'}},$field);  
                     }  
                     if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {  
                         if ($contacts_hash{'contacts'}{'helpform'}{'maxsize'} != 1) {  
                             push(@{$changes{'helpform'}},'maxsize');  
                         }  
                     }  
                 }  
             }  
         }  
         if (@statuses) {  
             if (ref($currsetting{'overrides'}) eq 'HASH') {  
                 foreach my $key (keys(%{$currsetting{'overrides'}})) {  
                     if (ref($currsetting{'overrides'}{$key}) eq 'HASH') {  
                         if (ref($newsetting{'override_'.$key}) eq 'HASH') {  
                             foreach my $item (@contacts,'bcc','others','include') {  
                                 if ($currsetting{'overrides'}{$key}{$item} ne $newsetting{'override_'.$key}{$item}) {  
                                     push(@{$changes{'overrides'}},$key);  
                                     last;  
                                 }  
                             }  
                         } else {  
                             push(@{$changes{'overrides'}},$key);  
                         }  
                     }  
                 }  
                 foreach my $key (@overrides) {  
                     unless (exists($currsetting{'overrides'}{$key})) {  
                         push(@{$changes{'overrides'}},$key);  
                     }  
                 }  
             } else {  
                 foreach my $key (@overrides) {  
                     push(@{$changes{'overrides'}},$key);  
                 }  
             }              }
         }          }
     } else {      } else {
Line 10665  sub modify_contacts { Line 6057  sub modify_contacts {
         $default{'errormail'} = 'adminemail';          $default{'errormail'} = 'adminemail';
         $default{'packagesmail'} = 'adminemail';          $default{'packagesmail'} = 'adminemail';
         $default{'helpdeskmail'} = 'supportemail';          $default{'helpdeskmail'} = 'supportemail';
         $default{'otherdomsmail'} = 'supportemail';  
         $default{'lonstatusmail'} = 'adminemail';          $default{'lonstatusmail'} = 'adminemail';
         $default{'requestsmail'} = 'adminemail';          $default{'requestsmail'} = 'adminemail';
         $default{'updatesmail'} = 'adminemail';  
         $default{'hostipmail'} = 'adminemail';  
         foreach my $item (@contacts) {          foreach my $item (@contacts) {
            if ($to{$item} ne $default{$item}) {             if ($to{$item} ne $default{$item}) {
                $changes{$item} = 1;                $changes{$item} = 1;
            }             } 
         }          }
         foreach my $type (@mailings) {          foreach my $type (@mailings) {
             if ((@{$newsetting{$type}} != 1) || ($newsetting{$type}[0] ne $default{$type})) {              if ((@{$newsetting{$type}} != 1) || ($newsetting{$type}[0] ne $default{$type})) {
                  
                 push(@{$changes{$type}},@{$newsetting{$type}});                  push(@{$changes{$type}},@{$newsetting{$type}});
             }              }
             if ($others{$type} ne '') {              if ($others{$type} ne '') {
                 push(@{$changes{$type}},'others');                  push(@{$changes{$type}},'others');
             }              }
             if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {              if ($type eq 'helpdeskmail') {
                 if ($bcc{$type} ne '') {                  if ($bcc{$type} ne '') {
                     push(@{$changes{$type}},'bcc');                      push(@{$changes{$type}},'bcc');
                 }                  }
                 if (($includeloc{$type} =~ /^b|s$/) && ($includestr{$type} ne '')) {  
                     push(@{$changes{$type}},'include');  
                 }  
             }  
         }  
         if (ref($fields) eq 'ARRAY') {  
             foreach my $field (@{$fields}) {  
                 if ($contacts_hash{'contacts'}{'helpform'}{$field} ne 'yes') {  
                     push(@{$changes{'helpform'}},$field);  
                 }  
                 if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {  
                     if ($contacts_hash{'contacts'}{'helpform'}{'maxsize'} != 1) {  
                         push(@{$changes{'helpform'}},'maxsize');  
                     }  
                 }  
             }              }
         }          }
     }      }
     foreach my $item (@toggles) {  
         if (($env{'form.'.$item} == 1) && ($currsetting{$item} == 0)) {  
             $changes{$item} = 1;  
         } elsif ((!$env{'form.'.$item}) &&  
                  (($currsetting{$item} eq '') || ($currsetting{$item} == 1))) {  
             $changes{$item} = 1;  
         }  
     }  
     my $putresult = &Apache::lonnet::put_dom('configuration',\%contacts_hash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%contacts_hash,
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             &Apache::loncommon::devalidate_domconfig_cache($dom);  
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'domainconfig'} = 1;  
             }  
             my ($titles,$short_titles)  = &contact_titles();              my ($titles,$short_titles)  = &contact_titles();
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             foreach my $item (@contacts) {              foreach my $item (@contacts) {
Line 10732  sub modify_contacts { Line 6095  sub modify_contacts {
             }              }
             foreach my $type (@mailings) {              foreach my $type (@mailings) {
                 if (ref($changes{$type}) eq 'ARRAY') {                  if (ref($changes{$type}) eq 'ARRAY') {
                     if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {                      $resulttext .= '<li>'.$titles->{$type}.': ';
                         $resulttext .= '<li>'.$titles->{$type}.' -- '.&mt('sent to').': ';  
                     } else {  
                         $resulttext .= '<li>'.$titles->{$type}.': ';  
                     }  
                     my @text;                      my @text;
                     foreach my $item (@{$newsetting{$type}}) {                      foreach my $item (@{$newsetting{$type}}) {
                         push(@text,$short_titles->{$item});                          push(@text,$short_titles->{$item});
Line 10744  sub modify_contacts { Line 6103  sub modify_contacts {
                     if ($others{$type} ne '') {                      if ($others{$type} ne '') {
                         push(@text,$others{$type});                          push(@text,$others{$type});
                     }                      }
                     if (@text) {                      $resulttext .= '<span class="LC_cusr_emph">'.
                         $resulttext .= '<span class="LC_cusr_emph">'.                                     join(', ',@text).'</span>';
                                        join(', ',@text).'</span>';                      if ($type eq 'helpdeskmail') {
                     }  
                     if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {  
                         if ($bcc{$type} ne '') {                          if ($bcc{$type} ne '') {
                             my $bcctext;                              $resulttext .= '&nbsp;'.&mt('with Bcc to').': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';
                             if (@text) {  
                                 $bcctext = '&nbsp;'.&mt('with Bcc to');  
                             } else {  
                                 $bcctext = '(Bcc)';  
                             }  
                             $resulttext .= $bcctext.': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';  
                         } elsif (!@text) {  
                             $resulttext .= &mt('No one');  
                         }  
                         if ($includestr{$type} ne '') {  
                             if ($includeloc{$type} eq 'b') {  
                                 $resulttext .= '<br />'.&mt('Text automatically added to e-mail body:').' '.$includestr{$type};  
                             } elsif ($includeloc{$type} eq 's') {  
                                 $resulttext .= '<br />'.&mt('Text automatically added to e-mail subject:').' '.$includestr{$type};  
                             }  
                         }                          }
                     } elsif (!@text) {  
                         $resulttext .= &mt('No recipients');  
                     }                      }
                     $resulttext .= '</li>';                      $resulttext .= '</li>';
                 }                  }
             }              }
             if (ref($changes{'overrides'}) eq 'ARRAY') {  
                 my @deletions;  
                 foreach my $type (@{$changes{'overrides'}}) {  
                     if ($usertypeshash{$type}) {  
                         if (grep(/^\Q$type\E/,@overrides)) {  
                             $resulttext .= '<li>'.&mt("Overrides based on requester's affiliation set for [_1]",  
                                                       $usertypeshash{$type}).'<ul><li>';  
                             if (ref($newsetting{'override_'.$type}) eq 'HASH') {  
                                 my @text;  
                                 foreach my $item (@contacts) {  
                                     if ($newsetting{'override_'.$type}{$item}) {  
                                         push(@text,$short_titles->{$item});  
                                     }  
                                 }  
                                 if ($newsetting{'override_'.$type}{'others'} ne '') {  
                                     push(@text,$newsetting{'override_'.$type}{'others'});  
                                 }  
   
                                 if (@text) {  
                                     $resulttext .= &mt('Helpdesk e-mail sent to: [_1]',  
                                                        '<span class="LC_cusr_emph">'.join(', ',@text).'</span>');  
                                 }  
                                 if ($newsetting{'override_'.$type}{'bcc'} ne '') {  
                                     my $bcctext;  
                                     if (@text) {  
                                         $bcctext = '&nbsp;'.&mt('with Bcc to');  
                                     } else {  
                                         $bcctext = '(Bcc)';  
                                     }  
                                     $resulttext .= $bcctext.': <span class="LC_cusr_emph">'.$newsetting{'override_'.$type}{'bcc'}.'</span>';  
                                 } elsif (!@text) {  
                                      $resulttext .= &mt('Helpdesk e-mail sent to no one');  
                                 }  
                                 $resulttext .= '</li>';  
                                 if ($newsetting{'override_'.$type}{'include'} ne '') {  
                                     my ($loc,$str) = split(/:/,$newsetting{'override_'.$type}{'include'});  
                                     if ($loc eq 'b') {  
                                         $resulttext .= '<li>'.&mt('Text automatically added to e-mail body:').' '.&unescape($str).'</li>';  
                                     } elsif ($loc eq 's') {  
                                         $resulttext .= '<li>'.&mt('Text automatically added to e-mail subject:').' '.&unescape($str).'</li>';  
                                     }  
                                 }  
                             }  
                             $resulttext .= '</li></ul></li>';  
                         } else {  
                             push(@deletions,$usertypeshash{$type});  
                         }  
                     }  
                 }  
                 if (@deletions) {  
                     $resulttext .= '<li>'.&mt("Overrides based on requester's affiliation discontinued for: [_1]",  
                                               join(', ',@deletions)).'</li>';  
                 }  
             }  
             my @offon = ('off','on');  
             if ($changes{'reporterrors'}) {  
                 $resulttext .= '<li>'.  
                                &mt('E-mail error reports to [_1] set to "'.  
                                    $offon[$env{'form.reporterrors'}].'".',  
                                    &Apache::loncommon::modal_link('http://loncapa.org/core.html',  
                                        &mt('LON-CAPA core group - MSU'),600,500)).  
                                '</li>';  
             }  
             if ($changes{'reportupdates'}) {  
                 $resulttext .= '<li>'.  
                                 &mt('E-mail record of completed LON-CAPA updates to [_1] set to "'.  
                                     $offon[$env{'form.reportupdates'}].'".',  
                                     &Apache::loncommon::modal_link('http://loncapa.org/core.html',  
                                         &mt('LON-CAPA core group - MSU'),600,500)).  
                                 '</li>';  
             }  
             if ((ref($changes{'helpform'}) eq 'ARRAY') && (ref($fields) eq 'ARRAY')) {  
                 my (@optional,@required,@unused,$maxsizechg);  
                 foreach my $field (@{$changes{'helpform'}}) {  
                     if ($field eq 'maxsize') {  
                         $maxsizechg = 1;  
                         next;  
                     }  
                     if ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'yes') {  
                         push(@optional,$field);  
                     } elsif ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'no') {  
                         push(@unused,$field);  
                     } elsif ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'req') {  
                         push(@required,$field);  
                     }  
                 }  
                 if (@optional) {  
                     $resulttext .= '<li>'.  
                                    &mt('Help form fields changed to "Optional": [_1].',  
                                        '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @optional)).'</span>'.  
                                    '</li>';  
                 }  
                 if (@required) {  
                     $resulttext .= '<li>'.  
                                    &mt('Help form fields changed to "Required": [_1].',  
                                        '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @required)).'</span>'.  
                                    '</li>';  
                 }  
                 if (@unused) {  
                     $resulttext .= '<li>'.  
                                    &mt('Help form fields changed to "Not shown": [_1].',  
                                        '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @unused)).'</span>'.  
                                    '</li>';  
                 }  
                 if ($maxsizechg) {  
                     $resulttext .= '<li>'.  
                                    &mt('Max size for file uploaded to help form by logged-in user set to [_1] MB.',  
                                        $contacts_hash{'contacts'}{'helpform'}{'maxsize'}).  
                                    '</li>';  
                 }  
             }  
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
             $resulttext = &mt('No changes made to contacts and form settings');              $resulttext = &mt('No changes made to contact information');
         }          }
     } else {      } else {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
Line 10895  sub modify_contacts { Line 6124  sub modify_contacts {
     return $resulttext;      return $resulttext;
 }  }
   
 sub modify_passwords {  sub modify_usercreation {
     my ($r,$dom,$confname,$lastactref,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%current,%changes,%newvalues,@oktypes,$errors,      my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate);
         $updatedefaults,$updateconf);      my $warningmsg;
     my $customfn = 'resetpw.html';      if (ref($domconfig{'usercreation'}) eq 'HASH') {
     if (ref($domconfig{'passwords'}) eq 'HASH') {          foreach my $key (keys(%{$domconfig{'usercreation'}})) {
         %current = %{$domconfig{'passwords'}};              $curr_usercreation{$key} = $domconfig{'usercreation'}{$key};
     }  
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);  
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
     if (ref($types) eq 'ARRAY') {  
         @oktypes = @{$types};  
     }  
     push(@oktypes,'default');  
   
     my %titles = &Apache::lonlocal::texthash (  
         intauth_cost   => 'Encryption cost for bcrypt (positive integer)',  
         intauth_check  => 'Check bcrypt cost if authenticated',  
         intauth_switch => 'Existing crypt-based switched to bcrypt on authentication',  
         permanent      => 'Permanent e-mail address',  
         critical       => 'Critical notification address',  
         notify         => 'Notification address',  
         min            => 'Minimum password length',  
         max            => 'Maximum password length',  
         chars          => 'Required characters',  
         numsaved       => 'Number of previous passwords to save',  
         reset          => 'Resetting Forgotten Password',  
         intauth        => 'Encryption of Stored Passwords (Internal Auth)',  
         rules          => 'Rules for LON-CAPA Passwords',  
         crsownerchg    => 'Course Owner Changing Student Passwords',  
         username       => 'Username',  
         email          => 'E-mail address',  
     );  
   
 #  
 # Retrieve current domain configuration for internal authentication from $domconfig{'defaults'}.  
 #  
     my (%curr_defaults,%save_defaults);  
     if (ref($domconfig{'defaults'}) eq 'HASH') {  
         foreach my $key (keys(%{$domconfig{'defaults'}})) {  
             if ($key =~ /^intauth_(cost|check|switch)$/) {  
                 $curr_defaults{$key} = $domconfig{'defaults'}{$key};  
             } else {  
                 $save_defaults{$key} = $domconfig{'defaults'}{$key};  
             }  
         }  
     }  
     my %staticdefaults = (  
         'resetlink'      => 2,  
         'resetcase'      => \@oktypes,  
         'resetprelink'   => 'both',  
         'resetemail'     => ['critical','notify','permanent'],  
         'intauth_cost'   => 10,  
         'intauth_check'  => 0,  
         'intauth_switch' => 0,  
     );  
     $staticdefaults{'min'} = $Apache::lonnet::passwdmin;  
     foreach my $type (@oktypes) {  
         $staticdefaults{'resetpostlink'}{$type} = ['email','username'];  
     }  
     my $linklife = $env{'form.passwords_link'};  
     $linklife =~ s/^\s+|\s+$//g;  
     if (($linklife =~ /^\d+(|\.\d*)$/) && ($linklife > 0)) {  
         $newvalues{'resetlink'} = $linklife;  
         if ($current{'resetlink'}) {  
             if ($current{'resetlink'} ne $linklife) {  
                 $changes{'reset'} = 1;  
             }  
         } elsif (!ref($domconfig{passwords}) eq 'HASH') {  
             if ($staticdefaults{'resetlink'} ne $linklife) {  
                 $changes{'reset'} = 1;  
             }  
         }  
     } elsif ($current{'resetlink'}) {  
         $changes{'reset'} = 1;  
     }  
     my @casesens;  
     my @posscase = &Apache::loncommon::get_env_multiple('form.passwords_case_sensitive');  
     foreach my $case (sort(@posscase)) {  
         if (grep(/^\Q$case\E$/,@oktypes)) {  
             push(@casesens,$case);  
         }  
     }  
     $newvalues{'resetcase'} = \@casesens;  
     if (ref($current{'resetcase'}) eq 'ARRAY') {  
         my @diffs = &Apache::loncommon::compare_arrays($current{'resetcase'},\@casesens);  
         if (@diffs > 0) {  
             $changes{'reset'} = 1;  
         }  
     } elsif (!ref($domconfig{passwords}) eq 'HASH') {  
         my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetcase'},\@casesens);  
         if (@diffs > 0) {  
             $changes{'reset'} = 1;  
         }  
     }  
     if ($env{'form.passwords_prelink'} =~ /^(both|either)$/) {  
         $newvalues{'resetprelink'} = $env{'form.passwords_prelink'};  
         if (exists($current{'resetprelink'})) {  
             if ($current{'resetprelink'} ne $newvalues{'resetprelink'}) {  
                 $changes{'reset'} = 1;  
             }  
         } elsif (!ref($domconfig{passwords}) eq 'HASH') {  
             if ($staticdefaults{'resetprelink'} ne $newvalues{'resetprelink'}) {  
                 $changes{'reset'} = 1;  
             }  
         }  
     } elsif ($current{'resetprelink'}) {  
         $changes{'reset'} = 1;  
     }  
     foreach my $type (@oktypes) {  
         my @possplink = &Apache::loncommon::get_env_multiple('form.passwords_postlink_'.$type);  
         my @postlink;  
         foreach my $item (sort(@possplink)) {  
             if ($item =~ /^(email|username)$/) {  
                 push(@postlink,$item);  
             }  
         }  
         $newvalues{'resetpostlink'}{$type} = \@postlink;  
         unless ($changes{'reset'}) {  
             if (ref($current{'resetpostlink'}) eq 'HASH') {  
                 if (ref($current{'resetpostlink'}{$type}) eq 'ARRAY') {  
                     my @diffs = &Apache::loncommon::compare_arrays($current{'resetpostlink'}{$type},\@postlink);  
                     if (@diffs > 0) {  
                         $changes{'reset'} = 1;  
                     }  
                 } else {  
                     $changes{'reset'} = 1;  
                 }  
             } elsif (!ref($domconfig{passwords}) eq 'HASH') {  
                 my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetpostlink'}{$type},\@postlink);  
                 if (@diffs > 0) {  
                     $changes{'reset'} = 1;  
                 }  
             }  
         }  
     }  
     my @possemailsrc = &Apache::loncommon::get_env_multiple('form.passwords_emailsrc');  
     my @resetemail;  
     foreach my $item (sort(@possemailsrc)) {  
         if ($item =~ /^(permanent|critical|notify)$/) {  
             push(@resetemail,$item);  
         }  
     }  
     $newvalues{'resetemail'} = \@resetemail;  
     unless ($changes{'reset'}) {  
         if (ref($current{'resetemail'}) eq 'ARRAY') {  
             my @diffs = &Apache::loncommon::compare_arrays($current{'resetemail'},\@resetemail);  
             if (@diffs > 0) {  
                 $changes{'reset'} = 1;  
             }  
         } elsif (!ref($domconfig{passwords}) eq 'HASH') {  
             my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetemail'},\@resetemail);  
             if (@diffs > 0) {  
                 $changes{'reset'} = 1;  
             }  
         }  
     }  
     if ($env{'form.passwords_stdtext'} == 0) {  
         $newvalues{'resetremove'} = 1;  
         unless ($current{'resetremove'}) {  
             $changes{'reset'} = 1;  
         }          }
     } elsif ($current{'resetremove'}) {  
         $changes{'reset'} = 1;  
     }      }
     if ($env{'form.passwords_customfile.filename'} ne '') {      my @username_rule = &Apache::loncommon::get_env_multiple('form.username_rule');
         my $servadm = $r->dir_config('lonAdmEMail');      my @id_rule = &Apache::loncommon::get_env_multiple('form.id_rule');
         my $servadm = $r->dir_config('lonAdmEMail');      my @email_rule = &Apache::loncommon::get_env_multiple('form.email_rule');
         my ($configuserok,$author_ok,$switchserver) =      my @contexts = ('author','course','requestcrs','selfcreate');
             &config_check($dom,$confname,$servadm);      foreach my $item(@contexts) {
         my $error;          if ($item eq 'selfcreate') {
         if ($configuserok eq 'ok') {              @{$cancreate{$item}} = &Apache::loncommon::get_env_multiple('form.can_createuser_'.$item);
             if ($switchserver) {              my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
                 $error = &mt("Upload of file containing domain-specific text is not permitted to this server: [_1]",$switchserver);              if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) || ($domdefaults{'auth_def'} eq 'localauth'))) {
             } else {                  if (ref($cancreate{$item}) eq 'ARRAY') { 
                 if ($author_ok eq 'ok') {                      if (grep(/^login$/,@{$cancreate{$item}})) {
                     my ($result,$customurl) =                          $warningmsg = &mt('Although account creation has been set to be available for institutional logins, currently default authentication in this domain has not been set to support this.').' '.&mt('You need to set the default authentication type to Kerberos 4 or 5 (with a Kerberos domain specified), or to Local authentication, if the localauth module has been customized in your domain to authenticate institutional logins.');   
                         &publishlogo($r,'upload','passwords_customfile',$dom,  
                                      $confname,'customtext/resetpw','','',$customfn);  
                     if ($result eq 'ok') {  
                         $newvalues{'resetcustom'} = $customurl;  
                         $changes{'reset'} = 1;  
                     } else {  
                         $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$customfn,$result);  
                     }                      }
                 } else {  
                     $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3].  Error was: [_4].",$customfn,$confname,$dom,$author_ok);  
                 }                  }
             }              }
         } else {          } else {
             $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3].  Error was: [_4].",$customfn,$confname,$dom,$configuserok);              $cancreate{$item} = $env{'form.can_createuser_'.$item};
         }          }
         if ($error) {  
             &Apache::lonnet::logthis($error);  
             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';  
         }  
     } elsif ($current{'resetcustom'}) {  
         if ($env{'form.passwords_custom_del'}) {  
             $changes{'reset'} = 1;  
         } else {  
             $newvalues{'resetcustom'} = $current{'resetcustom'};  
         }  
     }  
     $env{'form.intauth_cost'} =~ s/^\s+|\s+$//g;  
     if (($env{'form.intauth_cost'} ne '') && ($env{'form.intauth_cost'} =~ /^\d+$/)) {  
         $save_defaults{'intauth_cost'} = $env{'form.intauth_cost'};  
         if ($save_defaults{'intauth_cost'} ne $curr_defaults{'intauth_cost'}) {  
             $changes{'intauth'} = 1;  
         }  
     } else {  
         $save_defaults{'intauth_cost'} = $curr_defaults{'intauth_cost'};  
     }  
     if ($env{'form.intauth_check'} =~ /^(0|1|2)$/) {  
         $save_defaults{'intauth_check'} = $env{'form.intauth_check'};  
         if ($save_defaults{'intauth_check'} ne $curr_defaults{'intauth_check'}) {  
             $changes{'intauth'} = 1;  
         }  
     } else {  
         $save_defaults{'intauth_check'} = $curr_defaults{'intauth_check'};  
     }  
     if ($env{'form.intauth_switch'} =~ /^(0|1|2)$/) {  
         $save_defaults{'intauth_switch'} = $env{'form.intauth_switch'};  
         if ($save_defaults{'intauth_switch'} ne $curr_defaults{'intauth_switch'}) {  
             $changes{'intauth'} = 1;  
         }  
     } else {  
         $save_defaults{'intauth_check'} = $curr_defaults{'intauth_check'};  
     }      }
     foreach my $item ('cost','check','switch') {      my ($othertitle,$usertypes,$types) = 
         if ($save_defaults{'intauth_'.$item} ne $domdefaults{'intauth_'.$item}) {          &Apache::loncommon::sorted_inst_types($dom);
             $domdefaults{'intauth_'.$item} = $save_defaults{'intauth_'.$item};      if (ref($types) eq 'ARRAY') {
             $updatedefaults = 1;          if (@{$types} > 0) {
         }              @{$cancreate{'statustocreate'}} = 
     }                  &Apache::loncommon::get_env_multiple('form.statustocreate');
     foreach my $rule ('min','max','numsaved') {  
         $env{'form.passwords_'.$rule} =~ s/^\s+|\s+$//g;  
         my $ruleok;  
         if ($rule eq 'min') {  
             if ($env{'form.passwords_'.$rule} =~ /^\d+$/) {  
                 if ($env{'form.passwords_'.$rule} >= $Apache::lonnet::passwdmin) {  
                     $ruleok = 1;  
                 }  
             }  
         } elsif (($env{'form.passwords_'.$rule} =~ /^\d+$/) &&  
                  ($env{'form.passwords_'.$rule} ne '0')) {  
             $ruleok = 1;  
         }  
         if ($ruleok) {  
             $newvalues{$rule} = $env{'form.passwords_'.$rule};  
             if (exists($current{$rule})) {  
                 if ($newvalues{$rule} ne $current{$rule}) {  
                     $changes{'rules'} = 1;  
                 }  
             } elsif ($rule eq 'min') {  
                 if ($staticdefaults{$rule} ne $newvalues{$rule}) {  
                     $changes{'rules'} = 1;  
                 }  
             } else {  
                 $changes{'rules'} = 1;  
             }  
         } elsif (exists($current{$rule})) {  
             $changes{'rules'} = 1;  
         }  
     }  
     my @posschars = &Apache::loncommon::get_env_multiple('form.passwords_chars');  
     my @chars;  
     foreach my $item (sort(@posschars)) {  
         if ($item =~ /^(uc|lc|num|spec)$/) {  
             push(@chars,$item);  
         }  
     }  
     $newvalues{'chars'} = \@chars;  
     unless ($changes{'rules'}) {  
         if (ref($current{'chars'}) eq 'ARRAY') {  
             my @diffs = &Apache::loncommon::compare_arrays($current{'chars'},\@chars);  
             if (@diffs > 0) {  
                 $changes{'rules'} = 1;  
             }  
         } else {          } else {
             if (@chars > 0) {              @{$cancreate{'statustocreate'}} = ();
                 $changes{'rules'} = 1;  
             }  
         }          }
           push(@contexts,'statustocreate');
     }      }
     my %crsownerchg = (      if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {
                         by => [],          foreach my $item (@contexts) {
                         for => [],              if (($item eq 'selfcreate') || ($item eq 'statustocreate')) {
                       );                  if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') {
     foreach my $item ('by','for') {                      foreach my $curr (@{$curr_usercreation{'cancreate'}{$item}}) {
         my @posstypes = &Apache::loncommon::get_env_multiple('form.passwords_crsowner_'.$item);                          if (ref($cancreate{$item}) eq 'ARRAY') {
         foreach my $type (sort(@posstypes)) {                              if (!grep(/^$curr$/,@{$cancreate{$item}})) {
             if (grep(/^\Q$type\E$/,@oktypes)) {                                  if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                 push(@{$crsownerchg{$item}},$type);                                      push(@{$changes{'cancreate'}},$item);
             }  
         }  
     }  
     $newvalues{'crsownerchg'} = \%crsownerchg;  
     if (ref($current{'crsownerchg'}) eq 'HASH') {  
         foreach my $item ('by','for') {  
             if (ref($current{'crsownerchg'}{$item}) eq 'ARRAY') {  
                 my @diffs = &Apache::loncommon::compare_arrays($current{'crsownerchg'}{$item},$crsownerchg{$item});  
                 if (@diffs > 0) {  
                     $changes{'crsownerchg'} = 1;  
                     last;  
                 }  
             }  
         }  
     } elsif (!(ref($domconfig{passwords}) eq 'HASH')) {  
         foreach my $item ('by','for') {  
             if (@{$crsownerchg{$item}} > 0) {  
                 $changes{'crsownerchg'} = 1;  
                 last;  
             }  
         }  
     }  
   
     my %confighash = (  
                         defaults  => \%save_defaults,  
                         passwords => \%newvalues,  
                      );  
     &process_captcha('passwords',\%changes,$confighash{'passwords'},$domconfig{'passwords'});  
   
     my $putresult = &Apache::lonnet::put_dom('configuration',\%confighash,$dom);  
     if ($putresult eq 'ok') {  
         if (keys(%changes) > 0) {  
             $resulttext = &mt('Changes made: ').'<ul>';  
             foreach my $key ('reset','intauth','rules','crsownerchg') {  
                 if ($changes{$key}) {  
                     unless ($key eq 'intauth') {  
                         $updateconf = 1;  
                     }  
                     $resulttext .= '<li>'.$titles{$key}.':<ul>';  
                     if ($key eq 'reset') {  
                         if ($confighash{'passwords'}{'captcha'} eq 'original') {  
                             $resulttext .= '<li>'.&mt('CAPTCHA validation set to use: original CAPTCHA').'</li>';  
                         } elsif ($confighash{'passwords'}{'captcha'} eq 'recaptcha') {  
                             $resulttext .= '<li>'.&mt('CAPTCHA validation set to use: reCAPTCHA').' '.  
                                            &mt('version: [_1]',$confighash{'passwords'}{'recaptchaversion'}).'<br />';  
                             if (ref($confighash{'passwords'}{'recaptchakeys'}) eq 'HASH') {  
                                 $resulttext .= &mt('Public key: [_1]',$confighash{'passwords'}{'recaptchakeys'}{'public'}).'</br>'.  
                                                &mt('Private key: [_1]',$confighash{'passwords'}{'recaptchakeys'}{'private'}).'</li>';  
                             }  
                         } else {  
                             $resulttext .= '<li>'.&mt('No CAPTCHA validation').'</li>';  
                         }  
                         if ($confighash{'passwords'}{'resetlink'}) {  
                             $resulttext .= '<li>'.&mt('Reset link expiration set to [quant,_1,hour]',$confighash{'passwords'}{'resetlink'}).'</li>';  
                         } else {  
                             $resulttext .= '<li>'.&mt('No reset link expiration set.').' '.  
                                                   &mt('Will default to 2 hours').'</li>';  
                         }  
                         if (ref($confighash{'passwords'}{'resetcase'}) eq 'ARRAY') {  
                             if (@{$confighash{'passwords'}{'resetcase'}} == 0) {  
                                 $resulttext .= '<li>'.&mt('User input for username and/or e-mail address not case sensitive for "Forgot Password" web form').'</li>';  
                             } else {  
                                 my $casesens;  
                                 foreach my $type (@{$confighash{'passwords'}{'resetcase'}}) {  
                                     if ($type eq 'default') {  
                                         $casesens .= $othertitle.', ';  
                                     } elsif ($usertypes->{$type} ne '') {  
                                         $casesens .= $usertypes->{$type}.', ';  
                                     }  
                                 }                                  }
                                 $casesens =~ s/\Q, \E$//;  
                                 $resulttext .= '<li>'.&mt('"Forgot Password" web form input for username and/or e-mail address is case-sensitive for: [_1]',$casesens).'</li>';  
                             }                              }
                         } else {  
                             $resulttext .= '<li>'.&mt('Case-sensitivity not set for "Forgot Password" web form').' '.&mt('Will default to case-sensitive for username and/or e-mail address for all').'</li>';  
                         }                          }
                         if ($confighash{'passwords'}{'resetprelink'} eq 'either') {                      }
                             $resulttext .= '<li>'.&mt('Users can enter either a username or an e-mail address in "Forgot Password" web form').'</li>';                  } else {
                         } else {                      if ($curr_usercreation{'cancreate'}{$item} eq '') {
                             $resulttext .= '<li>'.&mt('Users can enter both a username and an e-mail address in "Forgot Password" web form').'</li>';                          if (@{$cancreate{$item}} > 0) {
                               if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                   push(@{$changes{'cancreate'}},$item);
                               }
                         }                          }
                         if (ref($confighash{'passwords'}{'resetpostlink'}) eq 'HASH') {                      } else {
                             my $output;                          if ($curr_usercreation{'cancreate'}{$item} eq 'any') {
                             if (ref($types) eq 'ARRAY') {                              if (@{$cancreate{$item}} < 3) {
                                 foreach my $type (@{$types}) {                                  if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                     if (ref($confighash{'passwords'}{'resetpostlink'}{$type}) eq 'ARRAY') {                                      push(@{$changes{'cancreate'}},$item);
                                         if (@{$confighash{'passwords'}{'resetpostlink'}{$type}} == 0) {  
                                             $output .= $usertypes->{$type}.' -- '.&mt('none');  
                                         } else {  
                                             $output .= $usertypes->{$type}.' -- '.  
                                                        join(', ',map { $titles{$_}; } (@{$confighash{'passwords'}{'resetpostlink'}{$type}})).'; ';  
                                         }  
                                     }  
                                 }                                  }
                             }                              }
                             if (ref($confighash{'passwords'}{'resetpostlink'}{'default'}) eq 'ARRAY') {                          } elsif ($curr_usercreation{'cancreate'}{$item} eq 'none') {
                                 if (@{$confighash{'passwords'}{'resetpostlink'}{'default'}} == 0) {                              if (@{$cancreate{$item}} > 0) {
                                     $output .= $othertitle.' -- '.&mt('none');                                  if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                 } else {                                      push(@{$changes{'cancreate'}},$item);
                                     $output .= $othertitle.' -- '.  
                                                join(', ',map { $titles{$_}; } (@{$confighash{'passwords'}{'resetpostlink'}{'default'}}));  
                                 }                                  }
                             }                              }
                             if ($output) {                          } elsif (!grep(/^$curr_usercreation{'cancreate'}{$item}$/,@{$cancreate{$item}})) {
                                 $resulttext .= '<li>'.&mt('Information required for new password form (by user type) set to: [_1]',$output).'</li>';                              if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                             } else {                                  push(@{$changes{'cancreate'}},$item);
                                 $resulttext .= '<li>'.&mt('Information required for new password form not set.').' '.&mt('Will default to requiring both the username and an e-mail address').'</li>';  
                             }  
                         } else {  
                             $resulttext .= '<li>'.&mt('Information required for new password form not set.').' '.&mt('Will default to requiring both the username and an e-mail address').'</li>';  
                         }  
                         if (ref($confighash{'passwords'}{'resetemail'}) eq 'ARRAY') {  
                             if (@{$confighash{'passwords'}{'resetemail'}} > 0) {  
                                 $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$confighash{'passwords'}{'resetemail'}})).'</li>';  
                             } else {  
                                 $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';  
                             }  
                         } else {  
                             $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA usedfor verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';  
                         }  
                         if ($confighash{'passwords'}{'resetremove'}) {  
                             $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" web form not shown').'</li>';  
                         } else {  
                             $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" web form is shown').'</li>';  
                         }  
                         if ($confighash{'passwords'}{'resetcustom'}) {  
                             my $customlink = &Apache::loncommon::modal_link($confighash{'passwords'}{'resetcustom'},  
                                                                             &mt('custom text'),600,500,undef,undef,  
                                                                             undef,undef,'background-color:#ffffff');  
                             $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" form includes: [_1]',$customlink).'</li>';  
                         } else {  
                             $resulttext .= '<li>'.&mt('No custom text included in preamble to "Forgot Password" form').'</li>';  
                         }  
                     } elsif ($key eq 'intauth') {  
                         foreach my $item ('cost','switch','check') {  
                             my $value = $save_defaults{$key.'_'.$item};  
                             if ($item eq 'switch') {  
                                 my %optiondesc = &Apache::lonlocal::texthash (  
                                                      0 => 'No',  
                                                      1 => 'Yes',  
                                                      2 => 'Yes, and copy existing passwd file to passwd.bak file',  
                                                  );  
                                 if ($value =~ /^(0|1|2)$/) {  
                                     $value = $optiondesc{$value};  
                                 } else {  
                                     $value = &mt('none -- defaults to No');  
                                 }  
                             } elsif ($item eq 'check') {  
                                 my %optiondesc = &Apache::lonlocal::texthash (  
                                                      0 => 'No',  
                                                      1 => 'Yes, allow login then update passwd file using default cost (if higher)',  
                                                      2 => 'Yes, disallow login if stored cost is less than domain default',  
                                                  );  
                                 if ($value =~ /^(0|1|2)$/) {  
                                     $value = $optiondesc{$value};  
                                 } else {  
                                     $value = &mt('none -- defaults to No');  
                                 }  
                             }                              }
                             $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$titles{$key.'_'.$item},$value).'</li>';  
                         }                          }
                     } elsif ($key eq 'rules') {                      }
                         foreach my $rule ('min','max','numsaved') {                  }
                             if ($confighash{'passwords'}{$rule} eq '') {                  if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                 if ($rule eq 'min') {                      foreach my $type (@{$cancreate{$item}}) {
                                     $resulttext .= '<li>'.&mt('[_1] not set.',$titles{$rule});                          if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') {
                                                    ' '.&mt('Default of [_1] will be used',                              if (!grep(/^$type$/,@{$curr_usercreation{'cancreate'}{$item}})) {
                                                            $Apache::lonnet::passwdmin).'</li>';                                  if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                 } else {                                      push(@{$changes{'cancreate'}},$item);
                                     $resulttext .= '<li>'.&mt('[_1] set to none',$titles{$rule}).'</li>';  
                                 }                                  }
                             } else {  
                                 $resulttext .= '<li>'.&mt('[_1] set to [_2]',$titles{$rule},$confighash{'passwords'}{$rule}).'</li>';  
                             }                              }
                         }                          } elsif (($curr_usercreation{'cancreate'}{$item} ne 'any') &&
                         if (ref($confighash{'passwords'}{'chars'}) eq 'ARRAY') {                                   ($curr_usercreation{'cancreate'}{$item} ne 'none')) {
                             if (@{$confighash{'passwords'}{'chars'}} > 0) {                              if ($curr_usercreation{'cancreate'}{$item} ne $type) {
                                 my %rulenames = &Apache::lonlocal::texthash(                                  if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                                      uc => 'At least one upper case letter',                                      push(@{$changes{'cancreate'}},$item);
                                                      lc => 'At least one lower case letter',  
                                                      num => 'At least one number',  
                                                      spec => 'At least one non-alphanumeric',  
                                                    );  
                                 my $needed = '<ul><li>'.  
                                              join('</li><li>',map {$rulenames{$_} } @{$confighash{'passwords'}{'chars'}}).  
                                              '</li></ul>';  
                                 $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$titles{'chars'},$needed).'</li>';  
                             } else {  
                                 $resulttext .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';  
                             }  
                         } else {  
                             $resulttext .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';  
                         }  
                     } elsif ($key eq 'crsownerchg') {  
                         if (ref($confighash{'passwords'}{'crsownerchg'}) eq 'HASH') {  
                             if ((@{$confighash{'passwords'}{'crsownerchg'}{'by'}} == 0) ||  
                                 (@{$confighash{'passwords'}{'crsownerchg'}{'for'}} == 0)) {  
                                 $resulttext .= '<li>'.&mt('Course owner may not change student passwords.').'</li>';  
                             } else {  
                                 my %crsownerstr;  
                                 foreach my $item ('by','for') {  
                                     if (ref($confighash{'passwords'}{'crsownerchg'}{$item}) eq 'ARRAY') {  
                                         foreach my $type (@{$confighash{'passwords'}{'crsownerchg'}{$item}}) {  
                                             if ($type eq 'default') {  
                                                 $crsownerstr{$item} .= $othertitle.', ';  
                                             } elsif ($usertypes->{$type} ne '') {  
                                                 $crsownerstr{$item} .= $usertypes->{$type}.', ';  
                                             }  
                                         }  
                                         $crsownerstr{$item} =~ s/\Q, \E$//;  
                                     }  
                                 }                                  }
                                 $resulttext .= '<li>'.&mt('Course owner (with status: [_1]) may change passwords for students (with status: [_2]).',  
                                            $crsownerstr{'by'},$crsownerstr{'for'}).'</li>';  
                             }                              }
                         } else {  
                             $resulttext .= '<li>'.&mt('Course owner may not change student passwords.').'</li>';  
                         }                          }
                     }                      }
                     $resulttext .= '</ul></li>';  
                 }                  }
             }  
             $resulttext .= '</ul>';  
         } else {  
             $resulttext = &mt('No changes made to password settings');  
         }  
         my $cachetime = 24*60*60;  
         if ($updatedefaults) {  
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);  
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'domdefaults'} = 1;  
             }  
         }  
         if ($updateconf) {  
             &Apache::lonnet::do_cache_new('passwdconf',$dom,$confighash{'passwords'},$cachetime);  
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'passwdconf'} = 1;  
             }  
         }  
     } else {  
         $resulttext = '<span class="LC_error">'.  
             &mt('An error occurred: [_1]',$putresult).'</span>';  
     }  
     if ($errors) {  
         $resulttext .= '<p>'.&mt('The following errors occurred: ').'<ul>'.  
                        $errors.'</ul></p>';  
     }  
     return $resulttext;  
 }  
   
 sub modify_usercreation {  
     my ($dom,%domconfig) = @_;  
     my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate,%save_usercreate);  
     my $warningmsg;  
     if (ref($domconfig{'usercreation'}) eq 'HASH') {  
         foreach my $key (keys(%{$domconfig{'usercreation'}})) {  
             if ($key eq 'cancreate') {  
                 if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {  
                     foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {  
                         if (($item eq 'requestcrs') || ($item eq 'course') || ($item eq 'author')) {  
                             $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};  
                         } else {  
                             $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};  
                         }  
                     }  
                 }  
             } elsif ($key eq 'email_rule') {  
                 $save_usercreate{$key} = $domconfig{'usercreation'}{$key};  
             } else {              } else {
                 $curr_usercreation{$key} = $domconfig{'usercreation'}{$key};                  if ($curr_usercreation{'cancreate'}{$item} ne $cancreate{$item}) {
             }                      push(@{$changes{'cancreate'}},$item);
         }                  }
     }  
     my @username_rule = &Apache::loncommon::get_env_multiple('form.username_rule');  
     my @id_rule = &Apache::loncommon::get_env_multiple('form.id_rule');  
     my @contexts = ('author','course','requestcrs');  
     foreach my $item(@contexts) {  
         $cancreate{$item} = $env{'form.can_createuser_'.$item};  
     }  
     if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {  
         foreach my $item (@contexts) {  
             if ($curr_usercreation{'cancreate'}{$item} ne $cancreate{$item}) {  
                 push(@{$changes{'cancreate'}},$item);  
             }              }
         }          }
     } elsif (ref($curr_usercreation{'cancreate'}) eq 'ARRAY') {      } elsif (ref($curr_usercreation{'cancreate'}) eq 'ARRAY') {
Line 11521  sub modify_usercreation { Line 6275  sub modify_usercreation {
         push(@{$changes{'id_rule'}},@id_rule);          push(@{$changes{'id_rule'}},@id_rule);
     }      }
   
       if (ref($curr_usercreation{'email_rule'}) eq 'ARRAY') {
           foreach my $type (@{$curr_usercreation{'email_rule'}}) {
               if (!grep(/^\Q$type\E$/,@email_rule)) {
                   push(@{$changes{'email_rule'}},$type);
               }
           }
           foreach my $type (@email_rule) {
               if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'email_rule'}})) {
                   push(@{$changes{'email_rule'}},$type);
               }
           }
       } else {
           push(@{$changes{'email_rule'}},@email_rule);
       }
   
     my @authen_contexts = ('author','course','domain');      my @authen_contexts = ('author','course','domain');
     my @authtypes = ('int','krb4','krb5','loc');      my @authtypes = ('int','krb4','krb5','loc');
     my %authhash;      my %authhash;
Line 11551  sub modify_usercreation { Line 6320  sub modify_usercreation {
         }          }
     }      }
   
     $save_usercreate{'cancreate'}{'course'} = $cancreate{'course'};   
     $save_usercreate{'cancreate'}{'author'} = $cancreate{'author'};  
     $save_usercreate{'cancreate'}{'requestcrs'} = $cancreate{'requestcrs'};  
     $save_usercreate{'id_rule'} = \@id_rule;  
     $save_usercreate{'username_rule'} = \@username_rule,  
     $save_usercreate{'authtypes'} = \%authhash;  
   
     my %usercreation_hash =  (      my %usercreation_hash =  (
         usercreation     => \%save_usercreate,              usercreation => {
     );                                cancreate     => \%cancreate,
                                 username_rule => \@username_rule,
                                 id_rule       => \@id_rule,
                                 email_rule    => \@email_rule,
                                 authtypes     => \%authhash,
                               }
               );
   
     my $putresult = &Apache::lonnet::put_dom('configuration',\%usercreation_hash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%usercreation_hash,
                                              $dom);                                               $dom);
   
     if ($putresult eq 'ok') {  
         if (keys(%changes) > 0) {  
             $resulttext = &mt('Changes made:').'<ul>';  
             if (ref($changes{'cancreate'}) eq 'ARRAY') {  
                 my %lt = &usercreation_types();  
                 foreach my $type (@{$changes{'cancreate'}}) {  
                     my $chgtext = $lt{$type}.', ';  
                     if ($cancreate{$type} eq 'none') {  
                         $chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.');  
                     } elsif ($cancreate{$type} eq 'any') {  
                         $chgtext .= &mt('creation of new users is permitted for both institutional and non-institutional usernames.');  
                     } elsif ($cancreate{$type} eq 'official') {  
                         $chgtext .= &mt('creation of new users is only permitted for institutional usernames.');  
                     } elsif ($cancreate{$type} eq 'unofficial') {  
                         $chgtext .= &mt('creation of new users is only permitted for non-institutional usernames.');  
                     }  
                     $resulttext .= '<li>'.$chgtext.'</li>';  
                 }  
             }  
             if (ref($changes{'username_rule'}) eq 'ARRAY') {  
                 my ($rules,$ruleorder) =   
                     &Apache::lonnet::inst_userrules($dom,'username');  
                 my $chgtext = '<ul>';  
                 foreach my $type (@username_rule) {  
                     if (ref($rules->{$type}) eq 'HASH') {  
                         $chgtext .= '<li>'.$rules->{$type}{'name'}.'</li>';  
                     }  
                 }  
                 $chgtext .= '</ul>';  
                 if (@username_rule > 0) {  
                     $resulttext .= '<li>'.&mt('Usernames with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';       
                 } else {  
                     $resulttext .= '<li>'.&mt('There are now no username formats restricted to verified users in the institutional directory.').'</li>';   
                 }  
             }  
             if (ref($changes{'id_rule'}) eq 'ARRAY') {  
                 my ($idrules,$idruleorder) =   
                     &Apache::lonnet::inst_userrules($dom,'id');  
                 my $chgtext = '<ul>';  
                 foreach my $type (@id_rule) {  
                     if (ref($idrules->{$type}) eq 'HASH') {  
                         $chgtext .= '<li>'.$idrules->{$type}{'name'}.'</li>';  
                     }  
                 }  
                 $chgtext .= '</ul>';  
                 if (@id_rule > 0) {  
                     $resulttext .= '<li>'.&mt('IDs with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';  
                 } else {  
                     $resulttext .= '<li>'.&mt('There are now no ID formats restricted to verified users in the institutional directory.').'</li>';  
                 }  
             }  
             my %authname = &authtype_names();  
             my %context_title = &context_names();  
             if (ref($changes{'authtypes'}) eq 'ARRAY') {  
                 my $chgtext = '<ul>';  
                 foreach my $type (@{$changes{'authtypes'}}) {  
                     my @allowed;  
                     $chgtext .= '<li><span class="LC_cusr_emph">'.$context_title{$type}.'</span> - '.&mt('assignable authentication types: ');  
                     foreach my $auth (@authtypes) {  
                         if ($authhash{$type}{$auth}) {  
                             push(@allowed,$authname{$auth});  
                         }  
                     }  
                     if (@allowed > 0) {  
                         $chgtext .= join(', ',@allowed).'</li>';  
                     } else {  
                         $chgtext .= &mt('none').'</li>';  
                     }  
                 }  
                 $chgtext .= '</ul>';  
                 $resulttext .= '<li>'.&mt('Authentication types available for assignment to new users').'<br />'.$chgtext;  
                 $resulttext .= '</li>';  
             }  
             $resulttext .= '</ul>';  
         } else {  
             $resulttext = &mt('No changes made to user creation settings');  
         }  
     } else {  
         $resulttext = '<span class="LC_error">'.  
             &mt('An error occurred: [_1]',$putresult).'</span>';  
     }  
     if ($warningmsg ne '') {  
         $resulttext .= '<br /><span class="LC_warning">'.$warningmsg.'</span><br />';  
     }  
     return $resulttext;  
 }  
   
 sub modify_selfcreation {  
     my ($dom,$lastactref,%domconfig) = @_;  
     my ($resulttext,$warningmsg,%curr_usercreation,%curr_usermodify,%curr_inststatus,%changes,%cancreate);  
     my (%save_usercreate,%save_usermodify,%save_inststatus,@types,%usertypes);  
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);  
     my ($othertitle,$usertypesref,$typesref) = &Apache::loncommon::sorted_inst_types($dom);  
     if (ref($typesref) eq 'ARRAY') {  
         @types = @{$typesref};  
     }  
     if (ref($usertypesref) eq 'HASH') {  
         %usertypes = %{$usertypesref};  
     }  
     $usertypes{'default'} = $othertitle;  
 #  
 # Retrieve current domain configuration for self-creation of usernames from $domconfig{'usercreation'}.  
 #  
     if (ref($domconfig{'usercreation'}) eq 'HASH') {  
         foreach my $key (keys(%{$domconfig{'usercreation'}})) {  
             if ($key eq 'cancreate') {  
                 if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {  
                     foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {  
                         if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||  
                             ($item eq 'captcha') || ($item eq 'recaptchakeys') ||  
                             ($item eq 'recaptchaversion') || ($item eq 'notify') ||  
                             ($item eq 'emailusername') || ($item eq 'shibenv') ||  
                             ($item eq 'selfcreateprocessing') || ($item eq 'emailverified') ||  
                             ($item eq 'emailoptions') || ($item eq 'emaildomain')) {  
                             $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};  
                         } else {  
                             $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};  
                         }  
                     }  
                 }  
             } elsif ($key eq 'email_rule') {  
                 $curr_usercreation{$key} = $domconfig{'usercreation'}{$key};  
             } else {  
                 $save_usercreate{$key} = $domconfig{'usercreation'}{$key};  
             }  
         }  
     }  
 #  
 # Retrieve current domain configuration for self-creation of usernames from $domconfig{'usermodification'}.  
 #  
     if (ref($domconfig{'usermodification'}) eq 'HASH') {  
         foreach my $key (keys(%{$domconfig{'usermodification'}})) {  
             if ($key eq 'selfcreate') {  
                 $curr_usermodify{$key} = $domconfig{'usermodification'}{$key};  
             } else {  
                 $save_usermodify{$key} = $domconfig{'usermodification'}{$key};  
             }  
         }  
     }  
 #  
 # Retrieve current domain configuration for institutional status types from $domconfig{'inststatus'}.  
 #  
     if (ref($domconfig{'inststatus'}) eq 'HASH') {  
         foreach my $key (keys(%{$domconfig{'inststatus'}})) {  
             if ($key eq 'inststatusguest') {  
                 $curr_inststatus{$key} = $domconfig{'inststatus'}{$key};  
             } else {  
                 $save_inststatus{$key} = $domconfig{'inststatus'}{$key};  
             }  
         }  
     }  
   
     my @contexts = ('selfcreate');  
     @{$cancreate{'selfcreate'}} = ();  
     %{$cancreate{'emailusername'}} = ();  
     if (@types) {  
         @{$cancreate{'statustocreate'}} = ();  
     }  
     %{$cancreate{'selfcreateprocessing'}} = ();  
     %{$cancreate{'shibenv'}} = ();  
     %{$cancreate{'emailverified'}} = ();  
     %{$cancreate{'emailoptions'}} = ();  
     %{$cancreate{'emaildomain'}} = ();  
     my %selfcreatetypes = (      my %selfcreatetypes = (
                              sso   => 'users authenticated by institutional single sign on',                               sso   => 'users authenticated by institutional single sign on',
                              login => 'users authenticated by institutional log-in',                               login => 'users authenticated by institutional log-in',
                              email => 'users verified by e-mail',                               email => 'users who provide a valid e-mail address for use as the username',
                           );                            );
 #  
 # Populate $cancreate{'selfcreate'} array reference with types of user, for which self-creation of user accounts  
 # is permitted.  
 #  
   
     my ($emailrules,$emailruleorder) = &Apache::lonnet::inst_userrules($dom,'email');  
   
     my (@statuses,%email_rule);  
     foreach my $item ('login','sso','email') {  
         if ($item eq 'email') {  
             if ($env{'form.cancreate_email'}) {  
                 if (@types) {  
                     my @poss_statuses = &Apache::loncommon::get_env_multiple('form.selfassign');  
                     foreach my $status (@poss_statuses) {  
                         if (grep(/^\Q$status\E$/,(@types,'default'))) {  
                             push(@statuses,$status);  
                         }  
                     }  
                     $save_inststatus{'inststatusguest'} = \@statuses;  
                 } else {  
                     push(@statuses,'default');  
                 }  
                 if (@statuses) {  
                     my %curr_rule;  
                     if (ref($curr_usercreation{'email_rule'}) eq 'ARRAY') {  
                         foreach my $type (@statuses) {  
                             $curr_rule{$type} = $curr_usercreation{'email_rule'};  
                         }  
                     } elsif (ref($curr_usercreation{'email_rule'}) eq 'HASH') {  
                         foreach my $type (@statuses) {  
                             $curr_rule{$type} = $curr_usercreation{'email_rule'}{$type};  
                         }  
                     }  
                     push(@{$cancreate{'selfcreate'}},'email');  
                     push(@contexts,('selfcreateprocessing','emailverified','emailoptions'));  
                     my %curremaildom;  
                     if (ref($curr_usercreation{'cancreate'}{'emaildomain'}) eq 'HASH') {  
                         %curremaildom = %{$curr_usercreation{'cancreate'}{'emaildomain'}};  
                     }  
                     foreach my $type (@statuses) {  
                         if ($env{'form.cancreate_emailprocess_'.$type} =~ /^(?:approval|automatic)$/) {  
                             $cancreate{'selfcreateprocessing'}{$type} = $env{'form.cancreate_emailprocess_'.$type};  
                         }  
                         if ($env{'form.cancreate_usernameoptions_'.$type} =~ /^(?:all|first|free)$/) {  
                             $cancreate{'emailverified'}{$type} = $env{'form.cancreate_usernameoptions_'.$type};  
                         }  
                         if ($env{'form.cancreate_emailoptions_'.$type} =~ /^(any|inst|noninst|custom)$/) {  
 #  
 # Retrieve rules (if any) governing types of e-mail address which may be used to verify a username.  
 #  
                             my $chosen = $1;  
                             if (($chosen eq 'inst') || ($chosen eq 'noninst')) {  
                                 my $emaildom;  
                                 if ($env{'form.cancreate_emaildomain_'.$chosen.'_'.$type} =~ /^\@[^\@]+$/) {  
                                     $emaildom = $env{'form.cancreate_emaildomain_'.$chosen.'_'.$type};  
                                     $cancreate{'emaildomain'}{$type}{$chosen} = $emaildom;  
                                     if (ref($curremaildom{$type}) eq 'HASH') {  
                                         if (exists($curremaildom{$type}{$chosen})) {  
                                             if ($curremaildom{$type}{$chosen} ne $emaildom) {  
                                                 push(@{$changes{'cancreate'}},'emaildomain');  
                                             }  
                                         } elsif ($emaildom ne '') {  
                                             push(@{$changes{'cancreate'}},'emaildomain');  
                                         }  
                                     } elsif ($emaildom ne '') {  
                                         push(@{$changes{'cancreate'}},'emaildomain');  
                                     }  
                                 }  
                                 $cancreate{'emailoptions'}{$type} = $env{'form.cancreate_emailoptions_'.$type};  
                             } elsif ($chosen eq 'custom') {  
                                 my @possemail_rules = &Apache::loncommon::get_env_multiple('form.email_rule_'.$type);  
                                 $email_rule{$type} = [];  
                                 if (ref($emailrules) eq 'HASH') {  
                                     foreach my $rule (@possemail_rules) {  
                                         if (exists($emailrules->{$rule})) {  
                                             push(@{$email_rule{$type}},$rule);  
                                         }  
                                     }  
                                 }  
                                 if (@{$email_rule{$type}}) {  
                                     $cancreate{'emailoptions'}{$type} = 'custom';  
                                     if (ref($curr_rule{$type}) eq 'ARRAY') {  
                                         if (@{$curr_rule{$type}} > 0) {  
                                             foreach my $rule (@{$curr_rule{$type}}) {  
                                                 if (!grep(/^\Q$rule\E$/,@{$email_rule{$type}})) {  
                                                     push(@{$changes{'email_rule'}},$type);  
                                                 }  
                                             }  
                                         }  
                                         foreach my $type (@{$email_rule{$type}}) {  
                                             if (!grep(/^\Q$type\E$/,@{$curr_rule{$type}})) {  
                                                 push(@{$changes{'email_rule'}},$type);  
                                             }  
                                         }  
                                     } else {  
                                         push(@{$changes{'email_rule'}},$type);  
                                     }  
                                 }  
                             } else {  
                                 $cancreate{'emailoptions'}{$type} = $env{'form.cancreate_emailoptions_'.$type};  
                             }  
                         }  
                     }  
                     if (@types) {  
                         if (ref($curr_inststatus{'inststatusguest'}) eq 'ARRAY') {  
                             my @changed = &Apache::loncommon::compare_arrays(\@statuses,$curr_inststatus{'inststatusguest'});  
                             if (@changed) {  
                                 push(@{$changes{'inststatus'}},'inststatusguest');  
                             }  
                         } else {  
                             push(@{$changes{'inststatus'}},'inststatusguest');  
                         }  
                     }  
                 } else {  
                     delete($env{'form.cancreate_email'});  
                     if (ref($curr_inststatus{'inststatusguest'}) eq 'ARRAY') {  
                         if (@{$curr_inststatus{'inststatusguest'}} > 0) {  
                             push(@{$changes{'inststatus'}},'inststatusguest');  
                         }  
                     }  
                 }  
             } else {  
                 $save_inststatus{'inststatusguest'} = [];  
                 if (ref($curr_inststatus{'inststatusguest'}) eq 'ARRAY') {  
                     if (@{$curr_inststatus{'inststatusguest'}} > 0) {  
                         push(@{$changes{'inststatus'}},'inststatusguest');  
                     }  
                 }  
             }  
         } else {  
             if ($env{'form.cancreate_'.$item}) {  
                 push(@{$cancreate{'selfcreate'}},$item);  
             }  
         }  
     }  
     my (%userinfo,%savecaptcha);  
     my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();  
 #  
 # Populate $cancreate{'emailusername'}{$type} hash ref with information fields (if new user will provide data  
 # value set to one), if self-creation with e-mail address permitted, where $type is user type: faculty, staff, student etc.  
 #  
   
     if ($env{'form.cancreate_email'}) {  
         push(@contexts,'emailusername');  
         if (@statuses) {  
             foreach my $type (@statuses) {  
                 if (ref($infofields) eq 'ARRAY') {  
                     foreach my $field (@{$infofields}) {  
                         if ($env{'form.canmodify_emailusername_'.$type.'_'.$field} =~ /^(required|optional)$/) {  
                             $cancreate{'emailusername'}{$type}{$field} = $1;  
                         }  
                     }  
                 }  
             }  
         }  
 #  
 # Populate $cancreate{'notify'} hash ref with names of Domain Coordinators who are to be notified of  
 # queued requests for self-creation of account verified by e-mail.  
 #  
   
         my @approvalnotify = &Apache::loncommon::get_env_multiple('form.selfcreationnotifyapproval');  
         @approvalnotify = sort(@approvalnotify);  
         $cancreate{'notify'}{'approval'} = join(',',@approvalnotify);  
         if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {  
             if (ref($curr_usercreation{'cancreate'}{'notify'}) eq 'HASH') {  
                 if ($curr_usercreation{'cancreate'}{'notify'}{'approval'} ne $cancreate{'notify'}{'approval'}) {  
                     push(@{$changes{'cancreate'}},'notify');  
                 }  
             } else {  
                 if ($cancreate{'notify'}{'approval'}) {  
                     push(@{$changes{'cancreate'}},'notify');  
                 }  
             }  
         } elsif ($cancreate{'notify'}{'approval'}) {  
             push(@{$changes{'cancreate'}},'notify');  
         }  
   
         &process_captcha('cancreate',\%changes,\%savecaptcha,$curr_usercreation{'cancreate'});  
     }  
 #    
 # Check if domain default is set appropriately, if self-creation of accounts is to be available for  
 # institutional log-in.  
 #  
     if (grep(/^login$/,@{$cancreate{'selfcreate'}})) {  
         if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) ||   
                ($domdefaults{'auth_def'} eq 'localauth'))) {  
             $warningmsg = &mt('Although account creation has been set to be available for institutional logins, currently default authentication in this domain has not been set to support this.').' '.  
                           &mt('You need to set the default authentication type to Kerberos 4 or 5 (with a Kerberos domain specified), or to Local authentication, if the localauth module has been customized in your domain to authenticate institutional logins.');  
         }  
     }  
     my @fields = ('lastname','firstname','middlename','generation',  
                   'permanentemail','id');  
     my @shibfields = (@fields,'inststatus');  
     my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();  
 #  
 # Where usernames may created for institutional log-in and/or institutional single sign on:  
 # (a) populate $cancreate{'statustocreate'} array reference with institutional status types who  
 # may self-create accounts   
 # (b) populate $save_usermodify{'selfcreate'} hash reference with status types, and information fields  
 # which the user may supply, if institutional data is unavailable.  
 #  
     if (($env{'form.cancreate_login'}) || ($env{'form.cancreate_sso'})) {  
         if (@types) {  
             @{$cancreate{'statustocreate'}} = &Apache::loncommon::get_env_multiple('form.statustocreate');  
             push(@contexts,'statustocreate');  
             foreach my $type (@types) {  
                 my @modifiable =  &Apache::loncommon::get_env_multiple('form.canmodify_'.$type);  
                 foreach my $field (@fields) {  
                     if (grep(/^\Q$field\E$/,@modifiable)) {  
                         $save_usermodify{'selfcreate'}{$type}{$field} = 1;  
                     } else {  
                         $save_usermodify{'selfcreate'}{$type}{$field} = 0;  
                     }  
                 }  
             }  
             if (ref($curr_usermodify{'selfcreate'}) eq 'HASH') {  
                 foreach my $type (@types) {  
                     if (ref($curr_usermodify{'selfcreate'}{$type}) eq 'HASH') {  
                         foreach my $field (@fields) {  
                             if ($save_usermodify{'selfcreate'}{$type}{$field} ne  
                                 $curr_usermodify{'selfcreate'}{$type}{$field}) {  
                                 push(@{$changes{'selfcreate'}},$type);  
                                 last;  
                             }  
                         }  
                     }  
                 }  
             } else {  
                 foreach my $type (@types) {  
                     push(@{$changes{'selfcreate'}},$type);  
                 }  
             }  
         }  
         foreach my $field (@shibfields) {  
             if ($env{'form.shibenv_'.$field} ne '') {  
                 $cancreate{'shibenv'}{$field} = $env{'form.shibenv_'.$field};  
             }  
         }  
         if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {  
             if (ref($curr_usercreation{'cancreate'}{'shibenv'}) eq 'HASH') {  
                 foreach my $field (@shibfields) {  
                     if ($env{'form.shibenv_'.$field} ne $curr_usercreation{'cancreate'}{'shibenv'}{$field}) {  
                         push(@{$changes{'cancreate'}},'shibenv');  
                     }  
                 }  
             } else {  
                 foreach my $field (@shibfields) {  
                     if ($env{'form.shibenv_'.$field}) {  
                         push(@{$changes{'cancreate'}},'shibenv');  
                         last;  
                     }  
                 }  
             }  
         }  
     }  
     foreach my $item (@contexts) {  
         if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') {  
             foreach my $curr (@{$curr_usercreation{'cancreate'}{$item}}) {  
                 if (ref($cancreate{$item}) eq 'ARRAY') {  
                     if (!grep(/^$curr$/,@{$cancreate{$item}})) {  
                         if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                             push(@{$changes{'cancreate'}},$item);  
                         }  
                     }  
                 }  
             }  
             if (ref($cancreate{$item}) eq 'ARRAY') {  
                 foreach my $type (@{$cancreate{$item}}) {  
                     if (!grep(/^$type$/,@{$curr_usercreation{'cancreate'}{$item}})) {  
                         if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                             push(@{$changes{'cancreate'}},$item);  
                         }  
                     }  
                 }  
             }  
         } elsif (ref($curr_usercreation{'cancreate'}{$item}) eq 'HASH') {  
             if (ref($cancreate{$item}) eq 'HASH') {  
                 foreach my $type (keys(%{$curr_usercreation{'cancreate'}{$item}})) {  
                     if (ref($curr_usercreation{'cancreate'}{$item}{$type}) eq 'HASH') {  
                         foreach my $field (keys(%{$curr_usercreation{'cancreate'}{$item}{$type}})) {  
                             unless ($curr_usercreation{'cancreate'}{$item}{$type}{$field} eq $cancreate{$item}{$type}{$field}) {  
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                     push(@{$changes{'cancreate'}},$item);  
                                 }  
                             }  
                         }  
                     } elsif (($item eq 'selfcreateprocessing') || ($item eq 'emailverified') || ($item eq 'emailoptions')) {  
                         if ($cancreate{$item}{$type} ne $curr_usercreation{'cancreate'}{$item}{$type}) {  
                             if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                 push(@{$changes{'cancreate'}},$item);  
                             }  
                         }  
                     }  
                 }  
                 foreach my $type (keys(%{$cancreate{$item}})) {  
                     if (ref($cancreate{$item}{$type}) eq 'HASH') {  
                         foreach my $field (keys(%{$cancreate{$item}{$type}})) {  
                             if (ref($curr_usercreation{'cancreate'}{$item}{$type}) eq 'HASH') {  
                                 unless ($curr_usercreation{'cancreate'}{$item}{$type}{$field} eq $cancreate{$item}{$type}{$field}) {  
                                     if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                         push(@{$changes{'cancreate'}},$item);  
                                     }  
                                 }  
                             } else {  
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                     push(@{$changes{'cancreate'}},$item);  
                                 }  
                             }  
                         }  
                     } elsif (($item eq 'selfcreateprocessing') || ($item eq 'emailverified') || ($item eq 'emailoptions')) {  
                         if ($cancreate{$item}{$type} ne $curr_usercreation{'cancreate'}{$item}{$type}) {  
                             if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                 push(@{$changes{'cancreate'}},$item);  
                             }  
                         }  
                     }  
                 }  
             }  
         } elsif ($curr_usercreation{'cancreate'}{$item}) {  
             if (ref($cancreate{$item}) eq 'ARRAY') {  
                 if (!grep(/^\Q$curr_usercreation{'cancreate'}{$item}\E$/,@{$cancreate{$item}})) {  
                     if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                         push(@{$changes{'cancreate'}},$item);  
                     }  
                 }  
             }  
         } elsif (($item eq 'selfcreateprocessing') || ($item eq 'emailverified') || ($item eq 'emailoptions')) {  
             if (ref($cancreate{$item}) eq 'HASH') {  
                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                     push(@{$changes{'cancreate'}},$item);  
                 }  
             }  
         } elsif ($item eq 'emailusername') {  
             if (ref($cancreate{$item}) eq 'HASH') {  
                 foreach my $type (keys(%{$cancreate{$item}})) {  
                     if (ref($cancreate{$item}{$type}) eq 'HASH') {  
                         foreach my $field (keys(%{$cancreate{$item}{$type}})) {  
                             if ($cancreate{$item}{$type}{$field}) {  
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                     push(@{$changes{'cancreate'}},$item);  
                                 }  
                                 last;  
                             }  
                         }  
                     }  
                 }  
             }  
         }  
     }  
 #  
 # Populate %save_usercreate hash with updates to self-creation configuration.  
 #  
     $save_usercreate{'cancreate'}{'captcha'} = $savecaptcha{'captcha'};  
     $save_usercreate{'cancreate'}{'recaptchakeys'} = $savecaptcha{'recaptchakeys'};  
     $save_usercreate{'cancreate'}{'recaptchaversion'} = $savecaptcha{'recaptchaversion'};  
     $save_usercreate{'cancreate'}{'selfcreate'} = $cancreate{'selfcreate'};  
     if (ref($cancreate{'notify'}) eq 'HASH') {  
         $save_usercreate{'cancreate'}{'notify'} = $cancreate{'notify'};  
     }  
     if (ref($cancreate{'selfcreateprocessing'}) eq 'HASH') {  
         $save_usercreate{'cancreate'}{'selfcreateprocessing'} = $cancreate{'selfcreateprocessing'};  
     }  
     if (ref($cancreate{'emailverified'}) eq 'HASH') {  
         $save_usercreate{'cancreate'}{'emailverified'} = $cancreate{'emailverified'};  
     }  
     if (ref($cancreate{'emailoptions'}) eq 'HASH') {  
         $save_usercreate{'cancreate'}{'emailoptions'} = $cancreate{'emailoptions'};  
     }  
     if (ref($cancreate{'emaildomain'}) eq 'HASH') {  
         $save_usercreate{'cancreate'}{'emaildomain'} = $cancreate{'emaildomain'};  
     }  
     if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {  
         $save_usercreate{'cancreate'}{'statustocreate'} = $cancreate{'statustocreate'};  
     }  
     if (ref($cancreate{'shibenv'}) eq 'HASH') {  
         $save_usercreate{'cancreate'}{'shibenv'} = $cancreate{'shibenv'};  
     }  
     $save_usercreate{'cancreate'}{'emailusername'} = $cancreate{'emailusername'};  
     $save_usercreate{'email_rule'} = \%email_rule;  
   
     my %userconfig_hash = (  
             usercreation     => \%save_usercreate,  
             usermodification => \%save_usermodify,  
             inststatus       => \%save_inststatus,  
     );  
   
     my $putresult = &Apache::lonnet::put_dom('configuration',\%userconfig_hash,  
                                              $dom);  
 #  
 # Accumulate details of changes to domain configuration for self-creation of usernames in $resulttext  
 #  
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if (ref($changes{'cancreate'}) eq 'ARRAY') {              if (ref($changes{'cancreate'}) eq 'ARRAY') {
                 my %lt = &selfcreation_types();                  my %lt = &usercreation_types();
                 foreach my $type (@{$changes{'cancreate'}}) {                  foreach my $type (@{$changes{'cancreate'}}) {
                     my $chgtext = '';                      my $chgtext;
                       unless ($type eq 'statustocreate') {
                           $chgtext = $lt{$type}.', ';
                       }
                     if ($type eq 'selfcreate') {                      if ($type eq 'selfcreate') {
                         if (@{$cancreate{$type}} == 0) {                          if (@{$cancreate{$type}} == 0) {
                             $chgtext .= &mt('Self creation of a new user account is not permitted.');                              $chgtext .= &mt('creation of a new user account is not permitted.');
                         } else {                          } else {
                             $chgtext .= &mt('Self-creation of a new account is permitted for:').                              $chgtext .= &mt('creation of a new account is permitted for:').'<ul>';
                                         '<ul>';  
                             foreach my $case (@{$cancreate{$type}}) {                              foreach my $case (@{$cancreate{$type}}) {
                                 $chgtext .= '<li>'.$selfcreatetypes{$case}.'</li>';                                  $chgtext .= '<li>'.$selfcreatetypes{$case}.'</li>';
                             }                              }
Line 12145  sub modify_selfcreation { Line 6361  sub modify_selfcreation {
                                 if (grep(/^(login|sso)$/,@{$cancreate{$type}})) {                                  if (grep(/^(login|sso)$/,@{$cancreate{$type}})) {
                                     if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {                                      if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {
                                         if (@{$cancreate{'statustocreate'}} == 0) {                                          if (@{$cancreate{'statustocreate'}} == 0) {
                                             $chgtext .= '<span class="LC_warning">'.                                              $chgtext .= '<br /><span class="LC_warning">'.&mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").'</span>';
                                                         &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts via log-in or single sign-on.").  
                                                         '</span><br />';  
                                         }                                          }
                                     }                                      }
                                 }                                  }
                                 if (grep(/^email$/,@{$cancreate{$type}})) {  
                                     if (!@statuses) {  
                                         $chgtext .= '<span class="LC_warning">'.  
                                                     &mt("However, e-mail verification is currently set to 'unavailable' for all user types (including 'other'), so self-creation of accounts is not possible for non-institutional log-in.").  
                                                     '</span><br />';  
   
                                     }  
                                 }  
                             }                              }
                         }                          }
                     } elsif ($type eq 'shibenv') {  
                         if (keys(%{$cancreate{$type}}) == 0) {  
                             $chgtext .= &mt('Shibboleth-autheticated user does not use environment variables to set user information').'<br />';   
                         } else {  
                             $chgtext .= &mt('Shibboleth-autheticated user information set from environment variables, as follows:').  
                                         '<ul>';  
                             foreach my $field (@shibfields) {  
                                 next if ($cancreate{$type}{$field} eq '');  
                                 if ($field eq 'inststatus') {  
                                     $chgtext .= '<li>'.&mt('Institutional status').' -- '.$cancreate{$type}{$field}.'</li>';  
                                 } else {  
                                     $chgtext .= '<li>'.$fieldtitles{$field}.' -- '.$cancreate{$type}{$field}.'</li>';  
                                 }  
                             }  
                             $chgtext .= '</ul>';  
                         }  
                     } elsif ($type eq 'statustocreate') {                      } elsif ($type eq 'statustocreate') {
                         if ((ref($cancreate{'selfcreate'}) eq 'ARRAY') &&                          if ((ref($cancreate{'selfcreate'}) eq 'ARRAY') &&
                             (ref($cancreate{'statustocreate'}) eq 'ARRAY')) {                              (ref($cancreate{'statustocreate'}) eq 'ARRAY')) {
                             if (@{$cancreate{'selfcreate'}} > 0) {                              if (@{$cancreate{'selfcreate'}} > 0) {
                                 if (@{$cancreate{'statustocreate'}} == 0) {                                  if (@{$cancreate{'statustocreate'}} == 0) {
   
                                     $chgtext .= &mt("Institutional affiliations permitted to create accounts set to 'None'.");                                      $chgtext .= &mt("Institutional affiliations permitted to create accounts set to 'None'.");
                                     if (!grep(/^email$/,@{$cancreate{'selfcreate'}})) {                                      if (!grep(/^email$/,@{$cancreate{'selfcreate'}})) {
                                         $chgtext .= '<br />'.                                          $chgtext .= '<br /><span class="LC_warning">'.&mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").'</span>';
                                                     '<span class="LC_warning">'.                                      } 
                                                     &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").                                  } elsif (ref($usertypes) eq 'HASH') {
                                                     '</span>';  
                                     }  
                                 } elsif (keys(%usertypes) > 0) {  
                                     if (grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {                                      if (grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {
                                         $chgtext .= &mt('Creation of a new account for an institutional user is restricted to the following institutional affiliation(s):');                                          $chgtext .= &mt('Creation of a new account for an institutional user is restricted to the following institutional affiliation(s):');
                                     } else {                                      } else {
Line 12200  sub modify_selfcreation { Line 6388  sub modify_selfcreation {
                                         if ($case eq 'default') {                                          if ($case eq 'default') {
                                             $chgtext .= '<li>'.$othertitle.'</li>';                                              $chgtext .= '<li>'.$othertitle.'</li>';
                                         } else {                                          } else {
                                             $chgtext .= '<li>'.$usertypes{$case}.'</li>';                                              $chgtext .= '<li>'.$usertypes->{$case}.'</li>';
                                         }                                          }
                                     }                                      }
                                     $chgtext .= '</ul>';                                      $chgtext .= '</ul>';
                                     if (!grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {                                      if (!grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {
                                         $chgtext .= '<span class="LC_warning">'.                                          $chgtext .= '<br /><span class="LC_warning">'.&mt('However, users authenticated by institutional login/single sign on are not currently permitted to create accounts.').'</span>';
                                                     &mt('However, users authenticated by institutional login/single sign on are not currently permitted to create accounts.').  
                                                     '</span>';  
                                     }                                      }
                                 }                                  }
                             } else {                              } else {
Line 12217  sub modify_selfcreation { Line 6403  sub modify_selfcreation {
                                     $chgtext .= &mt('Although institutional affiliations permitted to create accounts were changed, self creation of accounts is not currently permitted for any authentication types.');                                      $chgtext .= &mt('Although institutional affiliations permitted to create accounts were changed, self creation of accounts is not currently permitted for any authentication types.');
                                 }                                  }
                             }                              }
                             $chgtext .= '<br />';  
                         }  
                     } elsif ($type eq 'selfcreateprocessing') {  
                         my %choices = &Apache::lonlocal::texthash (  
                                                                     automatic => 'Automatic approval',  
                                                                     approval  => 'Queued for approval',  
                                                                   );  
                         if (@types) {  
                             if (@statuses) {  
                                 $chgtext .= &mt('Processing of requests to create account with e-mail verification set as follows:').  
                                             '<ul>';  
                                 foreach my $status (@statuses) {  
                                     if ($status eq 'default') {  
                                         $chgtext .= '<li>'.$othertitle.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$status}}.'</li>';  
                                     } else {  
                                         $chgtext .= '<li>'.$usertypes{$status}.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$status}}.'</li>';  
                                     }  
                                 }  
                                 $chgtext .= '</ul>';  
                             }  
                         } else {  
                             $chgtext .= &mt('Processing of requests to create account with e-mail verification set to: "[_1]"',  
                                             $choices{$cancreate{'selfcreateprocessing'}{'default'}});  
                         }  
                     } elsif ($type eq 'emailverified') {  
                         my %options = &Apache::lonlocal::texthash (  
                                                                     all   => 'Same as e-mail',  
                                                                     first => 'Omit @domain',  
                                                                     free  => 'Free to choose',  
                                                                   );  
                         if (@types) {  
                             if (@statuses) {  
                                 $chgtext .= &mt('For self-created accounts verified by e-mail address, username is set as follows:').  
                                             '<ul>';  
                                 foreach my $status (@statuses) {  
                                     if ($status eq 'default') {  
                                         $chgtext .= '<li>'.$othertitle.' -- '.$options{$cancreate{'emailverified'}{$status}}.'</li>';  
                                     } else {  
                                         $chgtext .= '<li>'.$usertypes{$status}.' -- '.$options{$cancreate{'emailverified'}{$status}}.'</li>';  
                                     }  
                                 }  
                                 $chgtext .= '</ul>';  
                             }  
                         } else {  
                             $chgtext .= &mt("For self-created accounts verified by e-mail address, user's username is: '[_1]'",  
                                             $options{$cancreate{'emailverified'}{'default'}});  
                         }                          }
                     } elsif ($type eq 'emailoptions') {                      } else {
                         my %options = &Apache::lonlocal::texthash (                          if ($cancreate{$type} eq 'none') {
                                                                     any     => 'Any e-mail',                              $chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.');
                                                                     inst    => 'Institutional only',                          } elsif ($cancreate{$type} eq 'any') {
                                                                     noninst => 'Non-institutional only',                              $chgtext .= &mt('creation of new users is permitted for both institutional and non-institutional usernames.');
                                                                     custom  => 'Custom restrictions',                          } elsif ($cancreate{$type} eq 'official') {
                                                                   );                              $chgtext .= &mt('creation of new users is only permitted for institutional usernames.');
                         if (@types) {                          } elsif ($cancreate{$type} eq 'unofficial') {
                             if (@statuses) {                              $chgtext .= &mt('creation of new users is only permitted for non-institutional usernames.');
                                 $chgtext .= &mt('For self-created accounts verified by e-mail address, requirements for e-mail address are as follows:').  
                                             '<ul>';  
                                 foreach my $status (@statuses) {  
                                     if ($type eq 'default') {  
                                         $chgtext .= '<li>'.$othertitle.' -- '.$options{$cancreate{'emailoptions'}{$status}}.'</li>';  
                                     } else {  
                                         $chgtext .= '<li>'.$usertypes{$status}.' -- '.$options{$cancreate{'emailoptions'}{$status}}.'</li>';  
                                     }  
                                 }  
                                 $chgtext .= '</ul>';  
                             }  
                         } else {  
                             if ($cancreate{'emailoptions'}{'default'} eq 'any') {  
                                 $chgtext .= &mt('For self-created accounts verified by e-mail address, any e-mail may be used');  
                             } else {  
                                 $chgtext .= &mt('For self-created accounts verified by e-mail address, e-mail restricted to: "[_1]"',  
                                                 $options{$cancreate{'emailoptions'}{'default'}});  
                             }  
                         }  
                     } elsif ($type eq 'emaildomain') {  
                         my $output;  
                         if (@statuses) {  
                             foreach my $type (@statuses) {  
                                 if (ref($cancreate{'emaildomain'}{$type}) eq 'HASH') {  
                                     if ($cancreate{'emailoptions'}{$type} eq 'inst') {  
                                         if ($type eq 'default') {  
                                             if ((ref($cancreate{'emaildomain'}{$type}) ne 'HASH') ||  
                                                 ($cancreate{'emaildomain'}{$type}{'inst'} eq '')) {  
                                                 $output = '<li>'.$othertitle.' -- '.&mt('No restriction on e-mail domain').'</li>';  
                                             } else {  
                                                 $output = '<li>'.$othertitle.' -- '.&mt("User's e-mail address needs to end: [_1]",  
                                                                                         $cancreate{'emaildomain'}{$type}{'inst'}).'</li>';  
                                             }  
                                         } else {  
                                             if ((ref($cancreate{'emaildomain'}{$type}) ne 'HASH') ||  
                                                 ($cancreate{'emaildomain'}{$type}{'inst'} eq '')) {  
                                                 $output = '<li>'.$usertypes{$type}.' -- '.&mt('No restriction on e-mail domain').'</li>';  
                                             } else {  
                                                 $output = '<li>'.$usertypes{$type}.' -- '.&mt("User's e-mail address needs to end: [_1]",  
                                                                                               $cancreate{'emaildomain'}{$type}{'inst'}).'</li>';  
                                             }  
                                         }  
                                     } elsif ($cancreate{'emailoptions'}{$type} eq 'noninst') {  
                                         if ($type eq 'default') {  
                                             if ((ref($cancreate{'emaildomain'}{$type}) ne 'HASH') ||  
                                                 ($cancreate{'emaildomain'}{$type}{'noninst'} eq '')) {  
                                                 $output = '<li>'.$othertitle.' -- '.&mt('No restriction on e-mail domain').'</li>';  
                                             } else {  
                                                 $output = '<li>'.$othertitle.' -- '.&mt("User's e-mail address must not end: [_1]",  
                                                                                         $cancreate{'emaildomain'}{$type}{'noninst'}).'</li>';  
                                             }  
                                         } else {  
                                             if ((ref($cancreate{'emaildomain'}{$type}) ne 'HASH') ||  
                                                 ($cancreate{'emaildomain'}{$type}{'noninst'} eq '')) {  
                                                 $output = '<li>'.$usertypes{$type}.' -- '.&mt('No restriction on e-mail domain').'</li>';  
                                             } else {  
                                                 $output = '<li>'.$usertypes{$type}.' -- '.&mt("User's e-mail address must not end: [_1]",  
                                                                                                 $cancreate{'emaildomain'}{$type}{'noninst'}).'</li>';  
                                             }  
                                         }  
                                     }  
                                 }  
                             }  
                         }  
                         if ($output ne '') {  
                             $chgtext .= &mt('For self-created accounts verified by e-mail address:').  
                                         '<ul>'.$output.'</ul>';  
                         }  
                     } elsif ($type eq 'captcha') {  
                         if ($savecaptcha{$type} eq 'notused') {  
                             $chgtext .= &mt('No CAPTCHA validation in use for self-creation screen.');  
                         } else {  
                             my %captchas = &captcha_phrases();  
                             if ($captchas{$savecaptcha{$type}}) {  
                                 $chgtext .= &mt("Validation for self-creation screen set to $captchas{$savecaptcha{$type}}.");  
                             } else {  
                                 $chgtext .= &mt('Validation for self-creation screen set to unknown type.');  
                             }  
                         }  
                     } elsif ($type eq 'recaptchakeys') {  
                         my ($privkey,$pubkey);  
                         if (ref($savecaptcha{$type}) eq 'HASH') {  
                             $pubkey = $savecaptcha{$type}{'public'};  
                             $privkey = $savecaptcha{$type}{'private'};  
                         }  
                         $chgtext .= &mt('ReCAPTCHA keys changes').'<ul>';  
                         if (!$pubkey) {  
                             $chgtext .= '<li>'.&mt('Public key deleted').'</li>';  
                         } else {  
                             $chgtext .= '<li>'.&mt('Public key set to [_1]',$pubkey).'</li>';  
                         }  
                         if (!$privkey) {  
                             $chgtext .= '<li>'.&mt('Private key deleted').'</li>';  
                         } else {  
                             $chgtext .= '<li>'.&mt('Private key set to [_1]',$pubkey).'</li>';  
                         }  
                         $chgtext .= '</ul>';  
                     } elsif ($type eq 'recaptchaversion') {  
                         if ($savecaptcha{'captcha'} eq 'recaptcha') {  
                             $chgtext .= &mt('ReCAPTCHA set to version [_1]',$savecaptcha{$type});  
                         }  
                     } elsif ($type eq 'emailusername') {  
                         if (ref($cancreate{'emailusername'}) eq 'HASH') {  
                             if (@statuses) {  
                                 foreach my $type (@statuses) {  
                                     if (ref($cancreate{'emailusername'}{$type}) eq 'HASH') {  
                                         if (keys(%{$cancreate{'emailusername'}{$type}}) > 0) {  
                                             $chgtext .= &mt('When self-creating account with e-mail verification, the following information will be provided by [_1]:',"'$usertypes{$type}'").  
                                                     '<ul>';  
                                             foreach my $field (@{$infofields}) {  
                                                 if ($cancreate{'emailusername'}{$type}{$field}) {  
                                                     $chgtext .= '<li>'.$infotitles->{$field}.'</li>';  
                                                 }  
                                             }  
                                             $chgtext .= '</ul>';  
                                         } else {  
                                             $chgtext .= &mt('When self creating account with e-mail verification, no information besides e-mail address will be provided by [_1].',"'$usertypes{$type}'").'<br />';  
                                         }  
                                     } else {  
                                         $chgtext .= &mt('When self creating account with e-mail verification, no information besides e-mail address will be provided by [_1].',"'$usertypes{$type}'").'<br />';  
                                     }  
                                 }  
                             }  
                         }  
                     } elsif ($type eq 'notify') {  
                         my $numapprove = 0;  
                         if (ref($changes{'cancreate'}) eq 'ARRAY') {  
                             if ((grep(/^notify$/,@{$changes{'cancreate'}})) && (ref($cancreate{'notify'}) eq 'HASH')) {  
                                 if ($cancreate{'notify'}{'approval'}) {  
                                     $chgtext .= &mt('Notification of username requests requiring approval will be sent to: ').$cancreate{'notify'}{'approval'};  
                                     $numapprove ++;  
                                 }  
                             }  
                         }  
                         unless ($numapprove) {  
                             $chgtext .= &mt('No Domain Coordinators will receive notification of username requests requiring approval.');  
                         }                          }
                     }                      }
                     if ($chgtext) {                      $resulttext .= '<li>'.$chgtext.'</li>';
                         $resulttext .= '<li>'.$chgtext.'</li>';                  }
               }
               if (ref($changes{'username_rule'}) eq 'ARRAY') {
                   my ($rules,$ruleorder) = 
                       &Apache::lonnet::inst_userrules($dom,'username');
                   my $chgtext = '<ul>';
                   foreach my $type (@username_rule) {
                       if (ref($rules->{$type}) eq 'HASH') {
                           $chgtext .= '<li>'.$rules->{$type}{'name'}.'</li>';
                     }                      }
                 }                  }
                   $chgtext .= '</ul>';
                   if (@username_rule > 0) {
                       $resulttext .= '<li>'.&mt('Usernames with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';     
                   } else {
                       $resulttext .= '<li>'.&mt('There are now no username formats restricted to verified users in the institutional directory.').'</li>'; 
                   }
             }              }
             if ((ref($changes{'email_rule'}) eq 'ARRAY') && (@{$changes{'email_rule'}} > 0)) {              if (ref($changes{'id_rule'}) eq 'ARRAY') {
                 my ($emailrules,$emailruleorder) =                  my ($idrules,$idruleorder) = 
                     &Apache::lonnet::inst_userrules($dom,'email');                      &Apache::lonnet::inst_userrules($dom,'id');
                 foreach my $type (@{$changes{'email_rule'}}) {                  my $chgtext = '<ul>';
                     if (ref($email_rule{$type}) eq 'ARRAY') {                  foreach my $type (@id_rule) {
                         my $chgtext = '<ul>';                      if (ref($idrules->{$type}) eq 'HASH') {
                         foreach my $rule (@{$email_rule{$type}}) {                          $chgtext .= '<li>'.$idrules->{$type}{'name'}.'</li>';
                             if (ref($emailrules->{$rule}) eq 'HASH') {  
                                 $chgtext .= '<li>'.$emailrules->{$rule}{'name'}.'</li>';  
                             }  
                         }  
                         $chgtext .= '</ul>';  
                         my $typename;  
                         if (@types) {  
                             if ($type eq 'default') {  
                                 $typename = $othertitle;  
                             } else {  
                                 $typename = $usertypes{$type};  
                             }  
                             $chgtext .= &mt('(Affiliation: [_1])',$typename);  
                         }  
                         if (@{$email_rule{$type}} > 0) {  
                             $resulttext .= '<li>'.  
                                            &mt('Accounts may not be created by users verified by e-mail, for e-mail addresses of the following types: ',  
                                                $usertypes{$type}).  
                                            $chgtext.  
                                            '</li>';  
                         } else {  
                             $resulttext .= '<li>'.  
                                            &mt('There are now no restrictions on e-mail addresses which may be used for verification when a user requests an account.').  
                                            '</li>'.  
                                            &mt('(Affiliation: [_1])',$typename);  
                         }  
                     }                      }
                 }                  }
                   $chgtext .= '</ul>';
                   if (@id_rule > 0) {
                       $resulttext .= '<li>'.&mt('IDs with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';
                   } else {
                       $resulttext .= '<li>'.&mt('There are now no ID formats restricted to verified users in the institutional directory.').'</li>';
                   }
             }              }
             if (ref($changes{'inststatus'}) eq 'ARRAY') {              if (ref($changes{'email_rule'}) eq 'ARRAY') {
                 if (ref($save_inststatus{'inststatusguest'}) eq 'ARRAY') {                  my ($emailrules,$emailruleorder) =
                     if (@{$save_inststatus{'inststatusguest'}} > 0) {                      &Apache::lonnet::inst_userrules($dom,'email');
                         my $chgtext = '<ul>';                  my $chgtext = '<ul>';
                         foreach my $type (@{$save_inststatus{'inststatusguest'}}) {                  foreach my $type (@email_rule) {
                             $chgtext .= '<li>'.$usertypes{$type}.'</li>';                      if (ref($emailrules->{$type}) eq 'HASH') {
                         }                          $chgtext .= '<li>'.$emailrules->{$type}{'name'}.'</li>';
                         $chgtext .= '</ul>';  
                         $resulttext .= '<li>'.  
                                        &mt('A user will self-report one of the following affiliations when requesting an account verified by e-mail: ').  
                                           $chgtext.  
                                        '</li>';  
                     } else {  
                         $resulttext .= '<li>'.  
                                        &mt('No affiliations available for self-reporting when requesting an account verified by e-mail.').  
                                        '</li>';  
                     }                      }
                 }                  }
                   $chgtext .= '</ul>';
                   if (@email_rule > 0) {
                       $resulttext .= '<li>'.&mt('Accounts may not be created by users self-enrolling with e-mail addresses of the following types: ').$chgtext.'</li>';
                   } else {
                       $resulttext .= '<li>'.&mt('There are now no restrictions on e-mail addresses which may be used as a username when self-enrolling.').'</li>';
                   }
             }              }
             if (ref($changes{'selfcreate'}) eq 'ARRAY') {  
                 $resulttext .= '<li>'.&mt('When self-creating institutional account:').'<ul>';              my %authname = &authtype_names();
                 my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();              my %context_title = &context_names();
                 foreach my $type (@{$changes{'selfcreate'}}) {              if (ref($changes{'authtypes'}) eq 'ARRAY') {
                     my $typename = $type;                  my $chgtext = '<ul>';
                     if (keys(%usertypes) > 0) {                  foreach my $type (@{$changes{'authtypes'}}) {
                         if ($usertypes{$type} ne '') {                      my @allowed;
                             $typename = $usertypes{$type};                      $chgtext .= '<li><span class="LC_cusr_emph">'.$context_title{$type}.'</span> - '.&mt('assignable authentication types: ');
                         }                      foreach my $auth (@authtypes) {
                     }                          if ($authhash{$type}{$auth}) {
                     my @modifiable;                              push(@allowed,$authname{$auth});
                     $resulttext .= '<li>'.  
                                     &mt('Self-creation of account by users with status: [_1]',  
                                         '<span class="LC_cusr_emph">'.$typename.'</span>').  
                                     ' - '.&mt('modifiable fields (if institutional data blank): ');  
                     foreach my $field (@fields) {  
                         if ($save_usermodify{'selfcreate'}{$type}{$field}) {  
                             push(@modifiable,'<b>'.$fieldtitles{$field}.'</b>');  
                         }                          }
                     }                      }
                     if (@modifiable > 0) {                      if (@allowed > 0) {
                         $resulttext .= join(', ',@modifiable);                          $chgtext .= join(', ',@allowed).'</li>';
                     } else {                      } else {
                         $resulttext .= &mt('none');                          $chgtext .= &mt('none').'</li>';
                     }                      }
                     $resulttext .= '</li>';  
                 }                  }
                 $resulttext .= '</ul></li>';                  $chgtext .= '</ul>';
                   $resulttext .= '<li>'.&mt('Authentication types available for assignment to new users').'<br />'.$chgtext;
                   $resulttext .= '</li>';
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
             my $cachetime = 24*60*60;  
             $domdefaults{'inststatusguest'} = $save_inststatus{'inststatusguest'};  
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);  
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'domdefaults'} = 1;  
             }  
         } else {          } else {
             $resulttext = &mt('No changes made to self-creation settings');              $resulttext = &mt('No changes made to user creation settings');
         }          }
     } else {      } else {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
Line 12520  sub modify_selfcreation { Line 6503  sub modify_selfcreation {
     return $resulttext;      return $resulttext;
 }  }
   
 sub process_captcha {  
     my ($container,$changes,$newsettings,$currsettings) = @_;  
     return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH'));  
     $newsettings->{'captcha'} = $env{'form.'.$container.'_captcha'};  
     unless ($newsettings->{'captcha'} eq 'recaptcha' || $newsettings->{'captcha'} eq 'notused') {  
         $newsettings->{'captcha'} = 'original';  
     }  
     my %current;  
     if (ref($currsettings) eq 'HASH') {  
         %current = %{$currsettings};  
     }  
     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'];  
             }  
         } elsif ($container eq 'passwords') {  
             $changes->{'reset'} = 1;  
         } else {  
             $changes->{'captcha'} = 1;  
         }  
     }  
     my ($newpub,$newpriv,$currpub,$currpriv,$newversion,$currversion);  
     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,  
                                           };  
         $newversion = $env{'form.'.$container.'_recaptchaversion'};  
         $newversion =~ s/\D//g;  
         if ($newversion ne '2') {  
             $newversion = 1;  
         }  
         $newsettings->{'recaptchaversion'} = $newversion;  
     }  
     if (ref($current{'recaptchakeys'}) eq 'HASH') {  
         $currpub = $current{'recaptchakeys'}{'public'};  
         $currpriv = $current{'recaptchakeys'}{'private'};  
         unless ($newsettings->{'captcha'} eq 'recaptcha') {  
             $newsettings->{'recaptchakeys'} = {  
                                                  public  => '',  
                                                  private => '',  
                                               }  
         }  
     }  
     if ($current{'captcha'} eq 'recaptcha') {  
         $currversion = $current{'recaptchaversion'};  
         if ($currversion ne '2') {  
             $currversion = 1;  
         }  
     }  
     if ($currversion ne $newversion) {  
         if ($container eq 'cancreate') {  
             if (ref($changes->{'cancreate'}) eq 'ARRAY') {  
                 push(@{$changes->{'cancreate'}},'recaptchaversion');  
             } elsif (!defined($changes->{'cancreate'})) {  
                 $changes->{'cancreate'} = ['recaptchaversion'];  
             }  
         } elsif ($container eq 'passwords') {  
             $changes->{'reset'} = 1;  
         } else {  
             $changes->{'recaptchaversion'} = 1;  
         }  
     }  
     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'];  
             }  
         } elsif ($container eq 'passwords') {  
             $changes->{'reset'} = 1;  
         } else {  
             $changes->{'recaptchakeys'} = 1;  
         }  
     }  
     return;  
 }  
   
 sub modify_usermodification {  sub modify_usermodification {
     my ($dom,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%curr_usermodification,%changes,%modifyhash);      my ($resulttext,%curr_usermodification,%changes);
     if (ref($domconfig{'usermodification'}) eq 'HASH') {      if (ref($domconfig{'usermodification'}) eq 'HASH') {
         foreach my $key (keys(%{$domconfig{'usermodification'}})) {          foreach my $key (keys(%{$domconfig{'usermodification'}})) {
             if ($key eq 'selfcreate') {              $curr_usermodification{$key} = $domconfig{'usermodification'}{$key};
                 $modifyhash{$key} = $domconfig{'usermodification'}{$key};  
             } else {    
                 $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 12629  sub modify_usermodification { Line 6523  sub modify_usermodification {
                   author => ['ca','aa'],                    author => ['ca','aa'],
                   course => ['st','ep','ta','in','cr'],                    course => ['st','ep','ta','in','cr'],
                 );                  );
       my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
       if (ref($types) eq 'ARRAY') {
           push(@{$types},'default');
           $usertypes->{'default'} = $othertitle;
       }
       $roles{'selfcreate'} = $types;  
     my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();      my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
       my %modifyhash;
     foreach my $context (@contexts) {      foreach my $context (@contexts) {
         foreach my $role (@{$roles{$context}}) {          foreach my $role (@{$roles{$context}}) {
             my @modifiable =  &Apache::loncommon::get_env_multiple('form.canmodify_'.$role);              my @modifiable =  &Apache::loncommon::get_env_multiple('form.canmodify_'.$role);
Line 12675  sub modify_usermodification { Line 6576  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 12710  sub modify_usermodification { Line 6624  sub modify_usermodification {
 }  }
   
 sub modify_defaults {  sub modify_defaults {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,$r) = @_;
     my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors);      my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors);
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
     my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def',      my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def','portal_def');
                  '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 12764  sub modify_defaults { Line 6677  sub modify_defaults {
         }          }
         $domdefaults{$item} = $newvalues{$item};          $domdefaults{$item} = $newvalues{$item};
     }      }
     my %staticdefaults = (  
                            'intauth_cost'   => 10,  
                            'intauth_check'  => 0,  
                            'intauth_switch' => 0,  
                          );  
     foreach my $item ('intauth_cost','intauth_check','intauth_switch') {  
         if (exists($domdefaults{$item})) {  
             $newvalues{$item} = $domdefaults{$item};  
         } else {  
             $newvalues{$item} = $staticdefaults{$item};  
         }  
     }  
     my %defaults_hash = (      my %defaults_hash = (
                          defaults => \%newvalues,                           defaults => \%newvalues,
                         );                          );
     my $title = &defaults_titles();      my $title = &defaults_titles();
   
     my $currinststatus;  
     if (ref($domconfig{'inststatus'}) eq 'HASH') {  
         $currinststatus = $domconfig{'inststatus'};  
     } else {  
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
         $currinststatus = {  
                              inststatustypes => $usertypes,  
                              inststatusorder => $types,  
                              inststatusguest => [],  
                           };  
     }  
     my @todelete = &Apache::loncommon::get_env_multiple('form.inststatus_delete');  
     my @allpos;  
     my %alltypes;  
     my @inststatusguest;  
     if (ref($currinststatus) eq 'HASH') {  
         if (ref($currinststatus->{'inststatusguest'}) eq 'ARRAY') {  
             foreach my $type (@{$currinststatus->{'inststatusguest'}}) {  
                 unless (grep(/^\Q$type\E$/,@todelete)) {  
                     push(@inststatusguest,$type);  
                 }  
             }  
         }  
     }  
     my ($currtitles,$currorder);  
     if (ref($currinststatus) eq 'HASH') {  
         if (ref($currinststatus->{'inststatusorder'}) eq 'ARRAY') {  
             foreach my $type (@{$currinststatus->{'inststatusorder'}}) {  
                 if (ref($currinststatus->{inststatustypes}) eq 'HASH') {  
                     if ($currinststatus->{inststatustypes}->{$type} ne '') {  
                         $currtitles .= $currinststatus->{inststatustypes}->{$type}.',';  
                     }  
                 }  
                 unless (grep(/^\Q$type\E$/,@todelete)) {   
                     my $position = $env{'form.inststatus_pos_'.$type};  
                     $position =~ s/\D+//g;  
                     $allpos[$position] = $type;  
                     $alltypes{$type} = $env{'form.inststatus_title_'.$type};  
                     $alltypes{$type} =~ s/`//g;  
                 }  
             }  
             $currorder = join(',',@{$currinststatus->{'inststatusorder'}});  
             $currtitles =~ s/,$//;  
         }  
     }  
     if ($env{'form.addinststatus'}) {  
         my $newtype = $env{'form.addinststatus'};  
         $newtype =~ s/\W//g;  
         unless (exists($alltypes{$newtype})) {  
             $alltypes{$newtype} = $env{'form.addinststatus_title'};  
             $alltypes{$newtype} =~ s/`//g;   
             my $position = $env{'form.addinststatus_pos'};  
             $position =~ s/\D+//g;  
             if ($position ne '') {  
                 $allpos[$position] = $newtype;  
             }  
         }  
     }  
     my @orderedstatus;  
     foreach my $type (@allpos) {  
         unless (($type eq '') || (grep(/^\Q$type\E$/,@orderedstatus))) {  
             push(@orderedstatus,$type);  
         }  
     }  
     foreach my $type (keys(%alltypes)) {  
         unless (grep(/^\Q$type\E$/,@orderedstatus)) {  
             delete($alltypes{$type});  
         }  
     }  
     $defaults_hash{'inststatus'} = {  
                                      inststatustypes => \%alltypes,  
                                      inststatusorder => \@orderedstatus,  
                                      inststatusguest => \@inststatusguest,  
                                    };  
     if (ref($defaults_hash{'inststatus'}) eq 'HASH') {  
         foreach my $item ('inststatustypes','inststatusorder','inststatusguest') {  
             $domdefaults{$item} = $defaults_hash{'inststatus'}{$item};  
         }  
     }  
     if ($currorder ne join(',',@orderedstatus)) {  
         $changes{'inststatus'}{'inststatusorder'} = 1;  
     }  
     my $newtitles;  
     foreach my $item (@orderedstatus) {  
         $newtitles .= $alltypes{$item}.',';  
     }  
     $newtitles =~ s/,$//;  
     if ($currtitles ne $newtitles) {  
         $changes{'inststatus'}{'inststatustypes'} = 1;  
     }  
     my $putresult = &Apache::lonnet::put_dom('configuration',\%defaults_hash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%defaults_hash,
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             my $version = &Apache::lonnet::get_server_loncaparev($dom);              my $version = $r->dir_config('lonVersion');
             my $mailmsgtext = "Changes made to domain settings in a LON-CAPA installation - domain: $dom (running version: $version) - dns_domain.tab needs to be updated with the following changes, to support legacy 2.4, 2.5 and 2.6 versions of LON-CAPA.\n\n";              my $mailmsgtext = "Changes made to domain settings in a LON-CAPA installation - domain: $dom (running version: $version) - dns_domain.tab needs to be updated with the following changes, to support legacy 2.4, 2.5 and 2.6 versions of LON-CAPA.\n\n";
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
                 if ($item eq 'inststatus') {                  my $value = $env{'form.'.$item};
                     if (ref($changes{'inststatus'}) eq 'HASH') {                  if ($value eq '') {
                         if (@orderedstatus) {                      $value = &mt('none');
                             $resulttext .= '<li>'.&mt('Institutional user status types set to:').' ';                  } elsif ($item eq 'auth_def') {
                             foreach my $type (@orderedstatus) {                       my %authnames = &authtype_names();
                                 $resulttext .= $alltypes{$type}.', ';                      my %shortauth = (
                             }                               internal => 'int',
                             $resulttext =~ s/, $//;                               krb4 => 'krb4',
                             $resulttext .= '</li>';                               krb5 => 'krb5',
                         } else {                               localauth  => 'loc',
                             $resulttext .= '<li>'.&mt('Institutional user status types deleted').'</li>';                      );
                         }                      $value = $authnames{$shortauth{$value}};
                     }  
                 } else {  
                     my $value = $env{'form.'.$item};  
                     if ($value eq '') {  
                         $value = &mt('none');  
                     } elsif ($item eq 'auth_def') {  
                         my %authnames = &authtype_names();  
                         my %shortauth = (  
                                           internal   => 'int',  
                                           krb4       => 'krb4',  
                                           krb5       => 'krb5',  
                                           localauth  => 'loc',  
                         );  
                         $value = $authnames{$shortauth{$value}};  
                     }  
                     $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$item},$value).'</li>';  
                     $mailmsgtext .= "$title->{$item} set to $value\n";    
                 }                  }
                   $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$item},$value).'</li>';
                   $mailmsgtext .= "$title->{$item} set to $value\n";  
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
             $mailmsgtext .= "\n";              $mailmsgtext .= "\n";
             my $cachetime = 24*60*60;              my $cachetime = 24*60*60;
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);              &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'domdefaults'} = 1;  
             }  
             if ($changes{'auth_def'} || $changes{'auth_arg_def'} || $changes{'lang_def'} || $changes{'datelocale_def'}) {              if ($changes{'auth_def'} || $changes{'auth_arg_def'} || $changes{'lang_def'} || $changes{'datelocale_def'}) {
                 my $notify = 1;                  my $sysmail = $r->dir_config('lonSysEMail');
                 if (ref($domconfig{'contacts'}) eq 'HASH') {                  &Apache::lonmsg::sendemail($sysmail,"LON-CAPA Domain Settings Change - $dom",$mailmsgtext);
                     if ($domconfig{'contacts'}{'reportupdates'} == 0) {  
                         $notify = 0;  
                     }  
                 }  
                 if ($notify) {  
                     &Apache::lonmsg::sendemail('installrecord@loncapa.org',  
                                                "LON-CAPA Domain Settings Change - $dom",  
                                                $mailmsgtext);  
                 }  
             }              }
         } else {          } else {
             $resulttext = &mt('No changes made to default authentication/language/timezone settings');              $resulttext = &mt('No changes made to default authentication/language/timezone settings');
Line 12948  sub modify_defaults { Line 6731  sub modify_defaults {
 }  }
   
 sub modify_scantron {  sub modify_scantron {
     my ($r,$dom,$confname,$lastactref,%domconfig) = @_;      my ($r,$dom,$confname,%domconfig) = @_;
     my ($resulttext,%confhash,%changes,$errors);      my ($resulttext,%confhash,%changes,$errors);
     my $custom = 'custom.tab';      my $custom = 'custom.tab';
     my $default = 'default.tab';      my $default = 'default.tab';
     my $servadm = $r->dir_config('lonAdmEMail');      my $servadm = $r->dir_config('lonAdmEMail');
     my ($configuserok,$author_ok,$switchserver) =      my ($configuserok,$author_ok,$switchserver) = 
         &config_check($dom,$confname,$servadm);          &config_check($dom,$confname,$servadm);
     if ($env{'form.scantronformat.filename'} ne '') {      if ($env{'form.scantronformat.filename'} ne '') {
         my $error;          my $error;
Line 12988  sub modify_scantron { Line 6771  sub modify_scantron {
             if ($env{'form.scantronformat_del'}) {              if ($env{'form.scantronformat_del'}) {
                 $confhash{'scantron'}{'scantronformat'} = '';                  $confhash{'scantron'}{'scantronformat'} = '';
                 $changes{'scantronformat'} = 1;                  $changes{'scantronformat'} = 1;
             } else {  
                 $confhash{'scantron'}{'scantronformat'} = $domconfig{'scantron'}{'scantronformat'};  
             }  
         }  
     }  
     my @options = ('hdr','pad','rem');  
     my @fields = &scantroncsv_fields();  
     my %titles = &scantronconfig_titles();  
     my @formats = &Apache::loncommon::get_env_multiple('form.scantronconfig');  
     my ($newdat,$currdat,%newcol,%currcol);  
     if (grep(/^dat$/,@formats)) {  
         $confhash{'scantron'}{config}{dat} = 1;  
         $newdat = 1;  
     } else {  
         $newdat = 0;  
     }  
     if (grep(/^csv$/,@formats)) {  
         my %bynum;  
         foreach my $field (@fields) {  
             if ($env{'form.scantronconfig_csv_'.$field} =~ /^(\d+)$/) {  
                 my $posscol = $1;  
                 if (($posscol < 20) && (!$bynum{$posscol})) {  
                     $confhash{'scantron'}{config}{csv}{fields}{$field} = $posscol;  
                     $bynum{$posscol} = $field;  
                     $newcol{$field} = $posscol;  
                 }  
             }  
         }  
         if (keys(%newcol)) {  
             foreach my $option (@options) {  
                 if ($env{'form.scantroncsv_'.$option}) {  
                     $confhash{'scantron'}{config}{csv}{options}{$option} = 1;  
                 }  
             }  
         }  
     }  
     $currdat = 1;  
     if (ref($domconfig{'scantron'}) eq 'HASH') {  
         if (ref($domconfig{'scantron'}{'config'}) eq 'HASH') {  
             unless (exists($domconfig{'scantron'}{'config'}{'dat'})) {  
                 $currdat = 0;  
             }  
             if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {  
                 if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {  
                     %currcol = %{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}};  
                 }  
             }  
         }  
     }  
     if ($currdat != $newdat) {  
         $changes{'config'} = 1;  
     } else {  
         foreach my $field (@fields) {  
             if ($currcol{$field} ne '') {  
                 if ($currcol{$field} ne $newcol{$field}) {  
                     $changes{'config'} = 1;  
                     last;  
                 }  
             } elsif ($newcol{$field} ne '') {  
                 $changes{'config'} = 1;  
                 last;  
             }              }
         }          }
     }      }
Line 13059  sub modify_scantron { Line 6781  sub modify_scantron {
             if (keys(%changes) > 0) {              if (keys(%changes) > 0) {
                 if (ref($confhash{'scantron'}) eq 'HASH') {                  if (ref($confhash{'scantron'}) eq 'HASH') {
                     $resulttext = &mt('Changes made:').'<ul>';                      $resulttext = &mt('Changes made:').'<ul>';
                     if ($changes{'scantronformat'}) {                      if ($confhash{'scantron'}{'scantronformat'} eq '') {
                         if ($confhash{'scantron'}{'scantronformat'} eq '') {                          $resulttext .= '<li>'.&mt('[_1] bubblesheet 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 bubblesheet 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>';  
                         }  
                     }  
                     if ($changes{'config'}) {  
                         if (ref($confhash{'scantron'}{'config'}) eq 'HASH') {  
                             if ($confhash{'scantron'}{'config'}{'dat'}) {  
                                 $resulttext .= '<li>'.&mt('Bubblesheet data upload formats includes .dat format').'</li>';  
                             }  
                             if (ref($confhash{'scantron'}{'config'}{'csv'}) eq 'HASH') {  
                                 if (ref($confhash{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {  
                                     if (keys(%{$confhash{'scantron'}{'config'}{'csv'}{'fields'}})) {  
                                         $resulttext .= '<li>'.&mt('Bubblesheet data upload formats includes .csv format, with following fields/column numbers supported:').'<ul>';  
                                         foreach my $field (@fields) {  
                                             if ($confhash{'scantron'}{'config'}{'csv'}{'fields'}{$field} ne '') {  
                                                 my $showcol = $confhash{'scantron'}{'config'}{'csv'}{'fields'}{$field} + 1;  
                                                 $resulttext .= '<li>'.$titles{$field}.': '.$showcol.'</li>';  
                                             }  
                                         }  
                                         $resulttext .= '</ul></li>';  
                                         if (ref($confhash{'scantron'}{'config'}{'csv'}{'options'}) eq 'HASH') {  
                                             if (keys(%{$confhash{'scantron'}{'config'}{'csv'}{'options'}})) {  
                                                 $resulttext .= '<li>'.&mt('Bubblesheet data upload formats includes .csv format, with following options:').'<ul>';  
                                                 foreach my $option (@options) {  
                                                     if ($confhash{'scantron'}{'config'}{'csv'}{'options'}{$option} ne '') {  
                                                         $resulttext .= '<li>'.$titles{$option}.'</li>';  
                                                     }  
                                                 }  
                                                 $resulttext .= '</ul></li>';  
                                             }  
                                         }  
                                     }  
                                 }  
                             }  
                         } else {  
                             $resulttext .= '<li>'.&mt('No bubblesheet data upload formats set -- will default to assuming .dat format').'</li>';  
                         }  
                     }                      }
                     $resulttext .= '</ul>';                      $resulttext .= '</ul>';
                 } else {                  } else {
                     $resulttext = &mt('Changes made to bubblesheet format file.');                      $resulttext = &mt('Changes made to bubblesheet format file.');
                 }                  }
                   $resulttext .= '</ul>';
                 &Apache::loncommon::devalidate_domconfig_cache($dom);                  &Apache::loncommon::devalidate_domconfig_cache($dom);
                 if (ref($lastactref) eq 'HASH') {  
                     $lastactref->{'domainconfig'} = 1;  
                 }  
             } else {              } else {
                 $resulttext = &mt('No changes made to bubblesheet format settings');                  $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 bubblesheet format settings');          $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 13126  sub modify_scantron { Line 6810  sub modify_scantron {
 }  }
   
 sub modify_coursecategories {  sub modify_coursecategories {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%deletions,%reorderings,%needreordering,%adds,%changes,$errors,      my ($resulttext,%deletions,%reorderings,%needreordering,%adds,%changes,$errors,
         $cathash);          $cathash);
     my @deletecategory = &Apache::loncommon::get_env_multiple('form.deletecategory');      my @deletecategory = &Apache::loncommon::get_env_multiple('form.deletecategory');
     my @catitems = ('unauth','auth');  
     my @cattypes = ('std','domonly','codesrch','none');  
     if (ref($domconfig{'coursecategories'}) eq 'HASH') {      if (ref($domconfig{'coursecategories'}) eq 'HASH') {
         $cathash = $domconfig{'coursecategories'}{'cats'};          $cathash = $domconfig{'coursecategories'}{'cats'};
         if ($domconfig{'coursecategories'}{'togglecats'} ne $env{'form.togglecats'}) {          if ($domconfig{'coursecategories'}{'togglecats'} ne $env{'form.togglecats'}) {
Line 13150  sub modify_coursecategories { Line 6832  sub modify_coursecategories {
             $changes{'categorizecomm'} = 1;              $changes{'categorizecomm'} = 1;
             $domconfig{'coursecategories'}{'categorizecomm'} = $env{'form.categorizecomm'};              $domconfig{'coursecategories'}{'categorizecomm'} = $env{'form.categorizecomm'};
         }          }
         foreach my $item (@catitems) {  
             if (grep(/^\Q$env{'form.coursecat_'.$item}\E$/,@cattypes)) {  
                 if ($domconfig{'coursecategories'}{$item} ne $env{'form.coursecat_'.$item}) {  
                     $changes{$item} = 1;  
                     $domconfig{'coursecategories'}{$item} = $env{'form.coursecat_'.$item};  
                 }  
             }  
         }  
     } else {      } else {
         $changes{'togglecats'} = 1;          $changes{'togglecats'} = 1;
         $changes{'categorize'} = 1;          $changes{'categorize'} = 1;
Line 13169  sub modify_coursecategories { Line 6843  sub modify_coursecategories {
                                              togglecatscomm => $env{'form.togglecatscomm'},                                               togglecatscomm => $env{'form.togglecatscomm'},
                                              categorizecomm => $env{'form.categorizecomm'},                                               categorizecomm => $env{'form.categorizecomm'},
                                          };                                           };
         foreach my $item (@catitems) {  
             if ($env{'form.coursecat_'.$item} ne 'std') {  
                 $changes{$item} = 1;  
             }  
             if (grep(/^\Q$env{'form.coursecat_'.$item}\E$/,@cattypes)) {  
                 $domconfig{'coursecategories'}{$item} = $env{'form.coursecat_'.$item};  
             }  
         }  
     }      }
     if (ref($cathash) eq 'HASH') {      if (ref($cathash) eq 'HASH') {
         if (($domconfig{'coursecategories'}{'cats'}{'instcode::0'} ne '')  && ($env{'form.instcode'} == 0)) {          if (($domconfig{'coursecategories'}{'cats'}{'instcode::0'} ne '')  && ($env{'form.instcode'} == 0)) {
Line 13299  sub modify_coursecategories { Line 6965  sub modify_coursecategories {
                          dom  => 'set in Domain ("Modify Course/Community")',                           dom  => 'set in Domain ("Modify Course/Community")',
                          crs  => 'set in Course ("Course Configuration")',                           crs  => 'set in Course ("Course Configuration")',
                          comm => 'set in Community ("Community Configuration")',                           comm => 'set in Community ("Community Configuration")',
                          none     => 'No catalog',  
                          std      => 'Standard catalog',  
                          domonly  => 'Domain-only catalog',  
                          codesrch => 'Code search form',  
                         );                          );
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if ($changes{'togglecats'}) {              if ($changes{'togglecats'}) {
Line 13317  sub modify_coursecategories { Line 6979  sub modify_coursecategories {
             if ($changes{'categorizecomm'}) {              if ($changes{'categorizecomm'}) {
                 $resulttext .= '<li>'.&mt("$title{'categorizecomm'} $level{$env{'form.categorizecomm'}}").'</li>';                  $resulttext .= '<li>'.&mt("$title{'categorizecomm'} $level{$env{'form.categorizecomm'}}").'</li>';
             }              }
             if ($changes{'unauth'}) {  
                 $resulttext .= '<li>'.&mt('Catalog type for unauthenticated users set to "'.$level{$env{'form.coursecat_unauth'}}.'"').'</li>';  
             }  
             if ($changes{'auth'}) {  
                 $resulttext .= '<li>'.&mt('Catalog type for authenticated users set to "'.$level{$env{'form.coursecat_auth'}}.'"').'</li>';  
             }  
             if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {              if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {
                 my $cathash;                  my $cathash;
                 if (ref($domconfig{'coursecategories'}) eq 'HASH') {                  if (ref($domconfig{'coursecategories'}) eq 'HASH') {
Line 13365  sub modify_coursecategories { Line 7021  sub modify_coursecategories {
                     }                      }
                     $resulttext .= '</ul></li>';                      $resulttext .= '</ul></li>';
                 }                  }
                 &Apache::lonnet::do_cache_new('cats',$dom,$cathash,3600);  
                 if (ref($lastactref) eq 'HASH') {  
                     $lastactref->{'cats'} = 1;  
                 }  
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
             if ($changes{'unauth'} || $changes{'auth'}) {  
                 my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);  
                 if ($changes{'auth'}) {  
                     $domdefaults{'catauth'} = $domconfig{'coursecategories'}{'auth'};  
                 }  
                 if ($changes{'unauth'}) {  
                     $domdefaults{'catunauth'} = $domconfig{'coursecategories'}{'unauth'};  
                 }  
                 my $cachetime = 24*60*60;  
                 &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);  
                 if (ref($lastactref) eq 'HASH') {  
                     $lastactref->{'domdefaults'} = 1;  
                 }  
             }  
         } else {          } else {
             $resulttext = '<span class="LC_error">'.              $resulttext = '<span class="LC_error">'.
                           &mt('An error occurred: [_1]',$putresult).'</span>';                            &mt('An error occurred: [_1]',$putresult).'</span>';
Line 13520  sub modify_serverstatuses { Line 7158  sub modify_serverstatuses {
 }  }
   
 sub modify_helpsettings {  sub modify_helpsettings {
     my ($r,$dom,$confname,$lastactref,%domconfig) = @_;      my ($r,$dom,$confname,%domconfig) = @_;
     my ($resulttext,$errors,%changes,%helphash);    my ($resulttext,$errors,%changes,%helphash);
     my %defaultchecked = ('submitbugs' => 'on');   
     my @offon = ('off','on');    my $customhelpfile  = $env{'form.loginhelpurl.filename'};
       my $defaulthelpfile = 'defaulthelp.html';
     my $servadm = $r->dir_config('lonAdmEMail');
       my ($configuserok,$author_ok,$switchserver) = 
           &config_check($dom,$confname,$servadm);
    
     my %defaultchecked = ('submitbugs' => 'on');
     my @offon = ('off','on');
       my %title = ( submitbugs     => 'Display link for users to submit a bug', 
        loginhelpurl  => 'Unauthenticated login help page set to custom file');
        
     my @toggles = ('submitbugs');      my @toggles = ('submitbugs');
     my %current = ('submitbugs' => '',  
                    'adhoc'      => {},      $helphash{'helpsettings'} = {};
                   );      
     if (ref($domconfig{'helpsettings'}) eq 'HASH') {      if (ref($domconfig{'helpsettings'}) ne 'HASH') {
         %current = %{$domconfig{'helpsettings'}};          if ($domconfig{'helpsettings'} eq '') {
     }              $domconfig{'helpsettings'} = {};
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);  
     foreach my $item (@toggles) {  
         if ($defaultchecked{$item} eq 'on') {   
             if ($current{$item} eq '') {  
                 if ($env{'form.'.$item} eq '0') {  
                     $changes{$item} = 1;  
                 }  
             } elsif ($current{$item} ne $env{'form.'.$item}) {  
                 $changes{$item} = 1;  
             }  
         } elsif ($defaultchecked{$item} eq 'off') {  
             if ($current{$item} eq '') {  
                 if ($env{'form.'.$item} eq '1') {  
                     $changes{$item} = 1;  
                 }  
             } elsif ($current{$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 $maxnum = $env{'form.helproles_maxnum'};  
     my $confname = $dom.'-domainconfig';  
     my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');  
     my (@allpos,%newsettings,%changedprivs,$newrole);  
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
     my @accesstypes = ('all','dh','da','none','status','inc','exc');  
     my %domhelpdesk = &Apache::lonnet::get_active_domroles($dom,['dh','da']);  
     my %lt = &Apache::lonlocal::texthash(  
                     s      => 'system',  
                     d      => 'domain',  
                     order  => 'Display order',  
                     access => 'Role usage',  
                     all    => 'All with domain helpdesk or helpdesk assistant role',  
                     dh     => 'All with domain helpdesk role',  
                     da     => 'All with domain helpdesk assistant role',  
                     none   => 'None',  
                     status => 'Determined based on institutional status',  
                     inc    => 'Include all, but exclude specific personnel',  
                     exc    => 'Exclude all, but include specific personnel',  
     );  
     for (my $num=0; $num<=$maxnum; $num++) {  
         my ($prefix,$identifier,$rolename,%curr);  
         if ($num == $maxnum) {  
             next unless ($env{'form.newcusthelp'} == $maxnum);  
             $identifier = 'custhelp'.$num;  
             $prefix = 'helproles_'.$num;  
             $rolename = $env{'form.custhelpname'.$num};  
             $rolename=~s/[^A-Za-z0-9]//gs;  
             next if ($rolename eq '');  
             next if (exists($existing{'rolesdef_'.$rolename}));  
             my %newprivs = &Apache::lonuserutils::custom_role_update($rolename,$identifier);  
             my $result = &Apache::lonnet::definerole($rolename,$newprivs{'s'},$newprivs{'d'},  
                                                      $newprivs{'c'},$confname,$dom);  
             if ($result ne 'ok') {  
                 $errors .= '<li><span class="LC_error">'.  
                            &mt('An error occurred storing the new custom role: [_1]',  
                            $result).'</span></li>';  
                 next;  
             } else {  
                 $changedprivs{$rolename} = \%newprivs;  
                 $newrole = $rolename;  
             }  
         } else {  
             $prefix = 'helproles_'.$num;  
             $rolename = $env{'form.'.$prefix};  
             next if ($rolename eq '');  
             next unless (exists($existing{'rolesdef_'.$rolename}));  
             $identifier = 'custhelp'.$num;  
             my %newprivs = &Apache::lonuserutils::custom_role_update($rolename,$identifier);  
             my %currprivs;  
             ($currprivs{'s'},$currprivs{'d'},$currprivs{'c'}) =  
                 split(/\_/,$existing{'rolesdef_'.$rolename});  
             foreach my $level ('c','d','s') {  
                 if ($newprivs{$level} ne $currprivs{$level}) {  
                     my $result = &Apache::lonnet::definerole($rolename,$newprivs{'s'},$newprivs{'d'},  
                                                              $newprivs{'c'},$confname,$dom);  
                     if ($result ne 'ok') {  
                         $errors .= '<li><span class="LC_error">'.  
                                    &mt('An error occurred storing privileges for existing role [_1]: [_2]',  
                                        $rolename,$result).'</span></li>';  
                     } else {  
                         $changedprivs{$rolename} = \%newprivs;  
                     }  
                     last;  
                 }  
             }  
             if (ref($current{'adhoc'}) eq 'HASH') {  
                 if (ref($current{'adhoc'}{$rolename}) eq 'HASH') {  
                     %curr = %{$current{'adhoc'}{$rolename}};  
                 }  
             }  
         }  
         my $newpos = $env{'form.'.$prefix.'_pos'};  
         $newpos =~ s/\D+//g;  
         $allpos[$newpos] = $rolename;  
         my $newdesc = $env{'form.'.$prefix.'_desc'};  
         $helphash{'helpsettings'}{'adhoc'}{$rolename}{'desc'} = $newdesc;  
         if ($curr{'desc'}) {  
             if ($curr{'desc'} ne $newdesc) {  
                 $changes{'customrole'}{$rolename}{'desc'} = 1;  
                 $newsettings{$rolename}{'desc'} = $newdesc;  
             }  
         } elsif ($newdesc ne '') {  
             $changes{'customrole'}{$rolename}{'desc'} = 1;  
             $newsettings{$rolename}{'desc'} = $newdesc;  
         }  
         my $access = $env{'form.'.$prefix.'_access'};  
         if (grep(/^\Q$access\E$/,@accesstypes)) {  
             $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'} = $access;  
             if ($access eq 'status') {  
                 my @statuses = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_status');  
                 if (scalar(@statuses) == 0) {  
                     $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'} = 'none';  
                 } else {  
                     my (@shownstatus,$numtypes);  
                     $helphash{'helpsettings'}{'adhoc'}{$rolename}{$access} = [];  
                     if (ref($types) eq 'ARRAY') {  
                         $numtypes = scalar(@{$types});  
                         foreach my $type (sort(@statuses)) {  
                             if ($type eq 'default') {  
                                 push(@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}},$type);  
                             } elsif (grep(/^\Q$type\E$/,@{$types})) {  
                                 push(@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}},$type);  
                                 push(@shownstatus,$usertypes->{$type});  
                             }  
                         }  
                     }  
                     if (grep(/^default$/,@statuses)) {  
                         push(@shownstatus,$othertitle);  
                     }  
                     if (scalar(@shownstatus) == 1+$numtypes) {  
                         $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'} = 'all';  
                         delete($helphash{'helpsettings'}{'adhoc'}{$rolename}{'status'});  
                     } else {  
                         $newsettings{$rolename}{'status'} = join(' '.&mt('or').' ',@shownstatus);  
                         if (ref($curr{'status'}) eq 'ARRAY') {  
                             my @diffs = &Apache::loncommon::compare_arrays($helphash{'helpsettings'}{'adhoc'}{$rolename}{$access},$curr{$access});  
                             if (@diffs) {  
                                 $changes{'customrole'}{$rolename}{$access} = 1;  
                             }  
                         } elsif (@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}}) {  
                             $changes{'customrole'}{$rolename}{$access} = 1;  
                         }  
                     }  
                 }  
             } elsif (($access eq 'inc') || ($access eq 'exc')) {  
                 my @personnel = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_staff_'.$access);  
                 my @newspecstaff;  
                 $helphash{'helpsettings'}{'adhoc'}{$rolename}{$access} = [];  
                 foreach my $person (sort(@personnel)) {  
                     if ($domhelpdesk{$person}) {  
                         push(@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}},$person);  
                     }  
                 }  
                 if (ref($curr{$access}) eq 'ARRAY') {  
                     my @diffs = &Apache::loncommon::compare_arrays($helphash{'helpsettings'}{'adhoc'}{$rolename}{$access},$curr{$access});  
                     if (@diffs) {  
                         $changes{'customrole'}{$rolename}{$access} = 1;  
                     }  
                 } elsif (@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}}) {  
                     $changes{'customrole'}{$rolename}{$access} = 1;  
                 }  
                 foreach my $person (@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}}) {  
                     my ($uname,$udom) = split(/:/,$person);  
                         push(@newspecstaff,&Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$udom,'lastname'),$uname,$udom));  
                 }  
                 $newsettings{$rolename}{$access} = join(', ',sort(@newspecstaff));  
             }  
         } else {  
             $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'}= 'all';  
         }  
         unless ($curr{'access'} eq $access) {  
             $changes{'customrole'}{$rolename}{'access'} = 1;  
             $newsettings{$rolename}{'access'} = $lt{$helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'}};  
         }          }
     }      }
     if (@allpos > 0) {      
         my $idx = 0;      if (ref($domconfig{'helpsettings'}) eq 'HASH') {
         foreach my $rolename (@allpos) {     
             if ($rolename ne '') {          foreach my $item (@toggles) {
                 $helphash{'helpsettings'}{'adhoc'}{$rolename}{'order'} = $idx;         
                 if (ref($current{'adhoc'}) eq 'HASH') {   if ($defaultchecked{$item} eq 'on') { 
                     if (ref($current{'adhoc'}{$rolename}) eq 'HASH') {   if (($domconfig{'helpsettings'}{$item} eq '') &&
                         if ($current{'adhoc'}{$rolename}{'order'} ne $idx) {   ($env{'form.'.$item} eq '0')) {
                             $changes{'customrole'}{$rolename}{'order'} = 1;   $changes{$item} = 1;
                             $newsettings{$rolename}{'order'} = $idx+1;   } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {
                         }   $changes{$item} = 1;
                     }   }
                 }   } elsif ($defaultchecked{$item} eq 'off') {
                 $idx ++;   if (($domconfig{'helpsettings'}{$item} eq '') &&
    ($env{'form.'.$item} eq '1')) {
    $changes{$item} = 1;
    } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {
    $changes{$item} = 1;
    }
    }
    $helphash{'helpsettings'}{$item} = $env{'form.'.$item};
    }
   
    if ($customhelpfile ne '') {
    my $error;
    if ($configuserok eq 'ok') {
    if ($switchserver) {
    $error = &mt("Upload of custom help file is not permitted to this server: [_1]",$switchserver);
    } else {
    if ($author_ok eq 'ok') {
    my ($result,$loginhelpurl) =
    &publishlogo($r,'upload','loginhelpurl',$dom,
    $confname,'help','','',$customhelpfile);
    if ($result eq 'ok') {
    $helphash{'helpsettings'}{'loginhelpurl'} = $loginhelpurl;
    $changes{'loginhelpurl'} = 1;
    } else {
    $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$customhelpfile,$result);
    }
    } else {
    $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3].  Error was: [_4].",$customhelpfile,$confname,$dom,$author_ok);
    }
    }
    } else {
    $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3].  Error was: [_4].",$customhelpfile,$confname,$dom,$configuserok);
    }
    if ($error) {
    &Apache::lonnet::logthis($error);
    $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
    }
    }
   
           if ($domconfig{'helpsettings'}{'loginhelpurl'} ne '') {
               if ($env{'form.loginhelpurl_del'}) {
                   $helphash{'helpsettings'}{'loginhelpurl'} = '';
                   $changes{'loginhelpurl'} = 1;
             }              }
         }          }
     }      }
       
       
     my $putresult;      my $putresult;
       
     if (keys(%changes) > 0) {      if (keys(%changes) > 0) {
         $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom);      $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom);
         if ($putresult eq 'ok') {      } else {
             if (ref($helphash{'helpsettings'}) eq 'HASH') {      $putresult = 'ok';
                 $domdefaults{'submitbugs'} = $helphash{'helpsettings'}{'submitbugs'};  
                 if (ref($helphash{'helpsettings'}{'adhoc'}) eq 'HASH') {  
                     $domdefaults{'adhocroles'} = $helphash{'helpsettings'}{'adhoc'};  
                 }  
             }  
             my $cachetime = 24*60*60;  
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);  
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'domdefaults'} = 1;  
             }  
         } else {  
             $errors .= '<li><span class="LC_error">'.  
                        &mt('An error occurred storing the settings: [_1]',  
                            $putresult).'</span></li>';  
         }  
     }      }
     if ((keys(%changes) && ($putresult eq 'ok')) || (keys(%changedprivs))) {                                               
         $resulttext = &mt('Changes made:').'<ul>';      if ($putresult eq 'ok') {
         my (%shownprivs,@levelorder);          if (keys(%changes) > 0) {
         @levelorder = ('c','d','s');   $resulttext = &mt('Changes made:').'<ul>';
         if ((keys(%changes)) && ($putresult eq 'ok')) {   foreach my $item (sort(keys(%changes))) {
             foreach my $item (sort(keys(%changes))) {   if ($item eq 'submitbugs') {
                 if ($item eq 'submitbugs') {   $resulttext .= '<li>'.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'</li>';
                     $resulttext .= '<li>'.&mt('Display link to: [_1] set to "'.$offon[$env{'form.'.$item}].'".',   }
                                               &Apache::loncommon::modal_link('http://bugs.loncapa.org',   if ($item eq 'loginhelpurl') {
                                               &mt('LON-CAPA bug tracker'),600,500)).'</li>';   if ($helphash{'helpsettings'}{'loginhelpurl'} eq '') {
                 } elsif ($item eq 'customrole') {                          $resulttext .= '<li>'.&mt('[_1] help file removed; [_2] file will be used for the unathorized help page in this domain.',$customhelpfile,$defaulthelpfile).'</li>';
                     if (ref($changes{'customrole'}) eq 'HASH') {                      } else {
                         my @keyorder = ('order','desc','access','status','exc','inc');                          $resulttext .= '<li>'.&mt("$title{$item} [_1]",$customhelpfile).'</li>';
                         my %keytext = &Apache::lonlocal::texthash(                      }
                                                                    order  => 'Order',   }
                                                                    desc   => 'Role description',   }
                                                                    access => 'Role usage',   $resulttext .= '</ul>';
                                                                    status => 'Allowed institutional types',   } else {
                                                                    exc    => 'Allowed personnel',   $resulttext = &mt('No changes made to help settings');
                                                                    inc    => 'Disallowed personnel',   }
                         );  
                         foreach my $role (sort(keys(%{$changes{'customrole'}}))) {  
                             if (ref($changes{'customrole'}{$role}) eq 'HASH') {  
                                 if ($role eq $newrole) {  
                                     $resulttext .= '<li>'.&mt('New custom role added: [_1]',  
                                                               $role).'<ul>';  
                                 } else {  
                                     $resulttext .= '<li>'.&mt('Existing custom role modified: [_1]',  
                                                               $role).'<ul>';  
                                 }  
                                 foreach my $key (@keyorder) {  
                                     if ($changes{'customrole'}{$role}{$key}) {  
                                         $resulttext .= '<li>'.&mt("[_1] set to: [_2]",  
                                                                   $keytext{$key},$newsettings{$role}{$key}).  
                                                        '</li>';  
                                     }  
                                 }  
                                 if (ref($changedprivs{$role}) eq 'HASH') {  
                                     $shownprivs{$role} = 1;  
                                     $resulttext .= '<li>'.&mt('Privileges set to :').'<ul>';  
                                     foreach my $level (@levelorder) {  
                                         foreach my $item (split(/\:/,$changedprivs{$role}{$level})) {  
                                             next if ($item eq '');  
                                             my ($priv) = split(/\&/,$item,2);  
                                             if (&Apache::lonnet::plaintext($priv)) {  
                                                 $resulttext .= '<li>'.&Apache::lonnet::plaintext($priv);  
                                                 unless ($level eq 'c') {  
                                                     $resulttext .= ' ('.$lt{$level}.')';  
                                                 }  
                                                 $resulttext .= '</li>';  
                                             }  
                                         }  
                                     }  
                                     $resulttext .= '</ul>';  
                                 }  
                                 $resulttext .= '</ul></li>';  
                             }  
                         }  
                     }  
                 }  
             }  
         }  
         if (keys(%changedprivs)) {  
             foreach my $role (sort(keys(%changedprivs))) {  
                 unless ($shownprivs{$role}) {  
                     $resulttext .= '<li>'.&mt('Existing custom role modified: [_1]',  
                                               $role).'<ul>'.  
                                    '<li>'.&mt('Privileges set to :').'<ul>';  
                     foreach my $level (@levelorder) {  
                         foreach my $item (split(/\:/,$changedprivs{$role}{$level})) {  
                             next if ($item eq '');  
                             my ($priv) = split(/\&/,$item,2);  
                             if (&Apache::lonnet::plaintext($priv)) {  
                                 $resulttext .= '<li>'.&Apache::lonnet::plaintext($priv);  
                                 unless ($level eq 'c') {  
                                     $resulttext .= ' ('.$lt{$level}.')';  
                                 }  
                                 $resulttext .= '</li>';  
                             }  
                         }  
                     }  
                     $resulttext .= '</ul></li></ul></li>';  
                 }  
             }  
         }  
         $resulttext .= '</ul>';  
     } else {      } else {
         $resulttext = &mt('No changes made to help settings');          $resulttext = '<span class="LC_error">'.
       &mt('An error occurred: [_1]',$putresult).'</span>';
     }      }
     if ($errors) {      if ($errors) {
         $resulttext .= '<br />'.&mt('The following errors occurred: ').'<ul>'.          $resulttext .= &mt('The following errors occurred: ').'<ul>'.
                                     $errors.'</ul>';                         $errors.'</ul>';
     }      }
     return $resulttext;      return $resulttext;
 }  }
   
 sub modify_coursedefaults {  sub modify_coursedefaults {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,$errors,%changes,%defaultshash);      my ($resulttext,$errors,%changes,%defaultshash);
     my %defaultchecked = (      my %defaultchecked = ('canuse_pdfforms' => 'off');
                            'uselcmath'       => 'on',      my @offon = ('off','on');
                            'usejsme'         => 'on'      my @toggles = ('canuse_pdfforms');
                          );  
     my @toggles = ('uselcmath','usejsme');  
     my @numbers = ('anonsurvey_threshold','uploadquota_official','uploadquota_unofficial',  
                    'uploadquota_community','uploadquota_textbook','mysqltables_official',  
                    'mysqltables_unofficial','mysqltables_community','mysqltables_textbook');  
     my @types = ('official','unofficial','community','textbook');  
     my %staticdefaults = (  
                            anonsurvey_threshold => 10,  
                            uploadquota          => 500,  
                            postsubmit           => 60,  
                            mysqltables          => 172800,  
                          );  
     my %texoptions = (  
                         MathJax  => 'MathJax',  
                         mimetex  => &mt('Convert to Images'),  
                         tth      => &mt('TeX to HTML'),  
                      );  
     $defaultshash{'coursedefaults'} = {};      $defaultshash{'coursedefaults'} = {};
   
     if (ref($domconfig{'coursedefaults'}) ne 'HASH') {      if (ref($domconfig{'coursedefaults'}) ne 'HASH') {
Line 13881  sub modify_coursedefaults { Line 7301  sub modify_coursedefaults {
                 if (($domconfig{'coursedefaults'}{$item} eq '') &&                  if (($domconfig{'coursedefaults'}{$item} eq '') &&
                     ($env{'form.'.$item} eq '0')) {                      ($env{'form.'.$item} eq '0')) {
                     $changes{$item} = 1;                      $changes{$item} = 1;
                 } elsif ($domconfig{'coursedefaults'}{$item} ne $env{'form.'.$item}) {                  } elsif ($domconfig{'coursdefaults'}{$item} ne $env{'form.'.$item}) {
                     $changes{$item} = 1;                      $changes{$item} = 1;
                 }                  }
             } elsif ($defaultchecked{$item} eq 'off') {              } elsif ($defaultchecked{$item} eq 'off') {
Line 13894  sub modify_coursedefaults { Line 7314  sub modify_coursedefaults {
             }              }
             $defaultshash{'coursedefaults'}{$item} = $env{'form.'.$item};              $defaultshash{'coursedefaults'}{$item} = $env{'form.'.$item};
         }          }
         foreach my $item (@numbers) {          my $currdefresponder = $domconfig{'coursedefaults'}{'anonsurvey_threshold'};
             my ($currdef,$newdef);          my $newdefresponder = $env{'form.anonsurvey_threshold'};
             $newdef = $env{'form.'.$item};          $newdefresponder =~ s/\D//g;
             if ($item eq 'anonsurvey_threshold') {          if ($newdefresponder eq '' || $newdefresponder < 1) {
                 $currdef = $domconfig{'coursedefaults'}{$item};              $newdefresponder = 1;
                 $newdef =~ s/\D//g;          }
                 if ($newdef eq '' || $newdef < 1) {          $defaultshash{'coursedefaults'}{'anonsurvey_threshold'} = $newdefresponder;
                     $newdef = 1;          if ($currdefresponder ne $newdefresponder) {
                 }              unless ($currdefresponder eq '' && $newdefresponder == 10) {
                 $defaultshash{'coursedefaults'}{$item} = $newdef;                  $changes{'anonsurvey_threshold'} = 1;
             } else {  
                 my ($setting,$type) = ($item =~ /^(uploadquota|mysqltables)_(\w+)$/);  
                 if (ref($domconfig{'coursedefaults'}{$setting}) eq 'HASH') {  
                     $currdef = $domconfig{'coursedefaults'}{$setting}{$type};  
                 }  
                 $newdef =~ s/[^\w.\-]//g;  
                 $defaultshash{'coursedefaults'}{$setting}{$type} = $newdef;  
             }  
             if ($currdef ne $newdef) {  
                 if ($item eq 'anonsurvey_threshold') {  
                     unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) {  
                         $changes{$item} = 1;  
                     }  
                 } elsif ($item =~ /^(uploadquota|mysqltables)_/) {  
                     my $setting = $1;  
                     unless (($currdef eq '') && ($newdef == $staticdefaults{$setting})) {  
                         $changes{$setting} = 1;  
                     }  
                 }  
             }  
         }  
         my $texengine;  
         if ($env{'form.texengine'} =~ /^(MathJax|mimetex|tth)$/) {  
             $texengine = $env{'form.texengine'};  
             my $currdef = $domconfig{'coursedefaults'}{'texengine'};  
             if ($currdef eq '') {  
                 unless ($texengine eq $Apache::lonnet::deftex) {  
                     $changes{'texengine'} = 1;  
                 }  
             } elsif ($currdef ne $texengine) {  
                 $changes{'texengine'} = 1;  
             }  
         }  
         if ($texengine ne '') {  
             $defaultshash{'coursedefaults'}{'texengine'} = $texengine;  
         }  
         my $currclone = $domconfig{'coursedefaults'}{'canclone'};  
         my @currclonecode;  
         if (ref($currclone) eq 'HASH') {  
             if (ref($currclone->{'instcode'}) eq 'ARRAY') {  
                 @currclonecode = @{$currclone->{'instcode'}};  
             }  
         }  
         my $newclone;  
         if ($env{'form.canclone'} =~ /^(none|domain|instcode)$/) {  
             $newclone = $env{'form.canclone'};  
         }  
         if ($newclone eq 'instcode') {  
             my @newcodes = &Apache::loncommon::get_env_multiple('form.clonecode');  
             my (%codedefaults,@code_order,@clonecode);  
             &Apache::lonnet::auto_instcode_defaults($dom,\%codedefaults,  
                                                     \@code_order);  
             foreach my $item (@code_order) {  
                 if (grep(/^\Q$item\E$/,@newcodes)) {  
                     push(@clonecode,$item);  
                 }  
             }  
             if (@clonecode) {  
                 $defaultshash{'coursedefaults'}{'canclone'} = { $newclone => \@clonecode };  
                 my @diffs = &Apache::loncommon::compare_arrays(\@currclonecode,\@clonecode);  
                 if (@diffs) {  
                     $changes{'canclone'} = 1;  
                 }  
             } else {  
                 $newclone eq '';  
             }  
         } elsif ($newclone ne '') {  
             $defaultshash{'coursedefaults'}{'canclone'} = $newclone;  
         }  
         if ($newclone ne $currclone) {  
             $changes{'canclone'} = 1;  
         }  
         my %credits;  
         foreach my $type (@types) {  
             unless ($type eq 'community') {  
                 $credits{$type} = $env{'form.'.$type.'_credits'};  
                 $credits{$type} =~ s/[^\d.]+//g;  
             }  
         }  
         if ((ref($domconfig{'coursedefaults'}{'coursecredits'}) ne 'HASH') &&  
             ($env{'form.coursecredits'} eq '1')) {  
             $changes{'coursecredits'} = 1;  
             foreach my $type (keys(%credits)) {  
                 $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type};  
             }  
         } else {  
             if ($env{'form.coursecredits'} eq '1') {  
                 foreach my $type (@types) {  
                     unless ($type eq 'community') {  
                         if ($domconfig{'coursedefaults'}{'coursecredits'}{$type} ne $credits{$type}) {  
                             $changes{'coursecredits'} = 1;  
                         }  
                         $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type};  
                     }  
                 }  
             } elsif (ref($domconfig{'coursedefaults'}{'coursecredits'}) eq 'HASH') {  
                 foreach my $type (@types) {  
                     unless ($type eq 'community') {  
                         if ($domconfig{'coursedefaults'}{'coursecredits'}{$type}) {  
                             $changes{'coursecredits'} = 1;  
                             last;  
                         }  
                     }  
                 }  
             }  
         }  
         if ($env{'form.postsubmit'} eq '1') {  
             $defaultshash{'coursedefaults'}{'postsubmit'}{'client'} = 'on';  
             my %currtimeout;  
             if (ref($domconfig{'coursedefaults'}{'postsubmit'}) eq 'HASH') {  
                 if ($domconfig{'coursedefaults'}{'postsubmit'}{'client'} eq 'off') {  
                     $changes{'postsubmit'} = 1;  
                 }  
                 if (ref($domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {  
                     %currtimeout = %{$domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}};  
                 }  
             } else {  
                 $changes{'postsubmit'} = 1;  
             }  
             foreach my $type (@types) {  
                 my $timeout = $env{'form.'.$type.'_timeout'};  
                 $timeout =~ s/\D//g;  
                 if ($timeout == $staticdefaults{'postsubmit'}) {  
                     $timeout = '';  
                 } elsif (($timeout eq '') || ($timeout =~ /^0+$/)) {  
                     $timeout = '0';  
                 }  
                 unless ($timeout eq '') {  
                     $defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}{$type} = $timeout;  
                 }  
                 if (exists($currtimeout{$type})) {  
                     if ($timeout ne $currtimeout{$type}) {  
                         $changes{'postsubmit'} = 1;  
                     }  
                 } elsif ($timeout ne '') {  
                     $changes{'postsubmit'} = 1;  
                 }  
             }  
         } else {  
             $defaultshash{'coursedefaults'}{'postsubmit'}{'client'} = 'off';  
             if (ref($domconfig{'coursedefaults'}{'postsubmit'}) eq 'HASH') {  
                 if ($domconfig{'coursedefaults'}{'postsubmit'}{'client'} eq 'on') {  
                     $changes{'postsubmit'} = 1;  
                 }  
             } else {  
                 $changes{'postsubmit'} = 1;  
             }              }
         }          }
     }      }
Line 14057  sub modify_coursedefaults { Line 7331  sub modify_coursedefaults {
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);              if ($changes{'canuse_pdfforms'}) {
             if (($changes{'uploadquota'}) || ($changes{'postsubmit'}) ||                  my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
                 ($changes{'coursecredits'}) || ($changes{'uselcmath'}) || ($changes{'usejsme'}) ||                  $domdefaults{'canuse_pdfforms'}=$defaultshash{'coursedefaults'}{'canuse_pdfforms'};
                 ($changes{'canclone'}) || ($changes{'mysqltables'}) || ($changes{'texengine'})) {  
                 foreach my $item ('uselcmath','usejsme','texengine') {  
                     if ($changes{$item}) {  
                         $domdefaults{$item}=$defaultshash{'coursedefaults'}{$item};  
                     }  
                 }  
                 if ($changes{'coursecredits'}) {  
                     if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {  
                         foreach my $type (keys(%{$defaultshash{'coursedefaults'}{'coursecredits'}})) {  
                             $domdefaults{$type.'credits'} =  
                                 $defaultshash{'coursedefaults'}{'coursecredits'}{$type};  
                         }  
                     }  
                 }  
                 if ($changes{'postsubmit'}) {  
                     if (ref($defaultshash{'coursedefaults'}{'postsubmit'}) eq 'HASH') {  
                         $domdefaults{'postsubmit'} = $defaultshash{'coursedefaults'}{'postsubmit'}{'client'};  
                         if (ref($defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {  
                             foreach my $type (keys(%{$defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}})) {  
                                 $domdefaults{$type.'postsubtimeout'} =  
                                     $defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}{$type};  
                             }  
                         }  
                     }  
                 }  
                 if ($changes{'uploadquota'}) {  
                     if (ref($defaultshash{'coursedefaults'}{'uploadquota'}) eq 'HASH') {  
                         foreach my $type (@types) {  
                             $domdefaults{$type.'quota'}=$defaultshash{'coursedefaults'}{'uploadquota'}{$type};  
                         }  
                     }  
                 }  
                 if ($changes{'canclone'}) {  
                     if (ref($defaultshash{'coursedefaults'}{'canclone'}) eq 'HASH') {  
                         if (ref($defaultshash{'coursedefaults'}{'canclone'}{'instcode'}) eq 'ARRAY') {  
                             my @clonecodes = @{$defaultshash{'coursedefaults'}{'canclone'}{'instcode'}};  
                             if (@clonecodes) {  
                                 $domdefaults{'canclone'} = join('+',@clonecodes);  
                             }  
                         }  
                     } else {  
                         $domdefaults{'canclone'}=$defaultshash{'coursedefaults'}{'canclone'};  
                     }  
                 }  
                 my $cachetime = 24*60*60;                  my $cachetime = 24*60*60;
                 &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);                  &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
                 if (ref($lastactref) eq 'HASH') {  
                     $lastactref->{'domdefaults'} = 1;  
                 }  
             }              }
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
                 if ($item eq 'uselcmath') {                  if ($item eq 'canuse_pdfforms') {
                     if ($env{'form.'.$item} eq '1') {                      if ($env{'form.'.$item} eq '1') {
                         $resulttext .= '<li>'.&mt('Math preview uses LON-CAPA previewer (javascript), if supported by browser.').'</li>';                          $resulttext .= '<li>'.&mt("Course/Community users can create/upload PDF forms set to 'on'").'</li>';
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('Math preview uses DragMath (Java), if supported by client OS.').'</li>';                          $resulttext .= '<li>'.&mt('Course/Community users can create/upload PDF forms set to "off"').'</li>';
                     }  
                 } elsif ($item eq 'usejsme') {  
                     if ($env{'form.'.$item} eq '1') {  
                         $resulttext .= '<li>'.&mt('Molecule editor uses JSME (HTML5), if supported by browser.').'</li>';  
                     } else {  
                         $resulttext .= '<li>'.&mt('Molecule editor uses JME (Java), if supported by client OS.').'</li>';  
                     }  
                 } elsif ($item eq 'texengine') {  
                     if ($defaultshash{'coursedefaults'}{'texengine'} ne '') {  
                         $resulttext .= '<li>'.&mt('Default method to display mathematics set to: "[_1]"',  
                                                   $texoptions{$defaultshash{'coursedefaults'}{'texengine'}}).'</li>';  
                     }                      }
                 } elsif ($item eq 'anonsurvey_threshold') {                  } elsif ($item eq 'anonsurvey_threshold') {
                     $resulttext .= '<li>'.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'</li>';                          $resulttext .= '<li>'.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'</li>';
                 } elsif ($item eq 'uploadquota') {  
                     if (ref($defaultshash{'coursedefaults'}{'uploadquota'}) eq 'HASH') {  
                         $resulttext .= '<li>'.&mt('Default quota for content uploaded to a course/community via Course Editor set as follows:').'<ul>'.  
                                        '<li>'.&mt('Official courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'official'}.'</b>').'</li>'.  
                                        '<li>'.&mt('Unofficial courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'unofficial'}.'</b>').'</li>'.  
                                        '<li>'.&mt('Textbook courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'textbook'}.'</b>').'</li>'.  
   
                                        '<li>'.&mt('Communities: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'community'}.'</b>').'</li>'.  
                                        '</ul>'.  
                                        '</li>';  
                     } else {  
                         $resulttext .= '<li>'.&mt('Default quota for content uploaded via Course Editor remains default: [_1] MB',$staticdefaults{'uploadquota'}).'</li>';  
                     }  
                 } elsif ($item eq 'mysqltables') {  
                     if (ref($defaultshash{'coursedefaults'}{'mysqltables'}) eq 'HASH') {  
                         $resulttext .= '<li>'.&mt('Lifetime of "Temporary" MySQL tables (student performance data) on homeserver').'<ul>'.  
                                        '<li>'.&mt('Official courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'official'}.'</b>').'</li>'.  
                                        '<li>'.&mt('Unofficial courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'unofficial'}.'</b>').'</li>'.  
                                        '<li>'.&mt('Textbook courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'textbook'}.'</b>').'</li>'.  
                                        '<li>'.&mt('Communities: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'community'}.'</b>').'</li>'.  
                                        '</ul>'.  
                                        '</li>';  
                     } else {  
                         $resulttext .= '<li>'.&mt('Lifetime of "Temporary" MySQL tables (student performance data) on homeserver remains default: [_1] s',$staticdefaults{'uploadquota'}).'</li>';  
                     }  
                 } elsif ($item eq 'postsubmit') {  
                     if ($domdefaults{'postsubmit'} eq 'off') {  
                         $resulttext .= '<li>'.&mt('Submit button(s) remain enabled on page after student makes submission.');  
                     } else {  
                         $resulttext .= '<li>'.&mt('Submit button(s) disabled on page after student makes submission').'; ';  
                         if (ref($defaultshash{'coursedefaults'}{'postsubmit'}) eq 'HASH') {  
                             $resulttext .= &mt('durations:').'<ul>';  
                             foreach my $type (@types) {  
                                 $resulttext .= '<li>';  
                                 my $timeout;  
                                 if (ref($defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {  
                                     $timeout = $defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}{$type};  
                                 }  
                                 my $display;  
                                 if ($timeout eq '0') {  
                                     $display = &mt('unlimited');  
                                 } elsif ($timeout eq '') {  
                                     $display = &mt('[quant,_1,second] (default)',$staticdefaults{'postsubmit'});  
                                 } else {  
                                     $display = &mt('[quant,_1,second]',$timeout);  
                                 }  
                                 if ($type eq 'community') {  
                                     $resulttext .= &mt('Communities');  
                                 } elsif ($type eq 'official') {  
                                     $resulttext .= &mt('Official courses');  
                                 } elsif ($type eq 'unofficial') {  
                                     $resulttext .= &mt('Unofficial courses');  
                                 } elsif ($type eq 'textbook') {  
                                     $resulttext .= &mt('Textbook courses');  
                                 }  
                                 $resulttext .= ' -- '.$display.'</li>';  
                             }  
                             $resulttext .= '</ul>';  
                         }  
                         $resulttext .= '</li>';  
                     }  
                 } elsif ($item eq 'coursecredits') {  
                     if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {  
                         if (($domdefaults{'officialcredits'} eq '') &&  
                             ($domdefaults{'unofficialcredits'} eq '') &&  
                             ($domdefaults{'textbookcredits'} eq '')) {  
                             $resulttext .= '<li>'.&mt('Student credits not in use for courses in this domain').'</li>';  
                         } else {  
                             $resulttext .= '<li>'.&mt('Student credits can be set per course by a Domain Coordinator, with the following defaults applying:').'<ul>'.  
                                            '<li>'.&mt('Official courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'official'}).'</li>'.  
                                            '<li>'.&mt('Unofficial courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'unofficial'}).'</li>'.  
                                            '<li>'.&mt('Textbook courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'textbook'}).'</li>'.  
                                            '</ul>'.  
                                            '</li>';  
                         }  
                     } else {  
                         $resulttext .= '<li>'.&mt('Student credits not in use for courses in this domain').'</li>';  
                     }  
                 } elsif ($item eq 'canclone') {  
                     if (ref($defaultshash{'coursedefaults'}{'canclone'}) eq 'HASH') {  
                         if (ref($defaultshash{'coursedefaults'}{'canclone'}{'instcode'}) eq 'ARRAY') {  
                             my $clonecodes = join(' '.&mt('and').' ',@{$defaultshash{'coursedefaults'}{'canclone'}{'instcode'}});  
                             $resulttext .= '<li>'.&mt('By default, official courses can be cloned from existing courses with the same: [_1]','<b>'.$clonecodes.'</b>').'</li>';  
                         }  
                     } elsif ($defaultshash{'coursedefaults'}{'canclone'} eq 'domain') {  
                         $resulttext .= '<li>'.&mt('By default, a course requester can clone any course from his/her domain.').'</li>';  
                     } else {  
                         $resulttext .= '<li>'.&mt('By default, only course owner and coordinators may clone a course.').'</li>';  
                     }  
                 }                  }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
Line 14233  sub modify_coursedefaults { Line 7360  sub modify_coursedefaults {
     return $resulttext;      return $resulttext;
 }  }
   
 sub modify_selfenrollment {  
     my ($dom,$lastactref,%domconfig) = @_;  
     my ($resulttext,$errors,%changes,%selfenrollhash,%ordered);  
     my @types = ('official','unofficial','community','textbook');  
     my %titles = &tool_titles();  
     my %descs = &Apache::lonuserutils::selfenroll_default_descs();  
     ($ordered{'admin'},my $titlesref) = &Apache::lonuserutils::get_selfenroll_titles();  
     $ordered{'default'} = ['types','registered','approval','limit'];  
   
     my (%roles,%shown,%toplevel);  
     $roles{'0'} = &Apache::lonnet::plaintext('dc');  
   
     if (ref($domconfig{'selfenrollment'}) ne 'HASH') {  
         if ($domconfig{'selfenrollment'} eq '') {  
             $domconfig{'selfenrollment'} = {};  
         }  
     }  
     %toplevel = (  
                   admin      => 'Configuration Rights',  
                   default    => 'Default settings',  
                   validation => 'Validation of self-enrollment requests',  
                 );  
     my ($itemsref,$namesref,$fieldsref) = &Apache::lonuserutils::selfenroll_validation_types();  
   
     if (ref($ordered{'admin'}) eq 'ARRAY') {  
         foreach my $item (@{$ordered{'admin'}}) {  
             foreach my $type (@types) {  
                 if ($env{'form.selfenrolladmin_'.$item.'_'.$type}) {  
                     $selfenrollhash{'admin'}{$type}{$item} = 1;  
                 } else {  
                     $selfenrollhash{'admin'}{$type}{$item} = 0;  
                 }  
                 if (ref($domconfig{'selfenrollment'}{'admin'}) eq 'HASH') {  
                     if (ref($domconfig{'selfenrollment'}{'admin'}{$type}) eq 'HASH') {  
                         if ($selfenrollhash{'admin'}{$type}{$item} ne  
                             $domconfig{'selfenrollment'}{'admin'}{$type}{$item})  {  
                             push(@{$changes{'admin'}{$type}},$item);  
                         }  
                     } else {  
                         if (!$selfenrollhash{'admin'}{$type}{$item}) {  
                             push(@{$changes{'admin'}{$type}},$item);  
                         }  
                     }  
                 } elsif (!$selfenrollhash{'admin'}{$type}{$item}) {  
                     push(@{$changes{'admin'}{$type}},$item);  
                 }  
             }  
         }  
     }  
   
     foreach my $item (@{$ordered{'default'}}) {  
         foreach my $type (@types) {  
             my $value = $env{'form.selfenrolldefault_'.$item.'_'.$type};  
             if ($item eq 'types') {  
                 unless (($value eq 'all') || ($value eq 'dom')) {  
                     $value = '';  
                 }  
             } elsif ($item eq 'registered') {  
                 unless ($value eq '1') {  
                     $value = 0;  
                 }  
             } elsif ($item eq 'approval') {  
                 unless ($value =~ /^[012]$/) {  
                     $value = 0;  
                 }  
             } else {  
                 unless (($value eq 'allstudents') || ($value eq 'selfenrolled')) {  
                     $value = 'none';  
                 }  
             }  
             $selfenrollhash{'default'}{$type}{$item} = $value;  
             if (ref($domconfig{'selfenrollment'}{'default'}) eq 'HASH') {  
                 if (ref($domconfig{'selfenrollment'}{'default'}{$type}) eq 'HASH') {  
                     if ($selfenrollhash{'default'}{$type}{$item} ne  
                          $domconfig{'selfenrollment'}{'default'}{$type}{$item})  {  
                          push(@{$changes{'default'}{$type}},$item);  
                     }  
                 } else {  
                     push(@{$changes{'default'}{$type}},$item);  
                 }  
             } else {  
                 push(@{$changes{'default'}{$type}},$item);  
             }  
             if ($item eq 'limit') {  
                 if (($value eq 'allstudents') || ($value eq 'selfenrolled')) {  
                     $env{'form.selfenrolldefault_cap_'.$type} =~ s/\D//g;  
                     if ($env{'form.selfenrolldefault_cap_'.$type} ne '') {  
                         $selfenrollhash{'default'}{$type}{'cap'} = $env{'form.selfenrolldefault_cap_'.$type};  
                     }  
                 } else {  
                     $selfenrollhash{'default'}{$type}{'cap'} = '';  
                 }  
                 if (ref($domconfig{'selfenrollment'}{'default'}{$type}) eq 'HASH') {  
                     if ($selfenrollhash{'default'}{$type}{'cap'} ne  
                          $domconfig{'selfenrollment'}{'admin'}{$type}{'cap'})  {  
                          push(@{$changes{'default'}{$type}},'cap');  
                     }  
                 } elsif ($selfenrollhash{'default'}{$type}{'cap'} ne '') {  
                     push(@{$changes{'default'}{$type}},'cap');  
                 }  
             }  
         }  
     }  
   
     foreach my $item (@{$itemsref}) {  
         if ($item eq 'fields') {  
             my @changed;  
             @{$selfenrollhash{'validation'}{$item}} = &Apache::loncommon::get_env_multiple('form.selfenroll_validation_'.$item);  
             if (@{$selfenrollhash{'validation'}{$item}} > 0) {  
                 @{$selfenrollhash{'validation'}{$item}} = sort(@{$selfenrollhash{'validation'}{$item}});  
             }  
             if (ref($domconfig{'selfenrollment'}{'validation'}) eq 'HASH') {  
                 if (ref($domconfig{'selfenrollment'}{'validation'}{$item}) eq 'ARRAY') {  
                     @changed = &Apache::loncommon::compare_arrays($selfenrollhash{'validation'}{$item},  
                                                                   $domconfig{'selfenrollment'}{'validation'}{$item});  
                 } else {  
                     @changed = @{$selfenrollhash{'validation'}{$item}};  
                 }  
             } else {  
                 @changed = @{$selfenrollhash{'validation'}{$item}};  
             }  
             if (@changed) {  
                 if ($selfenrollhash{'validation'}{$item}) {   
                     $changes{'validation'}{$item} = join(', ',@{$selfenrollhash{'validation'}{$item}});  
                 } else {  
                     $changes{'validation'}{$item} = &mt('None');  
                 }  
             }  
         } else {  
             $selfenrollhash{'validation'}{$item} = $env{'form.selfenroll_validation_'.$item};  
             if ($item eq 'markup') {  
                if ($env{'form.selfenroll_validation_'.$item}) {  
                    $env{'form.selfenroll_validation_'.$item} =~ s/[\n\r\f]+/\s/gs;  
                }  
             }  
             if (ref($domconfig{'selfenrollment'}{'validation'}) eq 'HASH') {  
                 if ($domconfig{'selfenrollment'}{'validation'}{$item} ne $selfenrollhash{'validation'}{$item}) {  
                     $changes{'validation'}{$item} = $selfenrollhash{'validation'}{$item};  
                 }  
             }  
         }  
     }  
   
     my $putresult = &Apache::lonnet::put_dom('configuration',{'selfenrollment' => \%selfenrollhash},  
                                              $dom);  
     if ($putresult eq 'ok') {  
         if (keys(%changes) > 0) {  
             my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);  
             $resulttext = &mt('Changes made:').'<ul>';  
             foreach my $key ('admin','default','validation') {  
                 if (ref($changes{$key}) eq 'HASH') {  
                     $resulttext .= '<li>'.$toplevel{$key}.'<ul>';  
                     if ($key eq 'validation') {  
                         foreach my $item (@{$itemsref}) {  
                             if (exists($changes{$key}{$item})) {  
                                 if ($item eq 'markup') {  
                                     $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$namesref->{$item},  
                                                               '<br /><pre>'.$changes{$key}{$item}.'</pre>').'</li>';  
                                 } else {    
                                     $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$namesref->{$item},  
                                                               '<b>'.$changes{$key}{$item}.'</b>').'</li>';  
                                 }  
                             }  
                         }  
                     } else {  
                         foreach my $type (@types) {  
                             if ($type eq 'community') {  
                                 $roles{'1'} = &mt('Community personnel');  
                             } else {  
                                 $roles{'1'} = &mt('Course personnel');  
                             }  
                             if (ref($changes{$key}{$type}) eq 'ARRAY') {  
                                 if (ref($selfenrollhash{$key}{$type}) eq 'HASH') {  
                                     if ($key eq 'admin') {  
                                         my @mgrdc = ();  
                                         if (ref($ordered{$key}) eq 'ARRAY') {  
                                             foreach my $item (@{$ordered{'admin'}}) {  
                                                 if (ref($selfenrollhash{$key}{$type}) eq 'HASH') {   
                                                     if ($selfenrollhash{$key}{$type}{$item} eq '0') {  
                                                         push(@mgrdc,$item);  
                                                     }  
                                                 }  
                                             }  
                                             if (@mgrdc) {  
                                                 $domdefaults{$type.'selfenrolladmdc'} = join(',',@mgrdc);  
                                             } else {  
                                                 delete($domdefaults{$type.'selfenrolladmdc'});  
                                             }  
                                         }  
                                     } else {  
                                         if (ref($ordered{$key}) eq 'ARRAY') {  
                                             foreach my $item (@{$ordered{$key}}) {  
                                                 if (grep(/^\Q$item\E$/,@{$changes{$key}{$type}})) {  
                                                     $domdefaults{$type.'selfenroll'.$item} =  
                                                         $selfenrollhash{$key}{$type}{$item};  
                                                 }  
                                             }  
                                         }  
                                     }  
                                 }  
                                 $resulttext .= '<li>'.$titles{$type}.'<ul>';  
                                 foreach my $item (@{$ordered{$key}}) {  
                                     if (grep(/^\Q$item\E$/,@{$changes{$key}{$type}})) {  
                                         $resulttext .= '<li>';  
                                         if ($key eq 'admin') {  
                                             $resulttext .= &mt('[_1] -- management by: [_2]',$titlesref->{$item},  
                                                                '<b>'.$roles{$selfenrollhash{'admin'}{$type}{$item}}.'</b>');  
                                         } else {  
                                             $resulttext .= &mt('[_1] set to: [_2]',$titlesref->{$item},  
                                                                '<b>'.$descs{$item}{$selfenrollhash{'default'}{$type}{$item}}.'</b>');  
                                         }  
                                         $resulttext .= '</li>';  
                                     }  
                                 }  
                                 $resulttext .= '</ul></li>';  
                             }  
                         }  
                         $resulttext .= '</ul></li>';   
                     }  
                 }  
             }  
             if ((exists($changes{'admin'})) || (exists($changes{'default'}))) {  
                 my $cachetime = 24*60*60;  
                 &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);  
                 if (ref($lastactref) eq 'HASH') {  
                     $lastactref->{'domdefaults'} = 1;  
                 }  
             }  
             $resulttext .= '</ul>';  
         } else {  
             $resulttext = &mt('No changes made to self-enrollment settings');  
         }  
     } else {  
         $resulttext = '<span class="LC_error">'.  
             &mt('An error occurred: [_1]',$putresult).'</span>';  
     }  
     return $resulttext;  
 }  
   
 sub modify_usersessions {  sub modify_usersessions {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my @hostingtypes = ('version','excludedomain','includedomain');      my @hostingtypes = ('version','excludedomain','includedomain');
     my @offloadtypes = ('primary','default');      my @offloadtypes = ('primary','default');
     my %types = (      my %types = (
Line 14490  sub modify_usersessions { Line 7378  sub modify_usersessions {
     foreach my $prefix (@prefixes) {      foreach my $prefix (@prefixes) {
         $defaultshash{'usersessions'}{$prefix} = {};          $defaultshash{'usersessions'}{$prefix} = {};
     }      }
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
     my $resulttext;      my $resulttext;
     my %iphost = &Apache::lonnet::get_iphost();      my %iphost = &Apache::lonnet::get_iphost();
     foreach my $prefix (@prefixes) {      foreach my $prefix (@prefixes) {
Line 14638  sub modify_usersessions { Line 7526  sub modify_usersessions {
             $changes{'spares'}{$lonhost} = \%spareschg;              $changes{'spares'}{$lonhost} = \%spareschg;
         }          }
     }      }
     $defaultshash{'usersessions'}{'offloadnow'} = {};  
     $defaultshash{'usersessions'}{'offloadoth'} = {};  
     my @offloadnow = &Apache::loncommon::get_env_multiple('form.offloadnow');  
     my @okoffload;  
     if (@offloadnow) {  
         foreach my $server (@offloadnow) {  
             if (&Apache::lonnet::hostname($server) ne '') {  
                 unless (grep(/^\Q$server\E$/,@okoffload)) {  
                     push(@okoffload,$server);  
                 }  
             }  
         }  
         if (@okoffload) {  
             foreach my $lonhost (@okoffload) {  
                 $defaultshash{'usersessions'}{'offloadnow'}{$lonhost} = 1;  
             }  
         }  
     }  
     my @offloadoth = &Apache::loncommon::get_env_multiple('form.offloadoth');  
     my @okoffloadoth;  
     if (@offloadoth) {  
         foreach my $server (@offloadoth) {  
             if (&Apache::lonnet::hostname($server) ne '') {  
                 unless (grep(/^\Q$server\E$/,@okoffloadoth)) {  
                     push(@okoffloadoth,$server);  
                 }  
             }  
         }  
         if (@okoffloadoth) {  
             foreach my $lonhost (@okoffloadoth) {  
                 $defaultshash{'usersessions'}{'offloadoth'}{$lonhost} = 1;  
             }  
         }  
     }  
     if (ref($domconfig{'usersessions'}) eq 'HASH') {      if (ref($domconfig{'usersessions'}) eq 'HASH') {
         if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') {          if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') {
             if (ref($changes{'spares'}) eq 'HASH') {              if (ref($changes{'spares'}) eq 'HASH') {
Line 14682  sub modify_usersessions { Line 7537  sub modify_usersessions {
         } else {          } else {
             $savespares = 1;              $savespares = 1;
         }          }
         foreach my $offload ('offloadnow','offloadoth') {  
             if (ref($domconfig{'usersessions'}{$offload}) eq 'HASH') {  
                 foreach my $lonhost (keys(%{$domconfig{'usersessions'}{$offload}})) {  
                     unless ($defaultshash{'usersessions'}{$offload}{$lonhost}) {  
                         $changes{$offload} = 1;  
                         last;  
                     }  
                 }  
                 unless ($changes{$offload}) {  
                     foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{$offload}})) {  
                         unless ($domconfig{'usersessions'}{$offload}{$lonhost}) {  
                             $changes{$offload} = 1;  
                             last;  
                         }  
                     }  
                 }  
             } else {  
                 if (($offload eq 'offloadnow') && (@okoffload)) {  
                      $changes{'offloadnow'} = 1;  
                 }  
                 if (($offload eq 'offloadoth') && (@okoffloadoth)) {  
                     $changes{'offloadoth'} = 1;  
                 }  
             }  
         }  
     } else {  
         if (@okoffload) {  
             $changes{'offloadnow'} = 1;  
         }  
         if (@okoffloadoth) {  
             $changes{'offloadoth'} = 1;  
         }  
     }      }
   
     my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');      my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');
     if ((keys(%changes) > 0) || ($savespares)) {      if ((keys(%changes) > 0) || ($savespares)) {
         my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,          my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
Line 14727  sub modify_usersessions { Line 7551  sub modify_usersessions {
                 if (ref($defaultshash{'usersessions'}{'hosted'}) eq 'HASH') {                  if (ref($defaultshash{'usersessions'}{'hosted'}) eq 'HASH') {
                     $domdefaults{'hostedsessions'} = $defaultshash{'usersessions'}{'hosted'};                      $domdefaults{'hostedsessions'} = $defaultshash{'usersessions'}{'hosted'};
                 }                  }
                 if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {  
                     $domdefaults{'offloadnow'} = $defaultshash{'usersessions'}{'offloadnow'};  
                 }  
                 if (ref($defaultshash{'usersessions'}{'offloadoth'}) eq 'HASH') {  
                     $domdefaults{'offloadoth'} = $defaultshash{'usersessions'}{'offloadoth'};  
                 }  
             }              }
             my $cachetime = 24*60*60;              my $cachetime = 24*60*60;
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);              &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
             &Apache::lonnet::do_cache_new('usersessions',$dom,$defaultshash{'usersessions'},3600);  
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'domdefaults'} = 1;  
                 $lastactref->{'usersessions'} = 1;  
             }  
             if (keys(%changes) > 0) {              if (keys(%changes) > 0) {
                 my %lt = &usersession_titles();                  my %lt = &usersession_titles();
                 $resulttext = &mt('Changes made:').'<ul>';                  $resulttext = &mt('Changes made:').'<ul>';
Line 14752  sub modify_usersessions { Line 7565  sub modify_usersessions {
                                 foreach my $lonhost (sort(keys(%{$changes{$prefix}}))) {                                  foreach my $lonhost (sort(keys(%{$changes{$prefix}}))) {
                                     $resulttext .= '<li><b>'.$lonhost.'</b> ';                                      $resulttext .= '<li><b>'.$lonhost.'</b> ';
                                     my $lonhostdom = &Apache::lonnet::host_domain($lonhost);                                      my $lonhostdom = &Apache::lonnet::host_domain($lonhost);
                                     my $cachekey = &escape('spares').':'.&escape($lonhostdom);                                      &Apache::lonnet::remote_devalidate_cache($lonhost,'spares',$lonhostdom);
                                     &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);  
                                     if (ref($changes{$prefix}{$lonhost}) eq 'HASH') {                                      if (ref($changes{$prefix}{$lonhost}) eq 'HASH') {
                                         foreach my $type (@{$types{$prefix}}) {                                          foreach my $type (@{$types{$prefix}}) {
                                             if ($changes{$prefix}{$lonhost}{$type}) {                                              if ($changes{$prefix}{$lonhost}{$type}) {
Line 14803  sub modify_usersessions { Line 7615  sub modify_usersessions {
                         $resulttext .= '</ul>';                          $resulttext .= '</ul>';
                     }                      }
                 }                  }
                 if ($changes{'offloadnow'}) {  
                     if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {  
                         if (keys(%{$defaultshash{'usersessions'}{'offloadnow'}}) > 0) {  
                             $resulttext .= '<li>'.&mt('Switch any active user on next access, for server(s):').'<ul>';  
                             foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadnow'}}))) {  
                                 $resulttext .= '<li>'.$lonhost.'</li>';  
                             }  
                             $resulttext .= '</ul>';  
                         } else {  
                             $resulttext .= '<li>'.&mt('No servers now set to switch any active user on next access.');  
                         }  
                     } else {  
                         $resulttext .= '<li>'.&mt('No servers now set to switch any active user on next access.').'</li>';  
                     }  
                 }  
                 if ($changes{'offloadoth'}) {  
                     if (ref($defaultshash{'usersessions'}{'offloadoth'}) eq 'HASH') {  
                         if (keys(%{$defaultshash{'usersessions'}{'offloadoth'}}) > 0) {  
                             $resulttext .= '<li>'.&mt('Switch other institutions on next access, for server(s):').'<ul>';  
                             foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadoth'}}))) {  
                                 $resulttext .= '<li>'.$lonhost.'</li>';  
                             }  
                             $resulttext .= '</ul>';  
                         } else {  
                             $resulttext .= '<li>'.&mt('No servers now set to switch other institutions on next access.');  
                         }  
                     } else {  
                         $resulttext .= '<li>'.&mt('No servers now set to switch other institutions on next access.').'</li>';  
                     }  
                 }  
                 $resulttext .= '</ul>';                  $resulttext .= '</ul>';
             } else {              } else {
                 $resulttext = $nochgmsg;                  $resulttext = $nochgmsg;
Line 14854  sub modify_loadbalancing { Line 7636  sub modify_loadbalancing {
     my ($othertitle,$usertypes,$types) =      my ($othertitle,$usertypes,$types) =
         &Apache::loncommon::sorted_inst_types($dom);          &Apache::loncommon::sorted_inst_types($dom);
     my %servers = &Apache::lonnet::internet_dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
     my %libraryservers = &Apache::lonnet::get_servers($dom,'library');  
     my @sparestypes = ('primary','default');      my @sparestypes = ('primary','default');
     my %typetitles = &sparestype_titles();      my %typetitles = &sparestype_titles();
     my $resulttext;      my $resulttext;
     my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);      if (keys(%servers) > 1) {
     if (ref($domconfig{'loadbalancing'}) eq 'HASH') {          my ($currbalancer,$currtargets,$currrules);
         %existing = %{$domconfig{'loadbalancing'}};          if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
     }              $currbalancer = $domconfig{'loadbalancing'}{'lonhost'};
     &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,              $currtargets = $domconfig{'loadbalancing'}{'targets'};
                               \%currtargets,\%currrules,\%currcookies);              $currrules = $domconfig{'loadbalancing'}{'rules'};
     my ($saveloadbalancing,%defaultshash,%changes);          } else {
     my ($alltypes,$othertypes,$titles) =              ($currbalancer,$currtargets) = 
         &loadbalancing_titles($dom,$intdom,$usertypes,$types);                  &Apache::lonnet::get_lonbalancer_config(\%servers);
     my %ruletitles = &offloadtype_text();          }
     my @deletions = &Apache::loncommon::get_env_multiple('form.loadbalancing_delete');          my ($saveloadbalancing,%defaultshash,%changes);
     for (my $i=0; $i<$env{'form.loadbalancing_total'}; $i++) {          my ($alltypes,$othertypes,$titles) =
         my $balancer = $env{'form.loadbalancing_lonhost_'.$i};              &loadbalancing_titles($dom,$intdom,$usertypes,$types);
         if ($balancer eq '') {          my %ruletitles = &offloadtype_text();
             next;          my $balancer = $env{'form.loadbalancing_lonhost'};
         }          if (!$servers{$balancer}) {
         if (!exists($servers{$balancer})) {              undef($balancer);
             if (exists($currbalancer{$balancer})) {          }
                 push(@{$changes{'delete'}},$balancer);          if ($currbalancer ne $balancer) {
               $changes{'lonhost'} = 1;
           }
           $defaultshash{'loadbalancing'}{'lonhost'} = $balancer;
           if ($balancer ne '') {
               unless (ref($domconfig{'loadbalancing'}) eq 'HASH') {
                   $saveloadbalancing = 1;
             }              }
             next;              foreach my $sparetype (@sparestypes) {
         }                  my @targets = &Apache::loncommon::get_env_multiple('form.loadbalancing_target_'.$sparetype);
         if ((@deletions > 0) && (grep(/^\Q$i\E$/,@deletions))) {                  my @offloadto;
             push(@{$changes{'delete'}},$balancer);                  foreach my $target (@targets) {
             next;                      if (($servers{$target}) && ($target ne $balancer)) {
         }                          if ($sparetype eq 'default') {
         if (!exists($currbalancer{$balancer})) {                              if (ref($defaultshash{'loadbalancing'}{'targets'}{'primary'}) eq 'ARRAY') {
             push(@{$changes{'add'}},$balancer);                                  next if (grep(/^\Q$target\E$/,@{$defaultshash{'loadbalancing'}{'targets'}{'primary'}}));
         }                              }
         $defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'} = [];                          }
         $defaultshash{'loadbalancing'}{$balancer}{'targets'}{'default'} = [];                          unless(grep(/^\Q$target\E$/,@offloadto)) {
         $defaultshash{'loadbalancing'}{$balancer}{'rules'} = {};                              push(@offloadto,$target);
         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)) {                      $defaultshash{'loadbalancing'}{'targets'}{$sparetype} = \@offloadto;
                         push(@offloadto,$target);  
                     }  
                 }                  }
             }              }
             if ($env{'form.loadbalancing_target_'.$i.'_hosthere'} eq $sparetype) {          } else {
                 unless(grep(/^\Q$balancer\E$/,@offloadto)) {              foreach my $sparetype (@sparestypes) {
                     push(@offloadto,$balancer);                  $defaultshash{'loadbalancing'}{'targets'}{$sparetype} = [];
                 }  
             }  
             $defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto;  
         }  
         if ($env{'form.loadbalancing_cookie_'.$i}) {  
             $defaultshash{'loadbalancing'}{$balancer}{'cookie'} = 1;  
             if (exists($currbalancer{$balancer})) {  
                 unless ($currcookies{$balancer}) {  
                     $changes{'curr'}{$balancer}{'cookie'} = 1;  
                 }  
             }  
         } elsif (exists($currbalancer{$balancer})) {  
             if ($currcookies{$balancer}) {  
                 $changes{'curr'}{$balancer}{'cookie'} = 1;  
             }              }
         }          }
         if (ref($currtargets{$balancer}) eq 'HASH') {          if (ref($currtargets) eq 'HASH') {
             foreach my $sparetype (@sparestypes) {              foreach my $sparetype (@sparestypes) {
                 if (ref($currtargets{$balancer}{$sparetype}) eq 'ARRAY') {                  if (ref($currtargets->{$sparetype}) eq 'ARRAY') {
                     my @targetdiffs = &Apache::loncommon::compare_arrays($currtargets{$balancer}{$sparetype},$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype});                      my @targetdiffs = &Apache::loncommon::compare_arrays($currtargets->{$sparetype},$defaultshash{'loadbalancing'}{'targets'}{$sparetype});
                     if (@targetdiffs > 0) {                      if (@targetdiffs > 0) {
                         $changes{'curr'}{$balancer}{'targets'} = 1;                          $changes{'targets'} = 1;
                     }                      }
                 } elsif (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {                  } elsif (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') {
                     if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {                      if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) {
                         $changes{'curr'}{$balancer}{'targets'} = 1;                          $changes{'targets'} = 1;
                     }                      }
                 }                  }
             }              }
         } else {          } else {
             if (ref($defaultshash{'loadbalancing'}{$balancer}) eq 'HASH') {              foreach my $sparetype (@sparestypes) {
                 foreach my $sparetype (@sparestypes) {                  if (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') {
                     if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {                      if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) {
                         if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {                          $changes{'targets'} = 1;  
                             $changes{'curr'}{$balancer}{'targets'} = 1;  
                         }  
                     }                      }
                 }                  }
             }              }  
         }          }
         my $ishomedom;          my $ishomedom;
         if (&Apache::lonnet::host_domain($balancer) eq $dom) {          if ($balancer ne '') {
             $ishomedom = 1;              if (&Apache::lonnet::host_domain($balancer) eq $dom) {
                   $ishomedom = 1;
               }
         }          }
         if (ref($alltypes) eq 'ARRAY') {          if (ref($alltypes) eq 'ARRAY') {
             foreach my $type (@{$alltypes}) {              foreach my $type (@{$alltypes}) {
                 my $rule;                  my $rule;
                 unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) &&                  if ($balancer ne '') {
                       unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) && 
                          (!$ishomedom)) {                           (!$ishomedom)) {
                     $rule = $env{'form.loadbalancing_rules_'.$i.'_'.$type};                          $rule = $env{'form.loadbalancing_rules_'.$type};
                 }                      }
                 if ($rule eq 'specific') {                      if ($rule eq 'specific') {
                     my $specifiedhost = $env{'form.loadbalancing_singleserver_'.$i.'_'.$type};                          $rule = $env{'form.loadbalancing_singleserver_'.$type};
                     if (exists($servers{$specifiedhost})) {  
                         $rule = $specifiedhost;  
                     }                      }
                 }                  }
                 $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type} = $rule;                  $defaultshash{'loadbalancing'}{'rules'}{$type} = $rule;
                 if (ref($currrules{$balancer}) eq 'HASH') {                  if (ref($currrules) eq 'HASH') {
                     if ($rule ne $currrules{$balancer}{$type}) {                      if ($rule ne $currrules->{$type}) {
                         $changes{'curr'}{$balancer}{'rules'}{$type} = 1;                          $changes{'rules'}{$type} = 1;
                     }                      }
                 } elsif ($rule ne '') {                  } elsif ($rule ne '') {
                     $changes{'curr'}{$balancer}{'rules'}{$type} = 1;                      $changes{'rules'}{$type} = 1;
                 }                  }
             }              }
         }          }
     }          my $nochgmsg = &mt('No changes made to Load Balancer settings.');
     my $nochgmsg = &mt('No changes made to Load Balancer settings.');          if ((keys(%changes) > 0) || ($saveloadbalancing)) {
     if ((keys(%changes) > 0) || ($saveloadbalancing)) {              my $putresult = &Apache::lonnet::put_dom('configuration',
         unless (ref($defaultshash{'loadbalancing'}) eq 'HASH') {                                                       \%defaultshash,$dom);
             $defaultshash{'loadbalancing'} = {};              if ($putresult eq 'ok') {
         }                  if (keys(%changes) > 0) {
         my $putresult = &Apache::lonnet::put_dom('configuration',                      if ($changes{'lonhost'}) {
                                                  \%defaultshash,$dom);                          if ($currbalancer ne '') {
         if ($putresult eq 'ok') {                              &Apache::lonnet::remote_devalidate_cache($currbalancer,'loadbalancing',$dom);
             if (keys(%changes) > 0) {                          }
                 my %toupdate;                          if ($balancer eq '') {
                 if (ref($changes{'delete'}) eq 'ARRAY') {                              $resulttext .= '<li>'.&mt('Load Balancing with dedicated server discontinued').'</li>'; 
                     foreach my $balancer (sort(@{$changes{'delete'}})) {                          } else {
                         $resulttext .= '<li>'.&mt('Load Balancing discontinued for: [_1]',$balancer).'</li>';                              &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom);
                         $toupdate{$balancer} = 1;                              $resulttext .= '<li>'.&mt('Dedicated Load Balancer server set to [_1]',$balancer);
                     }                          }
                 }                      } else {
                 if (ref($changes{'add'}) eq 'ARRAY') {                          &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom);
                     foreach my $balancer (sort(@{$changes{'add'}})) {                      }
                         $resulttext .= '<li>'.&mt('Load Balancing enabled for: [_1]',$balancer);                      if (($changes{'targets'}) && ($balancer ne '')) {
                         $toupdate{$balancer} = 1;                          my %offloadstr;
                     }                          foreach my $sparetype (@sparestypes) {
                 }                              if (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') {
                 if (ref($changes{'curr'}) eq 'HASH') {                                  if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) {
                     foreach my $balancer (sort(keys(%{$changes{'curr'}}))) {                                      $offloadstr{$sparetype} = join(', ',@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}});
                         $toupdate{$balancer} = 1;  
                         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 (keys(%offloadstr) == 0) {
                             if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) {                              $resulttext .= '<li>'.&mt("Servers to which Load Balance server offloads set to 'None', by default").'</li>';
                                 foreach my $type (@{$alltypes}) {                          } else {
                                     if ($changes{'curr'}{$balancer}{'rules'}{$type}) {                              my $showoffload;
                                         my $rule = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type};                              foreach my $sparetype (@sparestypes) {
                                         my $balancetext;                                  $showoffload .= '<i>'.$typetitles{$sparetype}.'</i>:&nbsp;';
                                         if ($rule eq '') {                                  if (defined($offloadstr{$sparetype})) {
                                             $balancetext =  $ruletitles{'default'};                                      $showoffload .= $offloadstr{$sparetype};
                                         } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer') ||                                  } else {
                                                  ($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) {                                      $showoffload .= &mt('None');
                                             if (($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) {  
                                                 foreach my $sparetype (@sparestypes) {  
                                                     if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {  
                                                         map { $toupdate{$_} = 1; } (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}});  
                                                     }  
                                                 }  
                                                 foreach my $item (@{$alltypes}) {  
                                                     next if ($item =~  /^_LC_ipchange/);  
                                                     my $hasrule = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$item};  
                                                     if ($hasrule eq 'homeserver') {  
                                                         map { $toupdate{$_} = 1; } (keys(%libraryservers));  
                                                     } else {  
                                                         unless (($hasrule eq 'default') || ($hasrule eq 'none') || ($hasrule eq 'externalbalancer')) {  
                                                             if ($servers{$hasrule}) {  
                                                                 $toupdate{$hasrule} = 1;  
                                                             }  
                                                         }  
                                                     }  
                                                 }  
                                                 if (($rule eq 'balancer') || ($rule eq 'offloadedto')) {  
                                                     $balancetext =  $ruletitles{$rule};  
                                                 } else {  
                                                     my $receiver = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type};  
                                                     $balancetext = $ruletitles{'particular'}.' '.$receiver;  
                                                     if ($receiver) {  
                                                         $toupdate{$receiver};  
                                                     }  
                                                 }  
                                             } else {  
                                                 $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>';  
                                     }  
                                 }                                  }
                                   $showoffload .= ('&nbsp;'x3);
                             }                              }
                               $resulttext .= '<li>'.&mt('By default, Load Balancer server set to offload to: [_1]',$showoffload).'</li>';
                         }                          }
                         if ($changes{'curr'}{$balancer}{'cookie'}) {                      }
                             $resulttext .= '<li>'.&mt('Load Balancer: [_1] -- cookie use enabled',                      if ((ref($changes{'rules'}) eq 'HASH') && ($balancer ne '')) {
                                                       $balancer).'</li>';                          if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) {
                         }                              foreach my $type (@{$alltypes}) {
                         if (keys(%toupdate)) {                                  if ($changes{'rules'}{$type}) {
                             my %thismachine;                                      my $rule = $defaultshash{'loadbalancing'}{'rules'}{$type};
                             my $updatedhere;                                      my $balancetext;
                             my $cachetime = 60*60*24;                                      if ($rule eq '') {
                             map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();                                          $balancetext =  $ruletitles{'default'};
                             foreach my $lonhost (keys(%toupdate)) {                                      } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer')) {
                                 if ($thismachine{$lonhost}) {                                          $balancetext =  $ruletitles{$rule};
                                     unless ($updatedhere) {                                      } else {
                                         &Apache::lonnet::do_cache_new('loadbalancing',$dom,                                          $balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{'rules'}{$type});
                                                                       $defaultshash{'loadbalancing'},  
                                                                       $cachetime);  
                                         $updatedhere = 1;  
                                     }                                      }
                                 } else {                                      $resulttext .= '<li>'.&mt('Load Balancing for [_1] set to: [_2]',$titles->{$type},$balancetext).'</li>';     
                                     my $cachekey = &escape('loadbalancing').':'.&escape($dom);  
                                     &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);  
                                 }                                  }
                             }                              }
                         }                          }
                     }                      }
                 }                      if ($resulttext ne '') {
                 if ($resulttext ne '') {                          $resulttext = &mt('Changes made:').'<ul>'.$resulttext.'</ul>';
                     $resulttext = &mt('Changes made:').'<ul>'.$resulttext.'</ul>';                      } else {
                           $resulttext = $nochgmsg;
                       }
                 } else {                  } else {
                     $resulttext = $nochgmsg;                      $resulttext = $nochgmsg;
                       if ($balancer ne '') {
                           &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom);
                       }
                 }                  }
             } else {              } else {
                 $resulttext = $nochgmsg;                  $resulttext = '<span class="LC_error">'.
                                 &mt('An error occurred: [_1]',$putresult).'</span>';
             }              }
         } else {          } else {
             $resulttext = '<span class="LC_error">'.              $resulttext = $nochgmsg;
                           &mt('An error occurred: [_1]',$putresult).'</span>';  
         }          }
     } else {      } else {
         $resulttext = $nochgmsg;          $resulttext =  &mt('Load Balancing unavailable as this domain only has one server.');
     }      }
     return $resulttext;      return $resulttext;
 }  }
Line 15157  sub recurse_cat_deletes { Line 7857  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 active_dc_picker {  sub get_active_dcs {
     my ($dom,$numinrow,$inputtype,$name,%currhash) = @_;      my ($dom) = @_;
     my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);      my %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc']);
     my @domcoord = keys(%domcoords);      my %domcoords;
     if (keys(%currhash)) {      my $numdcs = 0;
         foreach my $dc (keys(%currhash)) {      my $now = time;
             unless (exists($domcoords{$dc})) {      foreach my $server (keys(%dompersonnel)) {
                 push(@domcoord,$dc);          foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {
               my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user);
               my ($end,$start) = split(':',$dompersonnel{$server}{$user});
               if (($end eq '') || ($end == 0) || ($end > $now)) {
                   if ($start <= $now) {
                       $domcoords{$uname.':'.$udom} = $dompersonnel{$server}{$user};
                   }
             }              }
         }          }
     }      }
     @domcoord = sort(@domcoord);      return %domcoords;
     my $numdcs = scalar(@domcoord);  }
     my $rows = 0;  
     my $table;  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) {      if ($numdcs > 1) {
         $table = '<table>';          $datatable = '<table>';
         for (my $i=0; $i<@domcoord; $i++) {          for (my $i=0; $i<@dcs; $i++) {
             my $rem = $i%($numinrow);              my $rem = $i%($numinrow);
             if ($rem == 0) {              if ($rem == 0) {
                 if ($i > 0) {                  if ($i > 0) {
                     $table .= '</tr>';                      $datatable .= '</tr>';
                 }                  }
                 $table .= '<tr>';                  $datatable .= '<tr>';
                 $rows ++;  
             }              }
             my $check = '';              my $check = ' ';
             if ($inputtype eq 'radio') {              if ($curr_dc eq '') {
                 if (keys(%currhash) == 0) {                  if (!$i) { 
                     if (!$i) {                      $check = ' checked="checked" ';
                         $check = ' checked="checked"';  
                     }  
                 } elsif (exists($currhash{$domcoord[$i]})) {  
                     $check = ' checked="checked"';  
                 }  
             } else {  
                 if (exists($currhash{$domcoord[$i]})) {  
                     $check = ' checked="checked"';  
                 }                  }
               } elsif ($dcs[$i] eq $curr_dc) {
                   $check = ' checked="checked" ';
             }              }
             if ($i == @domcoord - 1) {              if ($i == @dcs - 1) {
                 my $colsleft = $numinrow - $rem;                  my $colsleft = $numinrow - $rem;
                 if ($colsleft > 1) {                  if ($colsleft > 1) {
                     $table .= '<td class="LC_left_item" colspan="'.$colsleft.'">';                      $datatable .= '<td colspan="'.$colsleft.'">';
                 } else {                  } else {
                     $table .= '<td class="LC_left_item">';                      $datatable .= '<td>';
                 }                  }
             } else {              } else {
                 $table .= '<td class="LC_left_item">';                  $datatable .= '<td>';
             }  
             my ($dcname,$dcdom) = split(':',$domcoord[$i]);  
             my $user = &Apache::loncommon::plainname($dcname,$dcdom);  
             $table .= '<span class="LC_nobreak"><label>'.  
                       '<input type="'.$inputtype.'" name="'.$name.'"'.  
                       ' value="'.$domcoord[$i].'"'.$check.' />'.$user;  
             if ($user ne $dcname.':'.$dcdom) {  
                 $table .=  ' ('.$dcname.':'.$dcdom.')';  
             }  
             $table .= '</label></span></td>';  
         }  
         $table .= '</tr></table>';  
     } elsif ($numdcs == 1) {  
         my ($dcname,$dcdom) = split(':',$domcoord[0]);  
         my $user = &Apache::loncommon::plainname($dcname,$dcdom);  
         if ($inputtype eq 'radio') {  
             $table = '<input type="hidden" name="'.$name.'" value="'.$domcoord[0].'" />'.$user;  
             if ($user ne $dcname.':'.$dcdom) {  
                 $table .=  ' ('.$dcname.':'.$dcdom.')';  
             }  
         } else {  
             my $check;  
             if (exists($currhash{$domcoord[0]})) {  
                 $check = ' checked="checked"';  
             }  
             $table = '<span class="LC_nobreak"><label>'.  
                      '<input type="checkbox" name="'.$name.'" '.  
                      'value="'.$domcoord[0].'"'.$check.' />'.$user;  
             if ($user ne $dcname.':'.$dcdom) {  
                 $table .=  ' ('.$dcname.':'.$dcdom.')';  
             }              }
             $table .= '</label></span>';              my ($dcname,$dcdom) = split(':',$dcs[$i]);
             $rows ++;              $datatable .= '<span class="LC_nobreak"><label>'.
                             '<input type="radio" name="autocreate_xmldc"'.
                             ' value="'.$dcs[$i].'"'.$check.'/>'.
                             &Apache::loncommon::plainname($dcname,$dcdom).
                             '</label></span></td>';
         }          }
           $datatable .= '</tr></table>';
       } elsif (@dcs) {
           $datatable .= '<input type="hidden" name="autocreate_dc" value="'.
                         $dcs[0].'" />';
     }      }
     return ($numdcs,$table,$rows);      return ($numdcs,$datatable);
 }  }
   
 sub usersession_titles {  sub usersession_titles {
Line 15291  sub count_servers { Line 7974  sub count_servers {
 }  }
   
 sub lonbalance_targets_js {  sub lonbalance_targets_js {
     my ($dom,$types,$servers,$settings) = @_;      my ($dom,$types,$servers) = @_;
     my $select = &mt('Select');      my $select = &mt('Select');
     my ($alltargets,$allishome,$allinsttypes,@alltypes);      my ($alltargets,$allishome,$allinsttypes,@alltypes);
     if (ref($servers) eq 'HASH') {      if (ref($servers) eq 'HASH') {
Line 15313  sub lonbalance_targets_js { Line 7996  sub lonbalance_targets_js {
     }      }
     push(@alltypes,'default','_LC_adv','_LC_author','_LC_internetdom','_LC_external');      push(@alltypes,'default','_LC_adv','_LC_author','_LC_internetdom','_LC_external');
     $allinsttypes = join("','",@alltypes);      $allinsttypes = join("','",@alltypes);
     my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);  
     if (ref($settings) eq 'HASH') {  
         %existing = %{$settings};  
     }  
     &get_loadbalancers_config($servers,\%existing,\%currbalancer,  
                               \%currtargets,\%currrules,\%currcookies);  
     my $balancers = join("','",sort(keys(%currbalancer)));  
     return <<"END";      return <<"END";
   
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
   
 currBalancers = new Array('$balancers');  function toggleTargets() {
       var balancer = document.display.loadbalancing_lonhost.options[document.display.loadbalancing_lonhost.selectedIndex].value;
 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 == '') {      if (balancer == '') {
         hideSpares(balnum);          hideSpares();
     } else {      } else {
         var currIdx = currBalancers.indexOf(balancer);  
         if (currIdx == -1) {  
             currBalancers.push(balancer);  
         }  
         var homedoms = new Array('$allishome');          var homedoms = new Array('$allishome');
         var ishomedom = homedoms[lonhostitem.selectedIndex];          var ishomedom = homedoms[document.display.loadbalancing_lonhost.selectedIndex];
         showSpares(balancer,ishomedom,balnum);          showSpares(balancer,ishomedom);
     }      }
     balancerChange(balnum,baltotal,'change',prevbalancer,balancer);  
     return;      return;
 }  }
   
 function showSpares(balancer,ishomedom,balnum) {  function showSpares(balancer,ishomedom) {
     var alltargets = new Array('$alltargets');      var alltargets = new Array('$alltargets');
     var insttypes = new Array('$allinsttypes');      var insttypes = new Array('$allinsttypes');
     var offloadtypes = new Array('primary','default');      var offloadtypes = new Array('primary','default');
   
     document.getElementById('loadbalancing_targets_'+balnum).style.display='block';      document.getElementById('loadbalancing_targets').style.display='block';
     document.getElementById('loadbalancing_disabled_'+balnum).style.display='none';      document.getElementById('loadbalancing_disabled').style.display='none';
     
     for (var i=0; i<offloadtypes.length; i++) {      for (var i=0; i<offloadtypes.length; i++) {
         var count = 0;          var count = 0;
         for (var j=0; j<alltargets.length; j++) {          for (var j=0; j<alltargets.length; j++) {
             if (alltargets[j] != balancer) {              if (alltargets[j] != balancer) {
                 var item = document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+count);                  document.getElementById('loadbalancing_target_'+offloadtypes[i]+'_'+count).value = alltargets[j];
                 item.value = alltargets[j];                  document.getElementById('loadbalancing_targettxt_'+offloadtypes[i]+'_'+count).style.textAlign='left';
                 item.style.textAlign='left';                  document.getElementById('loadbalancing_targettxt_'+offloadtypes[i]+'_'+count).style.textFace='normal';
                 item.style.textFace='normal';                  document.getElementById('loadbalancing_targettxt_'+offloadtypes[i]+'_'+count).innerHTML = alltargets[j];
                 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 ++;                  count ++;
             }              }
         }          }
Line 15385  function showSpares(balancer,ishomedom,b Line 8036  function showSpares(balancer,ishomedom,b
     for (var k=0; k<insttypes.length; k++) {      for (var k=0; k<insttypes.length; k++) {
         if ((insttypes[k] == '_LC_external') || (insttypes[k] == '_LC_internetdom')) {          if ((insttypes[k] == '_LC_external') || (insttypes[k] == '_LC_internetdom')) {
             if (ishomedom == 1) {              if (ishomedom == 1) {
                 document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='block';                  document.getElementById('balanceruletitle_'+insttypes[k]).style.display='block';
                 document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='block';                  document.getElementById('balancerule_'+insttypes[k]).style.display='block';
             } else {              } else {
                 document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='none';                  document.getElementById('balanceruletitle_'+insttypes[k]).style.display='none';
                 document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='none';                  document.getElementById('balancerule_'+insttypes[k]).style.display='none';
   
             }              }
         } else {          } else {
             document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='block';              document.getElementById('balanceruletitle_'+insttypes[k]).style.display='block';
             document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='block';              document.getElementById('balancerule_'+insttypes[k]).style.display='block';
         }          }
         if ((insttypes[k] != '_LC_external') &&           if ((insttypes[k] != '_LC_external') && 
             ((insttypes[k] != '_LC_internetdom') ||              ((insttypes[k] != '_LC_internetdom') ||
              ((insttypes[k] == '_LC_internetdom') && (ishomedom == 1)))) {               ((insttypes[k] == '_LC_internetdom') && (ishomedom == 1)))) {
             var item = document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]);              document.getElementById('loadbalancing_singleserver_'+insttypes[k]).options[0] = new Option("","",true,true);
             item.options.length = 0;  
             item.options[0] = new Option("","",true,true);  
             var idx = 0;  
             for (var m=0; m<alltargets.length; m++) {              for (var m=0; m<alltargets.length; m++) {
                 if ((currBalancers.indexOf(alltargets[m]) == -1) && (alltargets[m] != balancer)) {                  var idx = m+1;
                     idx ++;                  if (alltargets[m] != balancer) {
                     item.options[idx] = new Option(alltargets[m],alltargets[m],false,false);                      document.getElementById('loadbalancing_singleserver_'+insttypes[k]).options[idx] = new Option(alltargets[m],alltargets[m],false,false);
                 }                  }
             }              }
         }          }
Line 15413  function showSpares(balancer,ishomedom,b Line 8062  function showSpares(balancer,ishomedom,b
     return;      return;
 }  }
   
 function hideSpares(balnum) {  function hideSpares() {
     var alltargets = new Array('$alltargets');      var alltargets = new Array('$alltargets');
     var insttypes = new Array('$allinsttypes');      var insttypes = new Array('$allinsttypes');
     var offloadtypes = new Array('primary','default');      var offloadtypes = new Array('primary','default');
   
     document.getElementById('loadbalancing_targets_'+balnum).style.display='none';      document.getElementById('loadbalancing_targets').style.display='none';
     document.getElementById('loadbalancing_disabled_'+balnum).style.display='block';      document.getElementById('loadbalancing_disabled').style.display='block';
   
     var total = alltargets.length - 1;      var total = alltargets.length - 1;
     for (var i=0; i<offloadtypes; i++) {      for (var i=0; i<offloadtypes; i++) {
         for (var j=0; j<total; j++) {          for (var j=0; j<total; j++) {
            document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+j).checked = false;             document.getElementById('loadbalancing_target_'+offloadtypes[i]+'_'+j).checked = false;
            document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+j).value = '';             document.getElementById('loadbalancing_target_'+offloadtypes[i]+'_'+j).value = '';
            document.getElementById('loadbalancing_targettxt_'+balnum+'_'+offloadtypes[i]+'_'+j).innerHTML = '';             document.getElementById('loadbalancing_targettxt_'+offloadtypes[i]+'_'+j).innerHTML = '';
         }          }
     }      }
     for (var k=0; k<insttypes.length; k++) {      for (var k=0; k<insttypes.length; k++) {
         document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='none';          document.getElementById('balanceruletitle_'+insttypes[k]).style.display='none';
         document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='none';          document.getElementById('balancerule_'+insttypes[k]).style.display='none';
         if (insttypes[k] != '_LC_external') {          if (insttypes[k] != '_LC_external') {
             document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]).length = 0;              document.getElementById('loadbalancing_singleserver_'+insttypes[k]).length = 0;
             document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]).options[0] = new Option("","",true,true);              document.getElementById('loadbalancing_singleserver_'+insttypes[k]).options[0] = new Option("","",true,true);
         }          }
     }      }
     return;      return;
 }  }
   
 function checkOffloads(item,balnum,type) {  function checkOffloads(item,type) {
     var alltargets = new Array('$alltargets');      var alltargets = new Array('$alltargets');
     var offloadtypes = new Array('primary','default');      var offloadtypes = new Array('primary','default');
     if (item.checked) {      if (item.checked) {
Line 15452  function checkOffloads(item,balnum,type) Line 8101  function checkOffloads(item,balnum,type)
             other = offloadtypes[0];              other = offloadtypes[0];
         }          }
         for (var i=0; i<total; i++) {          for (var i=0; i<total; i++) {
             var server = document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).value;              var server = document.getElementById('loadbalancing_target_'+other+'_'+i).value;
             if (server == item.value) {              if (server == item.value) {
                 if (document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).checked) {                  if (document.getElementById('loadbalancing_target_'+other+'_'+i).checked) {
                     document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).checked = false;                      document.getElementById('loadbalancing_target_'+other+'_'+i).checked = false;
                 }                  }
             }              }
         }          }
Line 15463  function checkOffloads(item,balnum,type) Line 8112  function checkOffloads(item,balnum,type)
     return;      return;
 }  }
   
 function singleServerToggle(balnum,type) {  function singleServerToggle(type) {
     var offloadtoSelIdx = document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).selectedIndex;      var offloadtoSelIdx = document.getElementById('loadbalancing_singleserver_'+type).selectedIndex;
     if (offloadtoSelIdx == 0) {      if (offloadtoSelIdx == 0) {
         document.getElementById('loadbalancing_rules_'+balnum+'_'+type+'_0').checked = true;          document.getElementById('loadbalancing_rules_'+type+'_0').checked = true;
         document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '';          document.getElementById('loadbalancing_singleserver_'+type).options[0].text = '';
   
     } else {      } else {
         document.getElementById('loadbalancing_rules_'+balnum+'_'+type+'_2').checked = true;          document.getElementById('loadbalancing_rules_'+type+'_2').checked = true;
         document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '$select';          document.getElementById('loadbalancing_singleserver_'+type).options[0].text = '$select';
     }      }
     return;      return;
 }  }
   
 function balanceruleChange(formname,balnum,type) {  function balanceruleChange(formname,type) {
     if (type == '_LC_external') {      if (type == '_LC_external') {
         return;          return; 
     }      }
     var typesRules = getIndicesByName(formname,'loadbalancing_rules_'+balnum+'_'+type);      var typesRules = getIndicesByName(formname,'loadbalancing_rules_'+type);
     for (var i=0; i<typesRules.length; i++) {      for (var i=0; i<typesRules.length; i++) {
         if (formname.elements[typesRules[i]].checked) {          if (formname.elements[typesRules[i]].checked) {
             if (formname.elements[typesRules[i]].value != 'specific') {              if (formname.elements[typesRules[i]].value != 'specific') {
                 document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).selectedIndex = 0;                  document.getElementById('loadbalancing_singleserver_'+type).selectedIndex = 0;
                 document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '';                  document.getElementById('loadbalancing_singleserver_'+type).options[0].text = '';
             } else {              } else {
                 document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '$select';                  document.getElementById('loadbalancing_singleserver_'+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);  
                                         }  
                                     }  
                                 }  
                             }  
                         }  
                     }  
                 }  
             }              }
         }          }
     }      }
Line 15717  END Line 8268  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;  
     var versionitem;  
     var versiontext;  
     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 (document.getElementById(context+'_recaptchaversion')) {  
         versionitem = document.getElementById(context+'_recaptchaversion');  
     } else {  
         return;  
     }  
     if (document.getElementById(context+'_recaptchavertxt')) {  
         versiontext = document.getElementById(context+'_recaptchavertxt');  
     } 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'}";  
             versionitem.type = 'text';  
             versionitem.size = '3';  
             versiontext.innerHTML = "$lt{'ver'}";  
         } else {  
             pubitem.type = 'hidden';  
             privitem.type = 'hidden';  
             versionitem.type = 'hidden';  
             pubtext.innerHTML = '';  
             privtext.innerHTML = '';  
             versiontext.innerHTML = '';  
         }  
     }  
     return;  
 }  
   
 // ]]>  
 </script>  
   
 END  
   
 }  
   
 sub toggle_display_js {  
     return <<"END";  
   
 <script type="text/javascript">  
 // <![CDATA[  
   
 function toggleDisplay(domForm,caller) {  
     if (document.getElementById(caller)) {  
         var divitem = document.getElementById(caller);  
         var optionsElement = domForm.coursecredits;  
         var checkval = 1;  
         var dispval = 'block';  
         var selfcreateRegExp = /^cancreate_emailverified/;  
         if (caller == 'emailoptions') {  
             optionsElement = domForm.cancreate_email;   
         }  
         if (caller == 'studentsubmission') {  
             optionsElement = domForm.postsubmit;  
         }  
         if (caller == 'cloneinstcode') {  
             optionsElement = domForm.canclone;  
             checkval = 'instcode';  
         }  
         if (selfcreateRegExp.test(caller)) {  
             optionsElement = domForm.elements[caller];  
             checkval = 'other';  
             dispval = 'inline'  
         }  
         if (optionsElement.length) {  
             var currval;  
             for (var i=0; i<optionsElement.length; i++) {  
                 if (optionsElement[i].checked) {  
                    currval = optionsElement[i].value;  
                 }  
             }  
             if (currval == checkval) {  
                 divitem.style.display = dispval;  
             } else {  
                 divitem.style.display = 'none';  
             }  
         }  
     }  
     return;  
 }  
   
 // ]]>  
 </script>  
   
 END  
   
 }  
   
 sub captcha_phrases {  
     return &Apache::lonlocal::texthash (  
                  priv => 'Private key',  
                  pub  => 'Public key',  
                  original  => 'original (CAPTCHA)',  
                  recaptcha => 'successor (ReCAPTCHA)',  
                  notused   => 'unused',  
                  ver => 'ReCAPTCHA version (1 or 2)',  
     );  
 }  
   
 sub devalidate_remote_domconfs {  
     my ($dom,$cachekeys) = @_;  
     return unless (ref($cachekeys) eq 'HASH');  
     my %servers = &Apache::lonnet::internet_dom_servers($dom);  
     my %thismachine;  
     map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();  
     my @posscached = ('domainconfig','domdefaults','usersessions',  
                       'directorysrch','passwdconf','cats');  
     if (keys(%servers)) {  
         foreach my $server (keys(%servers)) {  
             next if ($thismachine{$server});  
             my @cached;  
             foreach my $name (@posscached) {  
                 if ($cachekeys->{$name}) {  
                     push(@cached,&escape($name).':'.&escape($dom));  
                 }  
             }  
             if (@cached) {  
                 &Apache::lonnet::remote_devalidate_cache($server,\@cached);  
             }  
         }  
     }  
     return;  
 }  
   
 1;  1;

Removed from v.1.160.6.105  
changed lines
  Added in v.1.162


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