Diff for /loncom/interface/domainprefs.pm between versions 1.160.6.106 and 1.294

version 1.160.6.106, 2021/01/01 15:33:55 version 1.294, 2017/03/13 18:30:07
Line 104  $datatable  - HTML containing form eleme Line 104  $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, community, textbook, and placement).  
 allow the selection of one of four values:  In each case the radio buttons allow the selection of one of four values:  
   
 0, approval, validate, autolimit=N (where N is blank, or a positive integer).  0, approval, validate, autolimit=N (where N is blank, or a positive integer).
 which have the following effects:  which have the following effects:
Line 170  use Apache::loncoursequeueadmin(); Line 170  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();
   use LONCAPA::SSL;
 use File::Copy;  use File::Copy;
 use Locale::Language;  use Locale::Language;
 use DateTime::TimeZone;  use DateTime::TimeZone;
 use DateTime::Locale;  use DateTime::Locale;
   use Time::HiRes qw( sleep );
   
 my $registered_cleanup;  my $registered_cleanup;
 my $modified_urls;  my $modified_urls;
Line 216  sub handler { Line 218  sub handler {
                 'contacts','defaults','scantron','coursecategories',                  'contacts','defaults','scantron','coursecategories',
                 'serverstatuses','requestcourses','helpsettings',                  'serverstatuses','requestcourses','helpsettings',
                 'coursedefaults','usersessions','loadbalancing',                  'coursedefaults','usersessions','loadbalancing',
                 'requestauthor','selfenrollment','inststatus','passwords'],$dom);                  'requestauthor','selfenrollment','inststatus',
     my @prefs_order = ('rolecolors','login','defaults','passwords','quotas','autoenroll',                  'ltitools','ssl','trust'],$dom);
       my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
                        'autoupdate','autocreate','directorysrch','contacts',                         'autoupdate','autocreate','directorysrch','contacts',
                        'usercreation','selfcreation','usermodification','scantron',                         'usercreation','selfcreation','usermodification','scantron',
                        'requestcourses','requestauthor','coursecategories',                         'requestcourses','requestauthor','coursecategories',
                        'serverstatuses','helpsettings','coursedefaults',                         'serverstatuses','helpsettings','coursedefaults',
                        'selfenrollment','usersessions');                         'ltitools','selfenrollment','usersessions','ssl','trust');
     my %existing;      my %existing;
     if (ref($domconfig{'loadbalancing'}) eq 'HASH') {      if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
         %existing = %{$domconfig{'loadbalancing'}};          %existing = %{$domconfig{'loadbalancing'}};
Line 262  sub handler { Line 265  sub handler {
                       help => 'Domain_Configuration_LangTZAuth',                        help => 'Domain_Configuration_LangTZAuth',
                       header => [{col1 => 'Setting',                        header => [{col1 => 'Setting',
                                   col2 => 'Value'},                                    col2 => 'Value'},
                                    {col1 => 'Internal Authentication',
                                     col2 => 'Value'},
                                  {col1 => 'Institutional user types',                                   {col1 => 'Institutional user types',
                                   col2 => 'Name displayed'}],                                    col2 => 'Assignable to e-mail usernames'}],
                       print => \&print_defaults,                        print => \&print_defaults,
                       modify => \&modify_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/quotas, portfolios',
                       help => 'Domain_Configuration_Quotas',                        help => 'Domain_Configuration_Quotas',
Line 359  sub handler { Line 350  sub handler {
                                 col2 => 'Enabled?'},                                  col2 => 'Enabled?'},
                                {col1 => 'Institutional user type (login/SSO self-creation)',                                 {col1 => 'Institutional user type (login/SSO self-creation)',
                                 col2 => 'Information user can enter'},                                  col2 => 'Information user can enter'},
                                {col1 => 'Self-creation with e-mail verification',                                 {col1 => 'Self-creation with e-mail as username',
                                 col2 => 'Settings'}],                                  col2 => 'Settings'}],
                     print => \&print_selfcreation,                      print => \&print_selfcreation,
                     modify => \&modify_selfcreation,                      modify => \&modify_selfcreation,
Line 375  sub handler { Line 366  sub handler {
                     modify => \&modify_usermodification,                      modify => \&modify_usermodification,
                   },                    },
         '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,                      print => \&print_scantron,
                     modify => \&modify_scantron,                      modify => \&modify_scantron,
                   },                    },
Line 465  sub handler { Line 455  sub handler {
                   print => \&print_selfenrollment,                    print => \&print_selfenrollment,
                   modify => \&modify_selfenrollment,                    modify => \&modify_selfenrollment,
                  },                   },
           'privacy' => 
                    {text   => 'User Privacy',
                     help   => 'Domain_Configuration_User_Privacy',
                     header => [{col1 => 'Setting',
                                 col2 => 'Value',}],
                     print => \&print_privacy,
                     modify => \&modify_privacy,
                    },
         'usersessions' =>          'usersessions' =>
                  {text  => 'User session hosting/offloading',                   {text  => 'User session hosting/offloading',
                   help  => 'Domain_Configuration_User_Sessions',                    help  => 'Domain_Configuration_User_Sessions',
Line 488  sub handler { Line 486  sub handler {
                   print => \&print_loadbalancing,                    print => \&print_loadbalancing,
                   modify => \&modify_loadbalancing,                    modify => \&modify_loadbalancing,
                  },                   },
           'ltitools' => 
                    {text => 'External Tools (LTI)',
                     help => 'Domain_configuration_LTI_Tools',
                     header => [{col1 => 'Setting',
                                 col2 => 'Value',}],
                     print => \&print_ltitools,
                     modify => \&modify_ltitools,
                    },
           'ssl' =>
                    {text  => 'LON-CAPA Network (SSL)',
                     help  => 'Domain_Configuration_Network_SSL',
                     header => [{col1 => 'Server',
                                 col2 => 'Certificate Status'},
                                {col1 => 'Connections to other servers',
                                 col2 => 'Rules'},
                                {col1 => 'Connections from other servers',
                                 col2 => 'Rules'},
                                {col1 => "Replicating domain's published content",
                                 col2 => 'Rules'}],
                     print => \&print_ssl,
                     modify => \&modify_ssl,
                    },
           'trust' =>
                    {text   => 'Trust Settings',
                     help   => 'Domain_Configuration_Trust',
                     header => [{col1 => "Access to this domain's content by others",
                                 col2 => 'Rules'},
                                {col1 => "Access to other domain's content by this domain",
                                 col2 => 'Rules'},
                                {col1 => "Enrollment in this domain's courses by others",
                                 col2 => 'Rules',},
                                {col1 => "Co-author roles in this domain for others",
                                 col2 => 'Rules',},
                                {col1 => "Co-author roles for this domain's users elsewhere",
                                 col2 => 'Rules',},
                                {col1 => "Domain roles in this domain assignable to others",
                                 col2 => 'Rules'},
                                {col1 => "Course catalog for this domain displayed elsewhere",
                                 col2 => 'Rules'},
                                {col1 => "Requests for creation of courses in this domain by others",
                                 col2 => 'Rules'},
                                {col1 => "Users in other domains can send messages to this domain",
                                 col2 => 'Rules'},],
                     print => \&print_trust,
                     modify => \&modify_trust,
                    },
     );      );
     if (keys(%servers) > 1) {      if (keys(%servers) > 1) {
         $prefs{'login'}  = { text   => 'Log-in page options',          $prefs{'login'}  = { text   => 'Log-in page options',
Line 541  $javascript_validations Line 585  $javascript_validations
 $coursebrowserjs  $coursebrowserjs
 END  END
         }          }
         if (grep(/^selfcreation$/,@actions)) {  
             $js .= &selfcreate_javascript();  
         }  
         if (grep(/^contacts$/,@actions)) {          if (grep(/^contacts$/,@actions)) {
             $js .= &contacts_javascript();              $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.  # check if domconfig user exists for the domain.
Line 639  sub process_changes { Line 677  sub process_changes {
     } 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') {      } elsif ($action eq 'selfcreation') {
         $output = &modify_selfcreation($dom,$lastactref,%domconfig);          $output = &modify_selfcreation($dom,%domconfig);
     } elsif ($action eq 'usermodification') {      } elsif ($action eq 'usermodification') {
         $output = &modify_usermodification($dom,%domconfig);          $output = &modify_usermodification($dom,%domconfig);
     } elsif ($action eq 'contacts') {      } elsif ($action eq 'contacts') {
Line 670  sub process_changes { Line 708  sub process_changes {
         $output = &modify_usersessions($dom,$lastactref,%domconfig);          $output = &modify_usersessions($dom,$lastactref,%domconfig);
     } elsif ($action eq 'loadbalancing') {      } elsif ($action eq 'loadbalancing') {
         $output = &modify_loadbalancing($dom,%domconfig);          $output = &modify_loadbalancing($dom,%domconfig);
     } elsif ($action eq 'passwords') {      } elsif ($action eq 'ltitools') {
         $output = &modify_passwords($r,$dom,$confname,$lastactref,%domconfig);          $output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig);
       } elsif ($action eq 'ssl') {
           $output = &modify_ssl($dom,$lastactref,%domconfig);
       } elsif ($action eq 'trust') {
           $output = &modify_trust($dom,$lastactref,%domconfig);
     }      }
     return $output;      return $output;
 }  }
Line 684  sub print_config_box { Line 726  sub print_config_box {
         $output = &coursecategories_javascript($settings);          $output = &coursecategories_javascript($settings);
     } elsif ($action eq 'defaults') {      } elsif ($action eq 'defaults') {
         $output = &defaults_javascript($settings);           $output = &defaults_javascript($settings); 
     } elsif ($action eq 'passwords') {  
         $output = &passwords_javascript();  
     } elsif ($action eq 'helpsettings') {      } elsif ($action eq 'helpsettings') {
         my (%privs,%levelscurrent);          my (%privs,%levelscurrent);
         my %full=();          my %full=();
Line 700  sub print_config_box { Line 740  sub print_config_box {
         &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);          &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
         my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);          my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
         $output =          $output =
             &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full,              &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full, 
                                                       \@templateroles);                                                        \@templateroles);
     }      }
     $output .=      $output .=
Line 718  sub print_config_box { Line 758  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 'defaults') ||          if (($action eq 'rolecolors') || ($action eq 'defaults') ||
             ($action eq 'directorysrch') ||              ($action eq 'directorysrch') ||
             (($action eq 'login') && ($numheaders < 4))) {              (($action eq 'login') && ($numheaders < 4))) {
Line 727  sub print_config_box { Line 766  sub print_config_box {
         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 'usercreation') || ($action eq 'selfcreation') ||
             ($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') ||              ($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') ||
             ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'directorysrch') ||              ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'ssl') ||
             ($action eq 'helpsettings') || ($action eq 'contacts')) {              ($action eq 'directorysrch') || ($action eq 'trust') || ($action eq 'helpsettings') ||
               ($action eq 'contacts')) {
             $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);              $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'passwords') {  
             $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 .= $item->{'print'}->('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) {              if ($numheaders == 4) {
                 $colspan = ' colspan="2"';                  $colspan = ' colspan="2"';
Line 776  sub print_config_box { Line 809  sub print_config_box {
             $rowtotal ++;              $rowtotal ++;
         if (($action eq 'autoupdate') || ($action eq 'usercreation') ||          if (($action eq 'autoupdate') || ($action eq 'usercreation') ||
             ($action eq 'selfcreation') || ($action eq 'selfenrollment') ||              ($action eq 'selfcreation') || ($action eq 'selfenrollment') ||
             ($action eq 'usersessions') || ($action eq 'coursecategories') ||              ($action eq 'usersessions') || ($action eq 'coursecategories') || 
             ($action eq 'contacts') || ($action eq 'passwords')) {              ($action eq 'trust') || ($action eq 'contacts') || ($action eq 'defaults')) {
             if ($action eq 'coursecategories') {              if ($action eq 'coursecategories') {
                 $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);                  $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);
                 $colspan = ' colspan="2"';                  $colspan = ' colspan="2"';
             } elsif ($action eq 'passwords') {              } elsif ($action eq 'trust') {
                 $output .= $item->{'print'}->('middle',$dom,$confname,$settings,\$rowtotal);                  $output .= $item->{'print'}->('shared',$dom,$settings,\$rowtotal);
             } else {              } else {
                 $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);                  $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);
             }              }
             $output .= '              if ($action eq 'trust') {
            </table>                  $output .= '
               </table>
           </td>            </td>
          </tr>           </tr>';
                   my @trusthdrs = qw(2 3 4 5 6 7);
                   my @prefixes = qw(enroll othcoau coaurem domroles catalog reqcrs);
                   for (my $i=0; $i<@trusthdrs; $i++) {
                       $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'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[$trusthdrs[$i]]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>                <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[$trusthdrs[$i]]->{'col2'}).'</td></tr>'.
              </tr>'."\n";                             $item->{'print'}->($prefixes[$i],$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>              </table>
            </td>            </td>
           </tr>           </tr>';
           <tr>                  }
                   $output .= '
            <tr>
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[8]->{'col1'}).'</td>
               <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td></tr>'."\n".                <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[8]->{'col2'}).'</td></tr>'.
               $item->{'print'}->('bottom',$dom,$confname,$settings,\$rowtotal).'                             $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
             </table>              } else {
                   $output .= '
              </table>
           </td>            </td>
          </tr>           </tr>
          <tr>';           <tr>
             } else {             <td>
                 $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);              <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
                 <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
                </tr>'."\n";
                   if ($action eq 'coursecategories') {
                       $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
                   } else {
                       $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
                   }
             }              }
             $rowtotal ++;              $rowtotal ++;
         } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||          } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||
                  ($action eq 'defaults') || ($action eq 'directorysrch') ||                   ($action eq 'defaults') || ($action eq 'directorysrch') ||
                  ($action eq 'helpsettings')) {                   ($action eq 'helpsettings')) {
             $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);              $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'scantron') {          } elsif ($action eq 'ssl') {
             $output .= $item->{'print'}->($r,'bottom',$dom,$confname,$settings,\$rowtotal);              $output .= $item->{'print'}->('connto',$dom,$settings,\$rowtotal).'
               </table>
             </td>
            </tr>
            <tr>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
                 <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td></tr>'.
                              $item->{'print'}->('connfrom',$dom,$settings,\$rowtotal).'
               </table>
             </td>
            </tr>
            <tr>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
                 <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td></tr>'.
                              $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'login') {          } elsif ($action eq 'login') {
             if ($numheaders == 4) {              if ($numheaders == 4) {
                 $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'                  $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'
Line 982  sub print_config_box { Line 1048  sub print_config_box {
         if ($action eq 'quotas') {          if ($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 'autocreate') || 
                  ($action eq 'serverstatuses') || ($action eq 'loadbalancing')) {                   ($action eq 'serverstatuses') || ($action eq 'loadbalancing') || 
                    ($action eq 'ltitools')) {
             $output .= $item->{'print'}->($dom,$settings,\$rowtotal);              $output .= $item->{'print'}->($dom,$settings,\$rowtotal);
           } elsif ($action eq 'scantron') {
               $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);
         }          }
     }      }
     $output .= '      $output .= '
Line 1328  sub print_login { Line 1397  sub print_login {
             } else {              } else {
                 $datatable .= '<input type="file" name="loginheadtag_'.$lonhost.'" />';                  $datatable .= '<input type="file" name="loginheadtag_'.$lonhost.'" />';
             }              }
             $datatable .= '</td><td><input type="text" name="loginheadtagexempt_'.$lonhost.'" value="'.$exempt.'" /></td></tr>';              $datatable .= '</td><td><input type="textbox" name="loginheadtagexempt_'.$lonhost.'" value="'.$exempt.'" /></td></tr>';
         }          }
         $datatable .= '</table></td></tr>';          $datatable .= '</table></td></tr>';
     }      }
Line 1488  sub display_color_options { Line 1557  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>';
     }      }
Line 1497  sub display_color_options { Line 1566  sub display_color_options {
     $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" class="colorchooser" size="10" name="'.$role.'_font"'.
                   ' value="'.$current_color.'" />&nbsp;'.                    ' value="'.$current_color.'" />&nbsp;'.
                   '&nbsp;</span></td></tr>';                    '&nbsp;</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>';
         }          }
Line 1512  sub display_color_options { Line 1581  sub display_color_options {
                       '<input class="colorchooser" type="text" size="10" name="'                        '<input class="colorchooser" type="text" size="10" name="'
       .$role.'_fontmenu"'.        .$role.'_fontmenu"'.
                       ' value="'.$current_color.'" />&nbsp;'.                        ' value="'.$current_color.'" />&nbsp;'.
                       '&nbsp;</span></td></tr>';                        '&nbsp;</td></tr>';
     }      }
     my $switchserver = &check_switchserver($dom,$confname);      my $switchserver = &check_switchserver($dom,$confname);
     foreach my $img (@{$images}) {      foreach my $img (@{$images}) {
Line 1571  sub display_color_options { Line 1640  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 1630  sub display_color_options { Line 1698  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 1658  sub display_color_options { Line 1726  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 1744  sub image_changes { Line 1812  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 1783  sub print_quotas { Line 1853  sub print_quotas {
     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','textbook','placement');
         @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();
Line 2196  sub print_quotas { Line 2266  sub print_quotas {
 }  }
   
 sub print_requestmail {  sub print_requestmail {
     my ($dom,$action,$settings,$rowtotal,$customcss,$rowstyle) = @_;      my ($dom,$action,$settings,$rowtotal) = @_;
     my ($now,$datatable,%currapp);      my ($now,$datatable,%currapp);
     $now = time;      $now = time;
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
Line 2208  sub print_requestmail { Line 2278  sub print_requestmail {
     }      }
     my $numinrow = 2;      my $numinrow = 2;
     my $css_class;      my $css_class;
     if ($$rowtotal%2) {      $css_class = ($$rowtotal%2? ' class="LC_odd_row"':'');
         $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;      my $text;
     if ($action eq 'requestcourses') {      if ($action eq 'requestcourses') {
         $text = &mt('Receive notification of course requests requiring approval');          $text = &mt('Receive notification of course requests requiring approval');
Line 2247  sub print_studentcode { Line 2305  sub print_studentcode {
     my ($settings,$rowtotal) = @_;      my ($settings,$rowtotal) = @_;
     my $rownum = 0;       my $rownum = 0; 
     my ($output,%current);      my ($output,%current);
     my @crstypes = ('official','unofficial','community','textbook');      my @crstypes = ('official','unofficial','community','textbook','placement');
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{'uniquecode'}) eq 'HASH') {          if (ref($settings->{'uniquecode'}) eq 'HASH') {
             foreach my $type (@crstypes) {              foreach my $type (@crstypes) {
Line 2343  sub print_textbookcourses { Line 2401  sub print_textbookcourses {
                               ('&nbsp;'x2).                                ('&nbsp;'x2).
                               '<span class="LC_nobreak">'.&mt('Thumbnail:');                                '<span class="LC_nobreak">'.&mt('Thumbnail:');
                 if ($image) {                  if ($image) {
                     $datatable .= '<span class="LC_nobreak">'.                      $datatable .= $imgsrc.
                                   $imgsrc.  
                                   '<label><input type="checkbox" name="'.$type.'_image_del"'.                                    '<label><input type="checkbox" name="'.$type.'_image_del"'.
                                   ' value="'.$key.'" />'.&mt('Delete?').'</label></span> '.                                    ' value="'.$key.'" />'.&mt('Delete?').'</label></span> '.
                                   '<span class="LC_nobreak">&nbsp;'.&mt('Replace:').'&nbsp;';                                    '<span class="LC_nobreak">&nbsp;'.&mt('Replace:').'&nbsp;';
Line 2375  sub print_textbookcourses { Line 2432  sub print_textbookcourses {
         $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';          $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
     }      }
     $datatable .= '</select>&nbsp;'."\n".      $datatable .= '</select>&nbsp;'."\n".
                   '<input type="checkbox" name="'.$type.'_addbook" value="1" />'.&mt('Add').'</span></td>'."\n".                    '<input type="checkbox" name="'.$type.'_addbook" value="1" />'.&mt('Add').'</td>'."\n".
                   '<td colspan="2">'.                    '<td colspan="2">'.
                   '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_addbook_subject" value="" /></span> '."\n".                    '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_addbook_subject" value="" /></span> '."\n".
                   ('&nbsp;'x2).                    ('&nbsp;'x2).
Line 2392  sub print_textbookcourses { Line 2449  sub print_textbookcourses {
         } else {          } else {
             $datatable .= '<input type="file" name="'.$type.'_addbook_image" value="" />';              $datatable .= '<input type="file" name="'.$type.'_addbook_image" value="" />';
         }          }
         $datatable .= '</span>'."\n";  
     }      }
     $datatable .= '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.      $datatable .= '</span>'."\n".
                     '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.
                   &Apache::loncommon::select_dom_form($env{'request.role.domain'},$type.'_addbook_cdom').                    &Apache::loncommon::select_dom_form($env{'request.role.domain'},$type.'_addbook_cdom').
                   '<input type="text" size="25" name="'.$type.'_addbook_cnum" value="" />'.                    '<input type="text" size="25" name="'.$type.'_addbook_cnum" value="" />'.
                   &Apache::loncommon::selectcourse_link                    &Apache::loncommon::selectcourse_link
                       ('display',$type.'_addbook_cnum',$type.'_addbook_cdom',undef,undef,undef,'Course').                        ('display',$type.'_addbook_cnum',$type.'_addbook_cdom',undef,undef,undef,'Course');
                   '</span></td>'."\n".                    '</span></td>'."\n".
                   '</tr>'."\n";                    '</tr>'."\n";
     $itemcount ++;      $itemcount ++;
Line 2498  $jstext{'templates'}; Line 2555  $jstext{'templates'};
 ENDSCRIPT  ENDSCRIPT
 }  }
   
   sub ltitools_javascript {
       my ($settings) = @_;
       return unless(ref($settings) eq 'HASH');
       my (%ordered,$total,%jstext);
       $total = 0;
       foreach my $item (keys(%{$settings})) {
           if (ref($settings->{$item}) eq 'HASH') {
               my $num = $settings->{$item}{'order'};
               $ordered{$num} = $item;
           }
       }
       $total = scalar(keys(%{$settings}));
       my @jsarray = ();
       foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
           push(@jsarray,$ordered{$item});
       }
       my $jstext = '    var ltitools = Array('."'".join("','",@jsarray)."'".');'."\n";
       return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   function reorderLTI(form,item) {
       var changedVal;
   $jstext
       var newpos = 'ltitools_add_pos';
       var maxh = 1 + $total;
       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;
       }
       for (var i=0; i<ltitools.length; i++) {
           var elementName = 'ltitools_'+ltitools[i];
           if (elementName != item) {
               if (form.elements[elementName]) {
                   var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
                   current[currVal] = elementName;
               }
           }
       }
       var oldVal;
       for (var j=0; j<maxh; j++) {
           if (current[j] == undefined) {
               oldVal = j;
           }
       }
       if (oldVal < changedVal) {
           for (var k=oldVal+1; k<=changedVal ; k++) {
              var elementName = current[k];
              form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
           }
       } else {
           for (var k=changedVal; k<oldVal; k++) {
               var elementName = current[k];
               form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   ENDSCRIPT
   }
   
 sub print_autoenroll {  sub print_autoenroll {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my $autorun = &Apache::lonnet::auto_run(undef,$dom),      my $autorun = &Apache::lonnet::auto_run(undef,$dom),
Line 2577  sub print_autoenroll { Line 2702  sub print_autoenroll {
                   '<td>'.&mt('Failsafe for no drops when institutional data missing').'</td>'.                    '<td>'.&mt('Failsafe for no drops when institutional data missing').'</td>'.
                   '<td class="LC_right_item"><span class="LC_nobreak">'.                    '<td class="LC_right_item"><span class="LC_nobreak">'.
                   '<input type="text" name="autoenroll_failsafe"'.                    '<input type="text" name="autoenroll_failsafe"'.
                   ' value="'.$failsafe.'" size="4" /></span></td></tr>';                    ' value="'.$failsafe.'" size="4" /></td></tr>';
     $$rowtotal += 4;      $$rowtotal += 4;
     return $datatable;      return $datatable;
 }  }
Line 2626  sub print_autoupdate { Line 2751  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 2769  sub print_directorysrch { Line 2894  sub print_directorysrch {
         if (ref($usertypes) eq 'HASH') {          if (ref($usertypes) eq 'HASH') {
             if (keys(%{$usertypes}) > 0) {              if (keys(%{$usertypes}) > 0) {
                 $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,                  $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,
                                              $numinrow,$othertitle,'cansearch',                                               $numinrow,$othertitle,'cansearch');
                                              $rowtotal);  
                 $cansrchrow = 1;                  $cansrchrow = 1;
             }              }
         }          }
Line 2870  sub print_contacts { Line 2994  sub print_contacts {
         }          }
     } elsif ($position eq 'middle') {      } elsif ($position eq 'middle') {
         @mailings = ('errormail','packagesmail','lonstatusmail','requestsmail',          @mailings = ('errormail','packagesmail','lonstatusmail','requestsmail',
                      'updatesmail','idconflictsmail','hostipmail');                       'updatesmail','idconflictsmail');
         foreach my $type (@mailings) {          foreach my $type (@mailings) {
             $otheremails{$type} = '';              $otheremails{$type} = '';
         }          }
Line 2947  sub print_contacts { Line 3071  sub print_contacts {
             $checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';              $checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';
             $checked{'updatesmail'}{'adminemail'} = ' checked="checked" ';              $checked{'updatesmail'}{'adminemail'} = ' checked="checked" ';
             $checked{'idconflictsmail'}{'adminemail'} = ' checked="checked" ';              $checked{'idconflictsmail'}{'adminemail'} = ' checked="checked" ';
             $checked{'hostipmail'}{'adminemail'} = ' checked="checked" ';  
         } elsif ($position eq 'bottom') {          } elsif ($position eq 'bottom') {
             $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';              $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';
             $checked{'otherdomsmail'}{'supportemail'} = ' checked="checked" ';              $checked{'otherdomsmail'}{'supportemail'} = ' checked="checked" ';
Line 2972  sub print_contacts { Line 3095  sub print_contacts {
                           $to{$item}.'" /></td></tr>';                            $to{$item}.'" /></td></tr>';
             $rownum ++;              $rownum ++;
         }          }
     } elsif ($position eq 'bottom') {      } else {
         $css_class = $rownum%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'>'.  
                       '<td>'.&mt('Extra helpdesk form fields:').'<br />'.  
                       &mt('(e-mail, subject, and description always shown)').  
                       '</td><td class="LC_left_item">';  
         if ((ref($fields) eq 'ARRAY') && (ref($fieldtitles) eq 'HASH') &&  
             (ref($fieldoptions) eq 'HASH') && (ref($possoptions) eq 'HASH')) {  
             $datatable .= '<table><tr><th>'.&mt('Field').'</th><th>'.&mt('Status').'</th></tr>';  
             foreach my $field (@{$fields}) {  
                 $datatable .= '<tr><td>'.$fieldtitles->{$field};  
                 if (($field eq 'screenshot') || ($field eq 'cc')) {  
                     $datatable .= ' '.&mt('(logged-in users)');  
                 }  
                 $datatable .='</td><td>';  
                 my $clickaction;  
                 if ($field eq 'screenshot') {  
                     $clickaction = ' onclick="screenshotSize(this);"';  
                 }  
                 if (ref($possoptions->{$field}) eq 'ARRAY') {  
                     foreach my $option (@{$possoptions->{$field}}) {  
                         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";  
         $rownum ++;  
     }  
     unless ($position eq 'top') {  
         foreach my $type (@mailings) {          foreach my $type (@mailings) {
             $css_class = $rownum%2?' class="LC_odd_row"':'';              $css_class = $rownum%2?' class="LC_odd_row"':'';
             $datatable .= '<tr'.$css_class.'>'.              $datatable .= '<tr'.$css_class.'>'.
Line 3053  sub print_contacts { Line 3129  sub print_contacts {
                               'value="'.$bccemails{$type}.'"  /></fieldset>'.                                'value="'.$bccemails{$type}.'"  /></fieldset>'.
                               '<fieldset><legend>'.&mt('Optional added text').'</legend>'.                                '<fieldset><legend>'.&mt('Optional added text').'</legend>'.
                               &mt('Text automatically added to e-mail:').' '.                                &mt('Text automatically added to e-mail:').' '.
                               '<input type="text" name="'.$type.'_includestr" value="'.$includestr{$type}.'" /><br />'.                                '<input type="text" name="'.$type.'_includestr" value="'.$includestr{$type}.'" /><br >'.
                               '<span class="LC_nobreak">'.&mt('Location:').'&nbsp;'.                                '<span class="LC_nobreak">'.&mt('Location:').'&nbsp;'.
                               '<label><input type="radio" name="'.$type.'_includeloc" value="s"'.$locchecked{'s'}.' />'.&mt('in subject').'</label>'.                                '<label><input type="radio" name="'.$type.'_includeloc" value="s"'.$locchecked{'s'}.' />'.&mt('in subject').'</label>'.
                               ('&nbsp;'x2).                                ('&nbsp;'x2).
Line 3079  sub print_contacts { Line 3155  sub print_contacts {
                                                    \%choices,$rownum);                                                     \%choices,$rownum);
         $datatable .= $reports;          $datatable .= $reports;
     } elsif ($position eq 'bottom') {      } elsif ($position eq 'bottom') {
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);          $css_class = $rownum%2?' class="LC_odd_row"':'';
         my (@posstypes,%usertypeshash);          $datatable .= '<tr'.$css_class.'>'.
         if (ref($types) eq 'ARRAY') {                        '<td>'.&mt('Extra helpdesk form fields:').'<br />'.
             @posstypes = @{$types};                        &mt('(e-mail, subject, and description always shown)').
         }                        '</td><td class="LC_left_item">';
         if (@posstypes) {          if ((ref($fields) eq 'ARRAY') && (ref($fieldtitles) eq 'HASH') &&
             if (ref($usertypes) eq 'HASH') {              (ref($fieldoptions) eq 'HASH') && (ref($possoptions) eq 'HASH')) {
                 %usertypeshash = %{$usertypes};              $datatable .= '<table><tr><th>'.&mt('Field').'</th><th>'.&mt('Status').'</th></tr>';
             }              foreach my $field (@{$fields}) {
             my @overridden;                  $datatable .= '<tr><td>'.$fieldtitles->{$field};
             my $numinrow = 4;                  if (($field eq 'screenshot') || ($field eq 'cc')) {
             if (ref($settings) eq 'HASH') {                      $datatable .= ' '.&mt('(logged-in users)');
                 if (ref($settings->{'overrides'}) eq 'HASH') {                  }
                     foreach my $key (sort(keys(%{$settings->{'overrides'}}))) {                  $datatable .='</td><td>';
                         if (ref($settings->{'overrides'}{$key}) eq 'HASH') {                  my $clickaction;
                             push(@overridden,$key);                  if ($field eq 'screenshot') {
                             foreach my $item (@contacts) {                      $clickaction = ' onclick="screenshotSize(this);"';
                                 if ($settings->{'overrides'}{$key}{$item}) {                  }
                                     $checked{'override_'.$key}{$item} = ' checked="checked" ';                  if (ref($possoptions->{$field}) eq 'ARRAY') {
                                 }                      foreach my $option (@{$possoptions->{$field}}) {
                             }                          my $checked;
                             $otheremails{'override_'.$key} = $settings->{'overrides'}{$key}{'others'};                          if ($currfield{$field} eq $option) {
                             $bccemails{'override_'.$key} = $settings->{'overrides'}{$key}{'bcc'};                              $checked = ' checked="checked"';
                             $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});  
                             }  
                         }                          }
                           $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 $customclass = 'LC_helpdesk_override';                      my $display;
             my $optionsprefix = 'LC_options_helpdesk_';                      if ($currfield{$field} eq 'no') {
                           $display = ' style="display:none"';
             my $onclicktypes = "toggleHelpdeskRow(this.form,'overrides','$customclass','$optionsprefix');";                      }
                       $datatable .= '</td></tr><tr id="help_screenshotsize"'.$display.' />'.
             $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,                                    '<td>'.&mt('Maximum size for upload (MB)').'</td><td>'.
                                          $numinrow,$othertitle,'overrides',                                    '<input type="text" size="5" name="helpform_maxsize" value="'.$maxsize.'" />';
                                          \$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 ++;  
                 }                  }
                   $datatable .= '</td></tr>';
             }              }
               $datatable .= '</table>';
         }          }
           $datatable .= '</td></tr>'."\n";
           $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 {  sub contacts_javascript {
     return <<"ENDSCRIPT";      return <<"ENDSCRIPT";
   
Line 3228  function screenshotSize(field) { Line 3222  function screenshotSize(field) {
     return;      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>  </script>
   
Line 3284  sub print_helpsettings { Line 3248  sub print_helpsettings {
         my $css_class;          my $css_class;
         my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');          my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');
         my (%customroles,%ordered,%current);          my (%customroles,%ordered,%current);
         if (ref($settings) eq 'HASH') {          if (ref($settings->{'adhoc'}) eq 'HASH') {
             if (ref($settings->{'adhoc'}) eq 'HASH') {              %current = %{$settings->{'adhoc'}};
                 %current = %{$settings->{'adhoc'}};  
             }  
         }          }
         my $count = 0;          my $count = 0;
         foreach my $key (sort(keys(%existing))) {          foreach my $key (sort(keys(%existing))) {
Line 3432  sub print_helpsettings { Line 3394  sub print_helpsettings {
                                                                 \@templateroles,$newcust).                                                                  \@templateroles,$newcust).
                       &Apache::lonuserutils::custom_role_table('Course',\%full,\%levels,                        &Apache::lonuserutils::custom_role_table('Course',\%full,\%levels,
                                                                \%levelscurrent,$newcust).                                                                 \%levelscurrent,$newcust).
                       '</fieldset>'.                        '</fieldset></td></tr>';
                       &helpsettings_javascript(\@roles_by_num,$maxnum,$hiddenstr,$formname).  
                       '</td></tr>';  
         $count ++;          $count ++;
         $$rowtotal += $count;          $$rowtotal += $count;
     }      }
Line 3705  sub radiobutton_prefs { Line 3665  sub radiobutton_prefs {
     return ($datatable,$itemcount);      return ($datatable,$itemcount);
 }  }
   
   sub print_ltitools {
       my ($dom,$settings,$rowtotal) = @_;
       my $rownum = 0;
       my $css_class;
       my $itemcount = 1;
       my $maxnum = 0;
       my %ordered;
       if (ref($settings) eq 'HASH') {
           foreach my $item (keys(%{$settings})) {
               if (ref($settings->{$item}) eq 'HASH') {
                   my $num = $settings->{$item}{'order'};
                   $ordered{$num} = $item;
               }
           }
       }
       my $confname = $dom.'-domainconfig';
       my $switchserver = &check_switchserver($dom,$confname);
       my $maxnum = scalar(keys(%ordered));
       my $datatable = &ltitools_javascript($settings);
       my %lt = &ltitools_names();
       my @courseroles = ('cc','in','ta','ep','st');
       my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner);
       my @fields = ('fullname','firstname','lastname','email','user','roles');
       if (keys(%ordered)) {
           my @items = sort { $a <=> $b } keys(%ordered);
           for (my $i=0; $i<@items; $i++) {
               $css_class = $itemcount%2?' class="LC_odd_row"':'';
               my $item = $ordered{$items[$i]};
               my ($title,$key,$secret,$url,$imgsrc,$version);
               if (ref($settings->{$item}) eq 'HASH') {
                   $title = $settings->{$item}->{'title'};
                   $url = $settings->{$item}->{'url'};
                   $key = $settings->{$item}->{'key'};
                   $secret = $settings->{$item}->{'secret'};
                   my $image = $settings->{$item}->{'image'};
                   if ($image ne '') {
                       $imgsrc = '<img src="'.$image.'" alt="'.&mt('Tool Provider icon').'" />';
                   }
               }
               my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_".$item."'".');"';
               $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
                            .'<select name="ltitools_'.$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;'x2).
                   '<label><input type="checkbox" name="ltitools_del" value="'.$item.'" />'.
                   &mt('Delete?').'</label></span></td>'.
                   '<td colspan="2">'.
                   '<fieldset><legend>'.&mt('Required settings').'</legend>'.
                   '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="30" name="ltitools_title_'.$i.'" value="'.$title.'" /></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'version'}.':<select name="ltitools_version_'.$i.'">'.
                   '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'msgtype'}.':<select name="ltitools_msgtype_'.$i.'">'.
                   '<option value="basic-lti-launch-request" selected="selected">Launch</option></select></span> '.
                   '<br /><br />'.
                   '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="30" name="ltitools_url_'.$i.'"'.
                   ' value="'.$url.'" /></span>'.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'key'}.
                   '<input type="text" size="25" name="ltitools_key_'.$i.'" value="'.$key.'" /></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'secret'}.':'.
                   '<input type="password" size="20" name="ltitools_secret_'.$i.'" value="'.$secret.'" />'.
                   '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.ltitools_secret_'.$i.'.type='."'text'".' } else { this.form.ltitools_secret_'.$i.'.type='."'password'".' }" />'.&mt('Visible input').'</label>'.
                   '<input type="hidden" name="ltitools_id_'.$i.'" value="'.$item.'" /></span>'.
                   '</fieldset>'.
                   '<fieldset><legend>'.&mt('Optional settings').'</legend>'.
                   '<span class="LC_nobreak">'.&mt('Display target:');
               my %currdisp;
               if (ref($settings->{$item}->{'display'}) eq 'HASH') {
                   if ($settings->{$item}->{'display'}->{'target'} eq 'window') {
                       $currdisp{'window'} = ' checked="checked"';
                   } else {
                       $currdisp{'iframe'} = ' checked="checked"';
                   }
                   if ($settings->{$item}->{'display'}->{'width'} =~ /^(\d+)$/) {
                       $currdisp{'width'} = $1;
                   }
                   if ($settings->{$item}->{'display'}->{'height'} =~ /^(\d+)$/) {
                        $currdisp{'height'} = $1;
                   }
               } else {
                   $currdisp{'iframe'} = ' checked="checked"';
               }
               foreach my $disp ('iframe','window') {
                   $datatable .= '<label><input type="radio" name="ltitools_target_'.$i.'" value="'.$disp.'"'.$currdisp{$disp}.' />'.
                                 $lt{$disp}.'</label>'.('&nbsp;'x2);
               }
               $datatable .= ('&nbsp;'x4);
               foreach my $dimen ('width','height') {
                   $datatable .= '<label>'.$lt{$dimen}.'&nbsp;'.
                                 '<input type="text" name="ltitools_'.$dimen.'_'.$i.'" size="5" value="'.$currdisp{$dimen}.'" /></label>'.
                                 ('&nbsp;'x2);
               }
               $datatable .= '<br />';
               foreach my $extra ('passback','roster') {
                   my $checkedon = '';
                   my $checkedoff = ' checked="checked"';
                   if ($settings->{$item}->{$extra}) {
                       $checkedon = $checkedoff;
                       $checkedoff = '';
                   }
                   $datatable .= $lt{$extra}.'&nbsp;'.
                                 '<label><input type="radio" name="ltitools_'.$extra.'_'.$i.'" value="1"'.$checkedon.' />'.
                                 &mt('Yes').'</label>'.('&nbsp;'x2).
                                 '<label><input type="radio" name="ltitools_'.$extra.'_'.$i.'" value="0"'.$checkedoff.' />'.
                                 &mt('No').'</label>'.('&nbsp;'x4);
               }
               $datatable .= '<br /><br /><span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;';
               if ($imgsrc) {
                   $datatable .= $imgsrc.
                                 '<label><input type="checkbox" name="ltitools_image_del"'.
                                 ' value="'.$item.'" />'.&mt('Delete?').'</label></span> '.
                                 '<span class="LC_nobreak">&nbsp;'.&mt('Replace:').'&nbsp;';
               } else {
                   $datatable .= '('.&mt('if larger than 21x21 pixels, image will be scaled').')&nbsp;';
               }
               if ($switchserver) {
                   $datatable .= &mt('Upload to library server: [_1]',$switchserver);
               } else {
                   $datatable .= '<input type="file" name="ltitools_image_'.$i.'" value="" />';
               }
               $datatable .= '</span></fieldset>';
               my (%checkedfields,%rolemaps);
               if (ref($settings->{$item}) eq 'HASH') {
                   if (ref($settings->{$item}->{'fields'}) eq 'HASH') {
                       %checkedfields = %{$settings->{$item}->{'fields'}};
                   }
                   if (ref($settings->{$item}->{'roles'}) eq 'HASH') {
                       %rolemaps = %{$settings->{$item}->{'roles'}};
                       $checkedfields{'roles'} = 1;
                   }
               }
               $datatable .= '<fieldset><legend>'.&mt('User data sent on launch').'</legend>'.
                             '<span class="LC_nobreak">';
               foreach my $field (@fields) {
                   my $checked;
                   if ($checkedfields{$field}) {
                       $checked = ' checked="checked"';
                   }
                   $datatable .= '<label>'.
                                 '<input type="checkbox" name="ltitools_fields_'.$i.'" value="'.$field.'"'.$checked.' />'.
                                 $lt{$field}.'</label>'.('&nbsp;' x2);
               }
               $datatable .= '</span></fieldset>'.
                             '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';
               foreach my $role (@courseroles) {
                   my ($selected,$selectnone);
                   if (!$rolemaps{$role}) {
                       $selectnone = ' selected="selected"';
                   }
                   $datatable .= '<td align="center">'. 
                                 &Apache::lonnet::plaintext($role,'Course').'<br />'.
                                 '<select name="ltitools_roles_'.$role.'_'.$i.'">'.
                                 '<option value=""'.$selectnone.'>'.&mt('Select').'</option>';
                   foreach my $ltirole (@ltiroles) {
                       unless ($selectnone) {
                           if ($rolemaps{$role} eq $ltirole) {
                               $selected = ' selected="selected"';
                           } else {
                               $selected = '';
                           }
                       }
                       $datatable .= '<option value="'.$ltirole.'"'.$selected.'>'.$ltirole.'</option>';
                   }
                   $datatable .= '</select></td>';
               }
               $datatable .= '</tr></table></fieldset>';
               my %courseconfig;
               if (ref($settings->{$item}) eq 'HASH') {
                   if (ref($settings->{$item}->{'crsconf'}) eq 'HASH') {
                       %courseconfig = %{$settings->{$item}->{'crsconf'}};
                   }
               }
               $datatable .= '<fieldset><legend>'.&mt('Configurable in course').'</legend><span class="LC_nobreak">';
               foreach my $item ('label','title','target') {
                   my $checked;
                   if ($courseconfig{$item}) {
                       $checked = ' checked="checked"';
                   }
                   $datatable .= '<label>'.
                          '<input type="checkbox" name="ltitools_courseconfig_'.$i.'" value="'.$item.'"'.$checked.' />'.
                          $lt{'crs'.$item}.'</label>'.('&nbsp;' x2)."\n";
               }
               $datatable .= '</span></fieldset>'.
                             '<fieldset><legend>'.&mt('Custom items sent on launch').'</legend>'.
                             '<table><tr><th>'.&mt('Action').'</th><th>'.&mt('Name').'</th><th>'.&mt('Value').'</th></tr>';
               if (ref($settings->{$item}->{'custom'}) eq 'HASH') {
                   my %custom = %{$settings->{$item}->{'custom'}};
                   if (keys(%custom) > 0) {
                       foreach my $key (sort(keys(%custom))) {
                           $datatable .= '<tr><td><span class="LC_nobreak">'.
                                         '<label><input type="checkbox" name="ltitools_customdel_'.$i.'" value="'.
                                         $key.'" />'.&mt('Delete').'</label></span></td><td>'.$key.'</td>'.
                                         '<td><input type="text" name="ltitools_customval_'.$key.'_'.$i.'"'.
                                         ' value="'.$custom{$key}.'" /></td></tr>';
                       }
                   }
               }
               $datatable .= '<tr><td><span class="LC_nobreak">'.
                             '<label><input type="checkbox" name="ltitools_customadd" value="'.$i.'" />'.
                             &mt('Add').'</label></span></td><td><input type="text" name="ltitools_custom_name_'.$i.'" />'.
                             '</td><td><input type="text" name="ltitools_custom_value_'.$i.'" /></td></tr>';
               $datatable .= '</table></fieldset></td></tr>'."\n";
               $itemcount ++;
           }
       }
       $css_class = $itemcount%2?' class="LC_odd_row"':'';
       my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_add_pos'".');"';
       $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
                     '<input type="hidden" name="ltitools_maxnum" value="'.$maxnum.'" />'."\n".
                     '<select name="ltitools_add_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="ltitools_add" value="1" />'.&mt('Add').'</td>'."\n".
                     '<td colspan="2">'.
                     '<fieldset><legend>'.&mt('Required settings').'</legend>'.
                     '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="30" name="ltitools_add_title" value="" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'version'}.':<select name="ltitools_add_version">'.
                     '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'msgtype'}.':<select name="ltitools_add_msgtype">'.
                     '<option value="basic-lti-launch-request" selected="selected">Launch</option></select></span> '.
                     '<br />'.
                     '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="30" name="ltitools_add_url" value="" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'key'}.':<input type="text" size="25" name="ltitools_add_key" value="" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'secret'}.':<input type="password" size="20" name="ltitools_add_secret" value="" />'.
                     '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.ltitools_add_secret.type='."'text'".' } else { this.form.ltitools_add_secret.type='."'password'".' }" />'.&mt('Visible input').'</label></span> '."\n".
                     '</fieldset>'.
                     '<fieldset><legend>'.&mt('Optional settings').'</legend>'.
                     '<span class="LC_nobreak">'.&mt('Display target:');
       my %defaultdisp;
       $defaultdisp{'iframe'} = ' checked="checked"';
       foreach my $disp ('iframe','window') {
           $datatable .= '<label><input type="radio" name="ltitools_add_target" value="'.$disp.'"'.$defaultdisp{$disp}.' />'.
                         $lt{$disp}.'</label>'.('&nbsp;'x2);
       }
       $datatable .= ('&nbsp;'x4);
       foreach my $dimen ('width','height') {
           $datatable .= '<label>'.$lt{$dimen}.'&nbsp;'.
                         '<input type="text" name="ltitools_add_'.$dimen.'" size="5" /></label>'.
                         ('&nbsp;'x2);
       }
       $datatable .= '<br />';
       foreach my $extra ('passback','roster') {
           $datatable .= $lt{$extra}.'&nbsp;'.
                         '<label><input type="radio" name="ltitools_add_'.$extra.'" value="1" />'.
                         &mt('Yes').'</label>'.('&nbsp;'x2).
                         '<label><input type="radio" name="ltitools_add_'.$extra.'" value="0" checked="checked" />'.
                         &mt('No').'</label>'.('&nbsp;'x4);
       }
       $datatable .= '<br /><br /><span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;'.
                     '('.&mt('if larger than 21x21 pixels, image will be scaled').')&nbsp;';
       if ($switchserver) {
           $datatable .= &mt('Upload to library server: [_1]',$switchserver);
       } else {
           $datatable .= '<input type="file" name="ltitools_add_image" value="" />';
       }
       $datatable .= '</span></fieldset>'.
                     '<fieldset><legend>'.&mt('User data sent on launch').'</legend>'.
                     '<span class="LC_nobreak">';
       foreach my $field (@fields) {
           $datatable .= '<label>'.
                         '<input type="checkbox" name="ltitools_add_fields" value="'.$field.'" />'.
                         $lt{$field}.'</label>'.('&nbsp;' x2);
       }
       $datatable .= '</span></fieldset>'.
                     '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';
       foreach my $role (@courseroles) {
           my ($checked,$checkednone);
           $datatable .= '<td align="center">'.
                         &Apache::lonnet::plaintext($role,'Course').'<br />'.
                         '<select name="ltitools_add_roles_'.$role.'">'.
                         '<option value="" selected="selected">'.&mt('Select').'</option>';
           foreach my $ltirole (@ltiroles) {
               $datatable .= '<option value="'.$ltirole.'">'.$ltirole.'</option>';
           }
           $datatable .= '</select></td>';
       }
       $datatable .= '</tr></table></fieldset>'.
                     '<fieldset><legend>'.&mt('Configurable in course').'</legend><span class="LC_nobreak">';
       foreach my $item ('label','title','target') {
            $datatable .= '<label>'.
                          '<input type="checkbox" name="ltitools_courseconfig" value="'.$item.'" checked="checked" />'.
                          $lt{'crs'.$item}.'</label>'.('&nbsp;' x2)."\n";
       }
       $datatable .= '</span></fieldset>'.
                     '<fieldset><legend>'.&mt('Custom items sent on launch').'</legend>'.
                     '<table><tr><th>'.&mt('Action').'</th><th>'.&mt('Name').'</th><th>'.&mt('Value').'</th></tr>'.
                     '<tr><td><span class="LC_nobreak">'.
                     '<label><input type="checkbox" name="ltitools_add_custom" value="1" />'.
                     &mt('Add').'</label></span></td><td><input type="text" name="ltitools_add_custom_name" />'.
                     '</td><td><input type="text" name="ltitools_add_custom_value" /></td></tr>'.
                     '</table></fieldset></td></tr>'."\n".
                     '</td>'."\n".
                     '</tr>'."\n";
       $itemcount ++;
       return $datatable;
   }
   
   sub ltitools_names {
       my %lt = &Apache::lonlocal::texthash(
                                             'title'     => 'Title',
                                             'version'   => 'Version',
                                             'msgtype'   => 'Message Type',
                                             'url'       => 'URL',
                                             'key'       => 'Key',
                                             'secret'    => 'Secret',
                                             'icon'      => 'Icon',   
                                             'user'      => 'Username:domain',
                                             'fullname'  => 'Full Name',
                                             'firstname' => 'First Name',
                                             'lastname'  => 'Last Name',
                                             'email'     => 'E-mail',
                                             'roles'     => 'Role',
                                             'window'    => 'Window/Tab',
                                             'iframe'    => 'iFrame',
                                             'height'    => 'Height',
                                             'width'     => 'Width',
                                             'passback'  => 'Tool can return grades:',
                                             'roster'    => 'Tool can retrieve roster:',
                                             'crstarget' => 'Display target',
                                             'crslabel'  => 'Course label',
                                             'crstitle'  => 'Course title', 
                                           );
       return %lt;
   }
   
 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,%checkedon,%checkedoff,%defaultchecked,@toggles);
     my $itemcount = 1;      my $itemcount = 1;
     my %choices =  &Apache::lonlocal::texthash (      my %choices =  &Apache::lonlocal::texthash (
           canuse_pdfforms      => 'Course/Community users can create/upload PDF forms',
         uploadquota          => 'Default quota for files uploaded directly to course/community using Course Editor (MB)',          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',          anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',
         coursecredits        => 'Credits can be specified for courses',          coursecredits        => 'Credits can be specified for courses',
         uselcmath            => 'Math preview uses LON-CAPA previewer (javascript) in place of DragMath (Java)',          uselcmath            => 'Math preview uses LON-CAPA previewer (javascript) in place of DragMath (Java)',
         usejsme              => 'Molecule editor uses JSME (HTML5) in place of JME (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',          postsubmit           => 'Disable submit button/keypress following student submission',
         canclone             => "People who may clone a course (besides course's owner and coordinators)",          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',          mysqltables          => 'Lifetime (s) of "Temporary" MySQL tables (student performance data) on homeserver',
Line 3728  sub print_coursedefaults { Line 4034  sub print_coursedefaults {
                          );                           );
     if ($position eq 'top') {      if ($position eq 'top') {
         %defaultchecked = (          %defaultchecked = (
                               'canuse_pdfforms' => 'off',
                             'uselcmath'       => 'on',                              'uselcmath'       => 'on',
                             'usejsme'         => 'on',                              'usejsme'         => 'on',
                             'canclone'        => 'none',                              'canclone'        => 'none',
                           );                            );
         @toggles = ('uselcmath','usejsme');          @toggles = ('canuse_pdfforms','uselcmath','usejsme');
         my $deftex = $Apache::lonnet::deftex;  
         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;  
         $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 valign="top">'.
Line 3839  sub print_coursedefaults { Line 4118  sub print_coursedefaults {
         my ($currdefresponder,%defcredits,%curruploadquota,%deftimeout,%currmysql);          my ($currdefresponder,%defcredits,%curruploadquota,%deftimeout,%currmysql);
         my $currusecredits = 0;          my $currusecredits = 0;
         my $postsubmitclient = 1;          my $postsubmitclient = 1;
         my @types = ('official','unofficial','community','textbook');          my @types = ('official','unofficial','community','textbook','placement');
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             $currdefresponder = $settings->{'anonsurvey_threshold'};              $currdefresponder = $settings->{'anonsurvey_threshold'};
             if (ref($settings->{'uploadquota'}) eq 'HASH') {              if (ref($settings->{'uploadquota'}) eq 'HASH') {
Line 3982  sub print_coursedefaults { Line 4261  sub print_coursedefaults {
         foreach my $type (@types) {          foreach my $type (@types) {
             $datatable .= '<td align="center">'.&mt($type).'<br />'.              $datatable .= '<td align="center">'.&mt($type).'<br />'.
                            '<input type="text" name="mysqltables_'.$type.'"'.                             '<input type="text" name="mysqltables_'.$type.'"'.
                            ' value="'.$currmysql{$type}.'" size="8" /></td>';                             ' value="'.$currmysql{$type}.'" size="5" /></td>';
         }          }
         $datatable .= '</tr></table></td></tr>'."\n";          $datatable .= '</tr></table></td></tr>'."\n";
         $itemcount ++;          $itemcount ++;
Line 3996  sub print_selfenrollment { Line 4275  sub print_selfenrollment {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable);      my ($css_class,$datatable);
     my $itemcount = 1;      my $itemcount = 1;
     my @types = ('official','unofficial','community','textbook');      my @types = ('official','unofficial','community','textbook','placement');
     if (($position eq 'top') || ($position eq 'middle')) {      if (($position eq 'top') || ($position eq 'middle')) {
         my ($rowsref,$titlesref) = &Apache::lonuserutils::get_selfenroll_titles();          my ($rowsref,$titlesref) = &Apache::lonuserutils::get_selfenroll_titles();
         my %descs = &Apache::lonuserutils::selfenroll_default_descs();          my %descs = &Apache::lonuserutils::selfenroll_default_descs();
Line 4180  sub print_validation_rows { Line 4459  sub print_validation_rows {
                               '</label></span> ';                                '</label></span> ';
             }              }
         } elsif ($item eq 'markup') {          } elsif ($item eq 'markup') {
             $datatable .= '<textarea name="'.$caller.'_validation_markup" cols="50" rows="5">'.              $datatable .= '<textarea name="'.$caller.'_validation_markup" cols="50" rows="5" wrap="soft">'.
                            $currvalidation{$item}.                             $currvalidation{$item}.
                               '</textarea>';                                '</textarea>';
         }          }
Line 4202  sub print_validation_rows { Line 4481  sub print_validation_rows {
         my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',          my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',
                                                        'validationdc',%currhash);                                                         'validationdc',%currhash);
         my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';          my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
         $datatable .= '<tr'.$css_class.'><td>';          $datatable .= '</td></tr><tr'.$css_class.'><td>';
         if ($numdc > 1) {          if ($numdc > 1) {
             $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)');              $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)');
         } else {          } else {
Line 4217  sub print_validation_rows { Line 4496  sub print_validation_rows {
     return $datatable;      return $datatable;
 }  }
   
 sub print_passwords {  sub print_usersessions {
     my ($position,$dom,$confname,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($datatable,$css_class);      my ($css_class,$datatable,$itemcount,%checked,%choices);
     my $itemcount = 0;      my (%by_ip,%by_location,@intdoms,@instdoms);
     my %titles = &Apache::lonlocal::texthash (      &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
         captcha        => '"Forgot Password" CAPTCHA validation',  
         link           => 'Reset link expiration (hours)',      my @alldoms = &Apache::lonnet::all_domains();
         case           => 'Case-sensitive usernames/e-mail',      my %serverhomes = %Apache::lonnet::serverhomeIDs;
         prelink        => 'Information required (form 1)',      my %servers = &Apache::lonnet::internet_dom_servers($dom);
         postlink       => 'Information required (form 2)',      my %altids = &id_for_thisdom(%servers);
         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') {      if ($position eq 'top') {
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);          if (keys(%serverhomes) > 1) {
         my $shownlinklife = 2;              my %spareid = &current_offloads_to($dom,$settings,\%servers);
         my $prelink = 'both';              my $curroffloadnow;
         my (%casesens,%postlink,%emailsrc,$nostdtext,$customurl);              if (ref($settings) eq 'HASH') {
         if (ref($settings) eq 'HASH') {                  if (ref($settings->{'offloadnow'}) eq 'HASH') {
             if ($settings->{resetlink} =~ /^\d+(|\.\d*)$/) {                      $curroffloadnow = $settings->{'offloadnow'};
                 $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; ';  
             }              }
         }              $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$curroffloadnow,$rowtotal);
         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 {          } else {
             $datatable .='<span class="LC_nobreak">&nbsp;'.              $datatable .= '<tr'.$css_class.'><td colspan="2">'.
                          '<input type="file" name="passwords_customfile" /></span>';                            &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.').
                             '</td></tr>';
         }          }
         $datatable .= '</td></tr>';      } else {
     } elsif ($position eq 'middle') {          my %titles = &usersession_titles();
         my %domconf = &Apache::lonnet::get_dom('configuration',['defaults'],$dom);          my ($prefix,@types);
         my @items = ('intauth_cost','intauth_check','intauth_switch');          if ($position eq 'bottom') {
         my %defaults;              $prefix = 'remote';
         if (ref($domconf{'defaults'}) eq 'HASH') {              @types = ('version','excludedomain','includedomain');
             %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 {          } else {
             %defaults = (              $prefix = 'hosted';
                           'intauth_cost'   => 10,              @types = ('excludedomain','includedomain');
                           'intauth_check'  => 0,  
                           'intauth_switch' => 0,  
                         );  
         }          }
         foreach my $item (@items) {          ($datatable,$itemcount) = &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
             if ($itemcount%2) {      }
                 $css_class = '';      $$rowtotal += $itemcount;
             } else {      return $datatable;
                 $css_class = ' class="LC_odd_row" ';  }
             }  
             $datatable .= '<tr'.$css_class.'>'.  sub rules_by_location {
                           '<td><span class="LC_nobreak">'.$titles{$item}.      my ($settings,$prefix,$by_location,$by_ip,$types,$titles) = @_; 
                           '</span></td><td class="LC_left_item" colspan="3">';      my ($datatable,$itemcount,$css_class);
             if ($item eq 'intauth_switch') {      if (keys(%{$by_location}) == 0) {
                 my @options = (0,1,2);          $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
                 my %optiondesc = &Apache::lonlocal::texthash (          $datatable = '<tr'.$css_class.'><td colspan="2">'.
                                    0 => 'No',                       &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.').
                                    1 => 'Yes',                       '</td></tr>';
                                    2 => 'Yes, and copy existing passwd file to passwd.bak file',          $itemcount = 1;
                                  );      } else {
                 $datatable .= '<table width="100%">';          $itemcount = 0;
                 foreach my $option (@options) {          my $numinrow = 5;
                     my $checked = ' ';          my (%current,%checkedon,%checkedoff);
                     if ($defaults{$item} eq $option) {          my @locations = sort(keys(%{$by_location}));
                         $checked = ' checked="checked"';          foreach my $type (@{$types}) {
                     }              $checkedon{$type} = '';
                     $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.              $checkedoff{$type} = ' checked="checked"';
                                   '<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 (ref($settings) eq 'HASH') {
             if ($settings->{min}) {              if (ref($settings->{$prefix}) eq 'HASH') {
                 $min = $settings->{min};                  foreach my $key (keys(%{$settings->{$prefix}})) {
             }                      $current{$key} = $settings->{$prefix}{$key};
             if ($settings->{max}) {                      if ($key eq 'version') {
                 $max = $settings->{max};                          if ($current{$key} ne '') {
             }                              $checkedon{$key} = ' checked="checked"';
             if (ref($settings->{chars}) eq 'ARRAY') {                              $checkedoff{$key} = '';
                 map { $chars{$_} = 1; } (@{$settings->{chars}});                          }
             }                      } elsif (ref($current{$key}) eq 'ARRAY') {
             if ($settings->{numsaved}) {                          $checkedon{$key} = ' checked="checked"';
                 $numsaved = $settings->{numsaved};                          $checkedoff{$key} = '';
             }                      }
         }  
         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);          foreach my $type (@{$types}) {
         my $colsleft = $numinrow - $rem;              next if ($type ne 'version' && !@locations);
         if ($colsleft > 1 ) {              $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
             $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.              $datatable .= '<tr'.$css_class.'>
                           '&nbsp;</td>';                             <td><span class="LC_nobreak">'.$titles->{$type}.'</span><br />
         } elsif ($colsleft == 1) {                             <span class="LC_nobreak">&nbsp;
             $datatable .= '<td class="LC_left_item">&nbsp;</td>';                             <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>&nbsp;
         }                             <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';
         $datatable .='</table></td></tr>';              if ($type eq 'version') {
         $itemcount ++;                  my @lcversions = &Apache::lonnet::all_loncaparevs();
         $css_class = $itemcount%2?' class="LC_odd_row"':'';                  my $selector = '<select name="'.$prefix.'_version">';
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'numsaved'}.'</td>'.                  foreach my $version (@lcversions) {
                       '<td class="LC_left_item"><span class="LC_nobreak">'.                      my $selected = '';
                       '<input type="text" name="passwords_numsaved" value="'.$numsaved.'" size="3" '.                      if ($current{'version'} eq $version) {
                       'onblur="javascript:warnIntPass(this);" />'.                          $selected = ' selected="selected"';
                       '<span class="LC_fontsize_small"> '.&mt('(Leave blank to not save previous passwords)').'</span>'.                      }
                       '</span></td></tr>';                      $selector .= ' <option value="'.$version.'"'.
     } else {                                   $selected.'>'.$version.'</option>';
         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'}});  
                 }                  }
             }                  $selector .= '</select> ';
         }                  $datatable .= &mt('remote server must be version: [_1] or later',$selector);
         $css_class = $itemcount%2?' class="LC_odd_row"':'';              } else {
         $datatable .= '<tr '.$css_class.'>'.                  $datatable.= '<div><input type="button" value="'.&mt('check all').'" '.
                       '<td>'.                               'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.
                       &mt('Requirements').'<ul>'.                               ' />'.('&nbsp;'x2).
                       '<li>'.&mt("Course 'type' is not a Community").'</li>'.                               '<input type="button" value="'.&mt('uncheck all').'" '.
                       '<li>'.&mt('User is Course Coordinator and also course owner').'</li>'.                               'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.
                       '<li>'.&mt("Student's only active roles are student role(s) in course(s) owned by this user").'</li>'.                               "\n".
                       '<li>'.&mt('User, course, and student share same domain').'</li>'.                               '</div><div><table>';
                       '</ul>'.                  my $rem;
                       '</td>'.                  for (my $i=0; $i<@locations; $i++) {
                       '<td class="LC_left_item">';                      my ($showloc,$value,$checkedtype);
         foreach my $item ('by','for') {                      if (ref($by_location->{$locations[$i]}) eq 'ARRAY') {
             $datatable .= '<fieldset style="display: inline-block;">'.                          my $ip = $by_location->{$locations[$i]}->[0];
                           '<legend>'.$ownertitles{$item}.'</legend>';                          if (ref($by_ip->{$ip}) eq 'ARRAY') {
             if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {                              $value = join(':',@{$by_ip->{$ip}});
                 foreach my $type (@{$types}) {                              $showloc = join(', ',@{$by_ip->{$ip}});
                     my $checked;                              if (ref($current{$type}) eq 'ARRAY') {
                     if ($ownerchg{$item}{$type}) {                                  foreach my $loc (@{$by_ip->{$ip}}) {
                         $checked = ' checked="checked"';                                      if (grep(/^\Q$loc\E$/,@{$current{$type}})) {
                                           $checkedtype = ' checked="checked"';
                                           last;
                                       }
                                   }
                               }
                           }
                     }                      }
                     $datatable .= '<span class="LC_nobreak"><label>'.                      $rem = $i%($numinrow);
                                   '<input type="checkbox" name="passwords_crsowner_'.$item.'" value="'.                      if ($rem == 0) {
                                   $type.'"'.$checked.' />'.$usertypes->{$type}.'</label>'.                          if ($i > 0) {
                                   '</span>&nbsp;&nbsp; ';                              $datatable .= '</tr>';
                           }
                           $datatable .= '<tr>';
                       }
                       $datatable .= '<td class="LC_left_item">'.
                                     '<span class="LC_nobreak"><label>'.
                                     '<input type="checkbox" name="'.$prefix.'_'.$type.
                                     '" value="'.$value.'"'.$checkedtype.' />'.$showloc.
                                     '</label></span></td>';
                 }                  }
                   $rem = @locations%($numinrow);
                   my $colsleft = $numinrow - $rem;
                   if ($colsleft > 1 ) {
                       $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                                     '&nbsp;</td>';
                   } elsif ($colsleft == 1) {
                       $datatable .= '<td class="LC_left_item">&nbsp;</td>';
                   }
                   $datatable .= '</tr></table>';
             }              }
             my $checked;              $datatable .= '</td></tr>';
             if ($ownerchg{$item}{'default'}) {              $itemcount ++;
                 $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,$itemcount);
 }  }
   
 sub print_usersessions {  sub print_ssl {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable,%checked,%choices);      my ($css_class,$datatable);
     my (%by_ip,%by_location,@intdoms);  
     &build_location_hashes(\@intdoms,\%by_ip,\%by_location);  
   
     my @alldoms = &Apache::lonnet::all_domains();  
     my %serverhomes = %Apache::lonnet::serverhomeIDs;  
     my %servers = &Apache::lonnet::internet_dom_servers($dom);  
     my %altids = &id_for_thisdom(%servers);  
     my $itemcount = 1;      my $itemcount = 1;
     if ($position eq 'top') {      if ($position eq 'top') {
         if (keys(%serverhomes) > 1) {          my $primary_id = &Apache::lonnet::domain($dom,'primary');
             my %spareid = &current_offloads_to($dom,$settings,\%servers);          my $intdom = &Apache::lonnet::internet_dom($primary_id);
             my ($curroffloadnow,$curroffloadoth);          my $same_institution;
             if (ref($settings) eq 'HASH') {          if ($intdom ne '') {
                 if (ref($settings->{'offloadnow'}) eq 'HASH') {              my $internet_names = &Apache::lonnet::get_internet_names($Apache::lonnet::perlvar{'lonHostID'});
                     $curroffloadnow = $settings->{'offloadnow'};              if (ref($internet_names) eq 'ARRAY') {
                 }                  if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
                 if (ref($settings->{'offloadoth'}) eq 'HASH') {                      $same_institution = 1;
                     $curroffloadoth = $settings->{'offloadoth'};  
                 }                  }
             }              }
             my $other_insts = scalar(keys(%by_location));          }
             $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,          $css_class = $itemcount%2?' class="LC_odd_row"':'';
                                       $other_insts,$curroffloadnow,$curroffloadoth,$rowtotal);          $datatable = '<tr'.$css_class.'><td colspan="2">';
           if ($same_institution) {
               my %domservers = &Apache::lonnet::get_servers($dom);
               $datatable .= &LONCAPA::SSL::print_certstatus(\%domservers,'web','domprefs');
         } else {          } else {
             $datatable .= '<tr'.$css_class.'><td colspan="2">'.              $datatable .= &mt("You need to be logged into one of your own domain's servers to display information about the status of LON-CAPA SSL certificates.");
                           &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.');  
         }          }
           $datatable .= '</td></tr>';
           $itemcount ++;
     } else {      } else {
         if (keys(%by_location) == 0) {          my %titles = &ssl_titles();
             $datatable .= '<tr'.$css_class.'><td colspan="2">'.          my (%by_ip,%by_location,@intdoms,@instdoms);
                           &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.');          &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
         } else {          my @alldoms = &Apache::lonnet::all_domains();
             my %lt = &usersession_titles();          my %serverhomes = %Apache::lonnet::serverhomeIDs;
             my $numinrow = 5;          my @domservers = &Apache::lonnet::get_servers($dom);
             my $prefix;          my %servers = &Apache::lonnet::internet_dom_servers($dom);
             my @types;          my %altids = &id_for_thisdom(%servers);
             if ($position eq 'bottom') {          if (($position eq 'connto') || ($position eq 'connfrom')) {
                 $prefix = 'remote';              my $legacy;
                 @types = ('version','excludedomain','includedomain');              unless (ref($settings) eq 'HASH') {
             } else {                  my $name;
                 $prefix = 'hosted';                  if ($position eq 'connto') {
                 @types = ('excludedomain','includedomain');                      $name = 'loncAllowInsecure';
             }                  } else {
             my (%current,%checkedon,%checkedoff);                      $name = 'londAllowInsecure';
             my @lcversions = &Apache::lonnet::all_loncaparevs();                  }
             my @locations = sort(keys(%by_location));                  my $primarylibserv = &Apache::lonnet::domain($dom,'primary');
             foreach my $type (@types) {                  my @ids=&Apache::lonnet::current_machine_ids();
                 $checkedon{$type} = '';                  if (($primarylibserv ne '') && (!grep(/^\Q$primarylibserv\E$/,@ids))) {
                 $checkedoff{$type} = ' checked="checked"';                      my %what = (
             }                                     $name => 1,
             if (ref($settings) eq 'HASH') {                                 );
                 if (ref($settings->{$prefix}) eq 'HASH') {                      my ($result,$returnhash) =
                     foreach my $key (keys(%{$settings->{$prefix}})) {                          &Apache::lonnet::get_remote_globals($primarylibserv,\%what);
                         $current{$key} = $settings->{$prefix}{$key};                      if ($result eq 'ok') {
                         if ($key eq 'version') {                          if (ref($returnhash) eq 'HASH') {
                             if ($current{$key} ne '') {                              $legacy = $returnhash->{$name};
                                 $checkedon{$key} = ' checked="checked"';  
                                 $checkedoff{$key} = '';  
                             }  
                         } elsif (ref($current{$key}) eq 'ARRAY') {  
                             $checkedon{$key} = ' checked="checked"';  
                             $checkedoff{$key} = '';  
                         }                          }
                     }                      }
                   } else {
                       $legacy = $Apache::lonnet::perlvar{$name};
                 }                  }
             }              }
             foreach my $type (@types) {              foreach my $type ('dom','intdom','other') {
                 next if ($type ne 'version' && !@locations);                  my %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>'.$titles{$type}.'</td>'.
                                <td><span class="LC_nobreak">'.$lt{$type}.'</span><br />                                '<td class="LC_right_item">';
                                <span class="LC_nobreak">&nbsp;                  my $skip; 
                                <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>&nbsp;                  if ($type eq 'dom') {
                                <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';                      unless (keys(%servers) > 1) {
                 if ($type eq 'version') {                          $datatable .= &mt('Nothing to set here, as there are no other servers/VMs');    
                     my $selector = '<select name="'.$prefix.'_version">';                          $skip = 1;
                     foreach my $version (@lcversions) {  
                         my $selected = '';  
                         if ($current{'version'} eq $version) {  
                             $selected = ' selected="selected"';  
                         }  
                         $selector .= ' <option value="'.$version.'"'.  
                                      $selected.'>'.$version.'</option>';  
                     }                      }
                     $selector .= '</select> ';                  }
                     $datatable .= &mt('remote server must be version: [_1] or later',$selector);                  if ($type eq 'intdom') {
                 } else {                      unless (@instdoms > 1) {
                     $datatable.= '<div><input type="button" value="'.&mt('check all').'" '.                          $datatable .= &mt('Nothing to set here, as there are no other domains for this institution');
                                  'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.                          $skip = 1;
                                  ' />'.('&nbsp;'x2).                      } 
                                  '<input type="button" value="'.&mt('uncheck all').'" '.                  } elsif ($type eq 'other') {
                                  'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.                      if (keys(%by_location) == 0) {
                                  "\n".                          $datatable .= &mt('Nothing to set here, as there are no other institutions');
                                  '</div><div><table>';                          $skip = 1;
                     my $rem;                      }
                     for (my $i=0; $i<@locations; $i++) {                  }
                         my ($showloc,$value,$checkedtype);                  unless ($skip) {
                         if (ref($by_location{$locations[$i]}) eq 'ARRAY') {                      $checked{'yes'} = ' checked="checked"'; 
                             my $ip = $by_location{$locations[$i]}->[0];                      if (ref($settings) eq 'HASH') {
                             if (ref($by_ip{$ip}) eq 'ARRAY') {                          if (ref($settings->{$position}) eq 'HASH') {
                                  $value = join(':',@{$by_ip{$ip}});                              if ($settings->{$position}->{$type} =~ /^(no|req)$/) {
                                 $showloc = join(', ',@{$by_ip{$ip}});                                  $checked{$1} = $checked{'yes'};
                                 if (ref($current{$type}) eq 'ARRAY') {                                  delete($checked{'yes'}); 
                                     foreach my $loc (@{$by_ip{$ip}}) {    
                                         if (grep(/^\Q$loc\E$/,@{$current{$type}})) {  
                                             $checkedtype = ' checked="checked"';  
                                             last;  
                                         }  
                                     }  
                                 }  
                             }                              }
                         }                          }
                         $rem = $i%($numinrow);                      } else {
                         if ($rem == 0) {                          if ($legacy == 0) {
                             if ($i > 0) {                              $checked{'req'} = $checked{'yes'};
                                 $datatable .= '</tr>';                              delete($checked{'yes'});    
                             }                          }
                             $datatable .= '<tr>';  
                         }  
                         $datatable .= '<td class="LC_left_item">'.  
                                       '<span class="LC_nobreak"><label>'.  
                                       '<input type="checkbox" name="'.$prefix.'_'.$type.  
                                       '" value="'.$value.'"'.$checkedtype.' />'.$showloc.  
                                       '</label></span></td>';  
                     }                      }
                     $rem = @locations%($numinrow);                      foreach my $option ('no','yes','req') {
                     my $colsleft = $numinrow - $rem;                          $datatable .= '<span class="LC_nobreak"><label>'.
                     if ($colsleft > 1 ) {                                        '<input type="radio" name="'.$position.'_'.$type.'" '.
                         $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.                                        'value="'.$option.'"'.$checked{$option}.' />'.$titles{$option}.
                                       '&nbsp;</td>';                                        '</label></span>'.('&nbsp;'x2);
                     } elsif ($colsleft == 1) {  
                         $datatable .= '<td class="LC_left_item">&nbsp;</td>';  
                     }                      }
                     $datatable .= '</tr></table>';  
                 }                  }
                 $datatable .= '</td></tr>';                  $datatable .= '</td></tr>';
                   $itemcount ++; 
               }
           } else {
               my $prefix = 'replication';
               my @types = ('certreq','nocertreq');
               if (keys(%by_location) == 0) {
                   $datatable .= '<tr'.$css_class.'><td>'.
                                 &mt('Nothing to set here, as there are no other institutions').
                                 '</td></tr>';
                 $itemcount ++;                  $itemcount ++;
               } else {
                   ($datatable,$itemcount) = 
                       &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
             }              }
         }          }
     }      }
Line 4786  sub print_usersessions { Line 4775  sub print_usersessions {
     return $datatable;      return $datatable;
 }  }
   
   sub ssl_titles {
       return &Apache::lonlocal::texthash (
                  dom           => 'LON-CAPA servers/VMs from same domain',
                  intdom        => 'LON-CAPA servers/VMs from same "internet" domain',
                  other         => 'External LON-CAPA servers/VMs',
                  connto        => 'Connections to other servers',
                  connfrom      => 'Connections from other servers',
                  replication   => 'Replicating content to other institutions',
                  certreq       => 'Client certificate required, but specific domains exempt',
                  nocertreq     => 'No client certificate required, except for specific domains',
                  no            => 'SSL not used',
                  yes           => 'SSL Optional (used if available)',
                  req           => 'SSL Required',
       );
   }
   
   sub print_trust {
       my ($prefix,$dom,$settings,$rowtotal) = @_;
       my ($css_class,$datatable,%checked,%choices);
       my (%by_ip,%by_location,@intdoms,@instdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
       my $itemcount = 1;
       my %titles = &trust_titles();
       my @types = ('exc','inc');
       if ($prefix eq 'top') {
           $prefix = 'content';
       } elsif ($prefix eq 'bottom') {
           $prefix = 'msg';
       }
       ($datatable,$itemcount) = &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
       $$rowtotal += $itemcount;
       return $datatable;
   }
   
   sub trust_titles {
       return &Apache::lonlocal::texthash(
                  content  => "Access to this domain's content by others",
                  shared   => "Access to other domain's content by this domain",
                  enroll   => "Enrollment in this domain's courses by others", 
                  othcoau  => "Co-author roles in this domain for others",
                  coaurem  => "Co-author roles for this domain's users elsewhere", 
                  domroles => "Domain roles in this domain assignable to others",
                  catalog  => "Course Catalog for this domain displayed elsewhere",
                  reqcrs   => "Requests for creation of courses in this domain by others",
                  msg      => "Users in other domains can send messages to this domain",
                  exc      => "Allow all, but exclude specific domains",
                  inc      => "Deny all, but include specific domains",
              );
   } 
   
 sub build_location_hashes {  sub build_location_hashes {
     my ($intdoms,$by_ip,$by_location) = @_;      my ($intdoms,$by_ip,$by_location,$instdoms) = @_;
     return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') &&      return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') &&
                   (ref($by_location) eq 'HASH'));                     (ref($by_location) eq 'HASH') && (ref($instdoms) eq 'ARRAY'));
     my %iphost = &Apache::lonnet::get_iphost();      my %iphost = &Apache::lonnet::get_iphost();
     my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary');      my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary');
     my $primary_ip = &Apache::lonnet::get_host_ip($primary_id);      my $primary_ip = &Apache::lonnet::get_host_ip($primary_id);
Line 4806  sub build_location_hashes { Line 4845  sub build_location_hashes {
             foreach my $id (@{$iphost{$ip}}) {              foreach my $id (@{$iphost{$ip}}) {
                 my $location = &Apache::lonnet::internet_dom($id);                  my $location = &Apache::lonnet::internet_dom($id);
                 if ($location) {                  if ($location) {
                     next if (grep(/^\Q$location\E$/,@{$intdoms}));                      if (grep(/^\Q$location\E$/,@{$intdoms})) {
                           my $dom = &Apache::lonnet::host_domain($id);
                           unless (grep(/^\Q$dom\E/,@{$instdoms})) {
                               push(@{$instdoms},$dom);
                           }
                           next;
                       }
                     if (ref($by_ip->{$ip}) eq 'ARRAY') {                      if (ref($by_ip->{$ip}) eq 'ARRAY') {
                         unless(grep(/^\Q$location\E$/,@{$by_ip->{$ip}})) {                          unless(grep(/^\Q$location\E$/,@{$by_ip->{$ip}})) {
                             push(@{$by_ip->{$ip}},$location);                              push(@{$by_ip->{$ip}},$location);
Line 4914  sub current_offloads_to { Line 4959  sub current_offloads_to {
 }  }
   
 sub spares_row {  sub spares_row {
     my ($dom,$servers,$spareid,$serverhomes,$altids,$other_insts,      my ($dom,$servers,$spareid,$serverhomes,$altids,$curroffloadnow,$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 4979  sub spares_row {
                 }                  }
             }              }
             next unless (ref($spareid->{$server}) eq 'HASH');              next unless (ref($spareid->{$server}) eq 'HASH');
             my ($checkednow,$checkedoth);              my $checkednow;
             if (ref($curroffloadnow) eq 'HASH') {              if (ref($curroffloadnow) eq 'HASH') {
                 if ($curroffloadnow->{$server}) {                  if ($curroffloadnow->{$server}) {
                     $checkednow = ' checked="checked"';                      $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">
Line 4954  sub spares_row { Line 4993  sub spares_row {
                               ,'<b>'.$server.'</b>').'</span><br />'.                                ,'<b>'.$server.'</b>').'</span><br />'.
                           '<span class="LC_nobreak">'."\n".                            '<span class="LC_nobreak">'."\n".
                           '<label><input type="checkbox" name="offloadnow" value="'.$server.'"'.$checkednow.' />'.                            '<label><input type="checkbox" name="offloadnow" value="'.$server.'"'.$checkednow.' />'.
                           '&nbsp;'.&mt('Switch any active user on next access').'</label></span>'.                            '&nbsp;'.&mt('Switch active users 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";                            "\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 5118  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,%existing);
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         %existing = %{$settings};          %existing = %{$settings};
     }      }
     if ((keys(%servers) > 1) || (keys(%existing) > 0)) {      if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
         &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,          &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
                                   \%currtargets,\%currrules,\%currcookies);                                    \%currtargets,\%currrules);
     } else {      } else {
         return;          return;
     }      }
Line 5169  sub print_loadbalancing { Line 5201  sub print_loadbalancing {
         my %hostherechecked = (          my %hostherechecked = (
                                   no => ' checked="checked"',                                    no => ' checked="checked"',
                               );                                );
         my %balcookiechecked = (  
                                   no => ' checked="checked"',  
                                );  
         foreach my $sparetype (@sparestypes) {          foreach my $sparetype (@sparestypes) {
             my $targettable;              my $targettable;
             for (my $i=0; $i<$numspares; $i++) {              for (my $i=0; $i<$numspares; $i++) {
Line 5227  sub print_loadbalancing { Line 5256  sub print_loadbalancing {
                 }                  }
             }              }
         }          }
         if ($currcookies{$lonhost}) {  
             %balcookiechecked = (  
                                     yes => ' checked="checked"',  
                                 );  
         }  
         $datatable .= &mt('Hosting on balancer itself').'<br />'.          $datatable .= &mt('Hosting on balancer itself').'<br />'.
                       '<label><input type="radio" name="loadbalancing_target_'.$balnum.'_hosthere" value="no"'.                        '<label><input type="radio" name="loadbalancing_target_'.$balnum.'_hosthere" value="no"'.
                       $hostherechecked{'no'}.' />'.&mt('No').'</label><br />';                        $hostherechecked{'no'}.' />'.&mt('No').'</label><br />';
Line 5240  sub print_loadbalancing { Line 5264  sub print_loadbalancing {
                           'value="'.$sparetype.'"'.$hostherechecked{$sparetype}.' /><i>'.$typetitles{$sparetype}.                            'value="'.$sparetype.'"'.$hostherechecked{$sparetype}.' /><i>'.$typetitles{$sparetype}.
                           '</i></label><br />';                            '</i></label><br />';
         }          }
         $datatable .= &mt('Use balancer cookie').'<br />'.          $datatable .= '</div></td></tr>'.
                       '<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},                        &loadbalancing_rules($dom,$intdom,$currrules{$lonhost},
                                            $othertitle,$usertypes,$types,\%servers,                                             $othertitle,$usertypes,$types,\%servers,
                                            \%currbalancer,$lonhost,                                             \%currbalancer,$lonhost,
Line 5259  sub print_loadbalancing { Line 5278  sub print_loadbalancing {
 }  }
   
 sub get_loadbalancers_config {  sub get_loadbalancers_config {
     my ($servers,$existing,$currbalancer,$currtargets,$currrules,$currcookies) = @_;      my ($servers,$existing,$currbalancer,$currtargets,$currrules) = @_;
     return unless ((ref($servers) eq 'HASH') &&      return unless ((ref($servers) eq 'HASH') &&
                    (ref($existing) eq 'HASH') && (ref($currbalancer) eq 'HASH') &&                     (ref($existing) eq 'HASH') && (ref($currbalancer) eq 'HASH') &&
                    (ref($currtargets) eq 'HASH') && (ref($currrules) eq 'HASH') &&                     (ref($currtargets) eq 'HASH') && (ref($currrules) eq 'HASH'));
                    (ref($currcookies) eq 'HASH'));  
     if (keys(%{$existing}) > 0) {      if (keys(%{$existing}) > 0) {
         my $oldlonhost;          my $oldlonhost;
         foreach my $key (sort(keys(%{$existing}))) {          foreach my $key (sort(keys(%{$existing}))) {
Line 5282  sub get_loadbalancers_config { Line 5300  sub get_loadbalancers_config {
                 $currbalancer->{$key} = 1;                  $currbalancer->{$key} = 1;
                 $currtargets->{$key} = $existing->{$key}{'targets'};                  $currtargets->{$key} = $existing->{$key}{'targets'};
                 $currrules->{$key} = $existing->{$key}{'rules'};                  $currrules->{$key} = $existing->{$key}{'rules'};
                 if ($existing->{$key}{'cookie'}) {  
                     $currcookies->{$key} = 1;  
                 }  
             }              }
         }          }
     } else {      } else {
Line 5340  sub loadbalancing_titles { Line 5355  sub loadbalancing_titles {
            '_LC_ipchange'    => &mt('Non-SSO users with IP mismatch'),             '_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','_LC_ipchangesso','_LC_ipchange');
     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 5474  sub contact_titles { Line 5484  sub contact_titles {
                    '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 for this domain's users",
                    'otherdomsmail'   => 'Helpdesk requests from users in other (unconfigured) domains',                     'otherdomsmail'   => 'Helpdesk requests for 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',                     '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',                     '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 5527  sub tool_titles { Line 5536  sub tool_titles {
                      unofficial => 'Unofficial courses',                       unofficial => 'Unofficial courses',
                      community  => 'Communities',                       community  => 'Communities',
                      textbook   => 'Textbook courses',                       textbook   => 'Textbook courses',
                        placement  => 'Placement tests',
                  );                   );
     return %titles;      return %titles;
 }  }
Line 5537  sub courserequest_titles { Line 5547  sub courserequest_titles {
                                    unofficial => 'Unofficial',                                     unofficial => 'Unofficial',
                                    community  => 'Communities',                                     community  => 'Communities',
                                    textbook   => 'Textbook',                                     textbook   => 'Textbook',
                                      placement  => 'Placement tests',
                                    norequest  => 'Not allowed',                                     norequest  => 'Not allowed',
                                    approval   => 'Approval by Dom. Coord.',                                     approval   => 'Approval by Dom. Coord.',
                                    validate   => 'With validation',                                     validate   => 'With validation',
Line 5701  sub print_usercreation { Line 5712  sub print_usercreation {
   
 sub print_selfcreation {  sub print_selfcreation {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my (@selfcreate,$createsettings,$processing,$emailoptions,$emailverified,      my (@selfcreate,$createsettings,$processing,$datatable);
         $emaildomain,$datatable);  
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{'cancreate'}) eq 'HASH') {          if (ref($settings->{'cancreate'}) eq 'HASH') {
             $createsettings = $settings->{'cancreate'};              $createsettings = $settings->{'cancreate'};
Line 5719  sub print_selfcreation { Line 5729  sub print_selfcreation {
                 if (ref($createsettings->{'selfcreateprocessing'}) eq 'HASH') {                  if (ref($createsettings->{'selfcreateprocessing'}) eq 'HASH') {
                     $processing = $createsettings->{'selfcreateprocessing'};                      $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 %radiohash;
     my $numinrow = 4;      my $numinrow = 4;
     map { $radiohash{'cancreate_'.$_} = 1; } @selfcreate;      map { $radiohash{'cancreate_'.$_} = 1; } @selfcreate;
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
     if ($position eq 'top') {      if ($position eq 'top') {
         my %choices = &Apache::lonlocal::texthash (          my %choices = &Apache::lonlocal::texthash (
                                                       cancreate_login      => 'Institutional Login',                                                        cancreate_login      => 'Institutional Login',
Line 5749  sub print_selfcreation { Line 5749  sub print_selfcreation {
         ($datatable,$itemcount) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,          ($datatable,$itemcount) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,
                                                      \%choices,$itemcount,$onclick);                                                       \%choices,$itemcount,$onclick);
         $$rowtotal += $itemcount;          $$rowtotal += $itemcount;
           
           my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
   
         if (ref($usertypes) eq 'HASH') {          if (ref($usertypes) eq 'HASH') {
             if (keys(%{$usertypes}) > 0) {              if (keys(%{$usertypes}) > 0) {
                 $datatable .= &insttypes_row($createsettings,$types,$usertypes,                  $datatable .= &insttypes_row($createsettings,$types,$usertypes,
                                              $dom,$numinrow,$othertitle,                                               $dom,$numinrow,$othertitle,
                                              'statustocreate',$rowtotal);                                               'statustocreate',$$rowtotal);
                 $$rowtotal ++;                  $$rowtotal ++;
             }              }
         }          }
Line 5767  sub print_selfcreation { Line 5769  sub print_selfcreation {
         $datatable .= '<tr'.$css_class.'>'.          $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">'.&mt('Mapping of Shibboleth environment variable names to user data fields (SSO auth)').'</td>'.
                      '<td class="LC_left_item">'."\n".                       '<td class="LC_left_item">'."\n".
                      '<table>'."\n";                       '<table><tr><td>'."\n";
         for (my $i=0; $i<@fields; $i++) {          for (my $i=0; $i<@fields; $i++) {
             $rem = $i%($numperrow);              $rem = $i%($numperrow);
             if ($rem == 0) {              if ($rem == 0) {
Line 5799  sub print_selfcreation { Line 5801  sub print_selfcreation {
         $$rowtotal ++;          $$rowtotal ++;
     } elsif ($position eq 'middle') {      } elsif ($position eq 'middle') {
         my %domconf = &Apache::lonnet::get_dom('configuration',['usermodification'],$dom);          my %domconf = &Apache::lonnet::get_dom('configuration',['usermodification'],$dom);
         my @posstypes;          my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
           $usertypes->{'default'} = $othertitle;
         if (ref($types) eq 'ARRAY') {          if (ref($types) eq 'ARRAY') {
             @posstypes = @{$types};              push(@{$types},'default');
         }              $usertypes->{'default'} = $othertitle;
         unless (grep(/^default$/,@posstypes)) {              foreach my $status (@{$types}) {
             push(@posstypes,'default');                  $datatable .= &modifiable_userdata_row('selfcreate',$status,$domconf{'usermodification'},
         }                                                         $numinrow,$$rowtotal,$usertypes);
         my %usertypeshash;                  $$rowtotal ++;
         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 {      } else {
         my %choices = &Apache::lonlocal::texthash (          my %choices = &Apache::lonlocal::texthash (
                           'cancreate_email' => 'Non-institutional username (via e-mail verification)',                                                        cancreate_email => 'E-mail address as username',
                                                   );                                                    );
         my @toggles = sort(keys(%choices));          my @toggles = sort(keys(%choices));
         my %defaultchecked = (          my %defaultchecked = (
                                'cancreate_email' => 'off',                                 'cancreate_email' => 'off',
                              );                               );
         my $customclass = 'LC_selfcreate_email';          my $itemcount = 0;
         my $classprefix = 'LC_canmodify_emailusername_';  
         my $optionsprefix = 'LC_options_emailusername_';  
         my $display = 'none';          my $display = 'none';
         my $rowstyle = 'display:none';  
         if (grep(/^\Qemail\E$/,@selfcreate)) {          if (grep(/^\Qemail\E$/,@selfcreate)) {
             $display = 'block';              $display = 'block';
             $rowstyle = 'display:table-row';  
         }          }
         my $onclick = "toggleRows(this.form,'cancreate_email','selfassign','$customclass','$classprefix','$optionsprefix');";          my $onclick = "toggleDisplay(this.form,'emailoptions');";
         ($datatable,$$rowtotal) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,          my $additional = '<div id="emailoptions" style="display: '.$display.'">';
                                                      \%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 %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
         my ($emailrules,$emailruleorder) =          my $usertypes = {};
             &Apache::lonnet::inst_userrules($dom,'email');          my $order = [];
         my $primary_id = &Apache::lonnet::domain($dom,'primary');          if ((ref($domdefaults{'inststatustypes'}) eq 'HASH') && (ref($domdefaults{'inststatusguest'}) eq 'ARRAY')) {
         my $intdom = &Apache::lonnet::internet_dom($primary_id);              $usertypes = $domdefaults{'inststatustypes'};
         if (ref($types) eq 'ARRAY') {              $order = $domdefaults{'inststatusguest'};
             @posstypes = @{$types};          }
         }          if (ref($order) eq 'ARRAY') {
         if (@posstypes) {              push(@{$order},'default');
             unless (grep(/^default$/,@posstypes)) {              if (@{$order} > 1) {
                 push(@posstypes,'default');                  $usertypes->{'default'} = &mt('Other users');
             }                  $additional .= '<table><tr>';
             if (ref($usertypes) eq 'HASH') {                  foreach my $status (@{$order}) {
                 %usertypeshash = %{$usertypes};                      $additional .= '<th>'.$usertypes->{$status}.'</th>';
             }                  }
             my $currassign;                  $additional .= '</tr><tr>';
             if (ref($domdefaults{'inststatusguest'}) eq 'ARRAY') {                  foreach my $status (@{$order}) {
                 $currassign = {                      $additional .= '<td>'.&email_as_username($rowtotal,$processing,$status).'</td>';
                                   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 ++;  
                 }                  }
                   $additional .= '</tr></table>';
               } else {
                   $usertypes->{'default'} = &mt('All users');
                   $additional .= &email_as_username($rowtotal,$processing);
             }              }
         } 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 ++;  
         }          }
           $additional .= '</div>'."\n";
   
           ($datatable,$itemcount) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,
                                                        \%choices,$$rowtotal,$onclick,$additional);
           $$rowtotal ++;
           $datatable .= &print_requestmail($dom,'selfcreation',$createsettings,$rowtotal);
           $$rowtotal ++;
         my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();          my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();
         $numinrow = 1;          $numinrow = 1;
         if (@posstypes) {          if (ref($order) eq 'ARRAY') {
             foreach my $status (@posstypes) {              foreach my $status (@{$order}) {
                 my $rowid = $classprefix.$status;  
                 my $datarowstyle = 'display:none';  
                 if (grep(/^\Q$status\E$/,@ordered)) {  
                     $datarowstyle = $rowstyle;  
                 }  
                 $datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,                  $datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,
                                                        $numinrow,$$rowtotal,\%usertypeshash,$infofields,                                                         $numinrow,$$rowtotal,$usertypes,$infofields,$infotitles);
                                                        $infotitles,$rowid,$customclass,$datarowstyle);                  $$rowtotal ++;
                 unless ($datarowstyle eq 'display:none') {  
                     $$rowtotal ++;  
                 }  
             }              }
         } else {  
             $datatable .= &modifiable_userdata_row('cancreate','emailusername_default',$settings,  
                                                    $numinrow,$$rowtotal,\%usertypeshash,$infofields,  
                                                    $infotitles,'',$customclass,$rowstyle);  
         }          }
     }          my ($emailrules,$emailruleorder) =
     return $datatable;              &Apache::lonnet::inst_userrules($dom,'email');
 }          if (ref($emailrules) eq 'HASH') {
               if (keys(%{$emailrules}) > 0) {
 sub selfcreate_javascript {                  $datatable .= &user_formats_row('email',$settings,$emailrules,
     return <<"ENDSCRIPT";                                                  $emailruleorder,$numinrow,$$rowtotal);
                   $$rowtotal ++;
 <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);  
             }              }
         }          }
           $datatable .= &captcha_choice('cancreate',$createsettings,$$rowtotal);
     }      }
     return;      return $datatable;
 }  }
   
 function toggleDataRow(form,checkbox,target,prefix,docount) {  sub email_as_username {
     if (form.elements[checkbox].length != undefined) {      my ($rowtotal,$processing,$type) = @_;
         var count = 0;      my %choices =
         if (docount) {          &Apache::lonlocal::texthash (
             for (var i=0; i<form.elements[checkbox].length; i++) {                                        automatic => 'Automatic approval',
                 if (form.elements[checkbox][i].checked) {                                        approval  => 'Queued for approval',
                     count ++;                                      );
                 }      my $output;
             }      foreach my $option ('automatic','approval') {
         }          my $checked;
         for (var i=0; i<form.elements[checkbox].length; i++) {          if (ref($processing) eq 'HASH') {
             var type = form.elements[checkbox][i].value;              if ($type eq '') {   
             if (document.getElementById(prefix+type)) {                  if (!exists($processing->{'default'})) {
                 if (form.elements[checkbox][i].checked) {                      if ($option eq 'automatic') {
                     document.getElementById(prefix+type).style.display = 'table-row';                          $checked = ' checked="checked"';
                     if (count % 2 == 1) {  
                         document.getElementById(prefix+type).className = target+' LC_odd_row';  
                     } else {  
                         document.getElementById(prefix+type).className = target;  
                     }                      }
                     count ++;  
                 } else {                  } else {
                     document.getElementById(prefix+type).style.display = 'none';                      if ($processing->{'default'} eq $option) {
                 }                          $checked = ' checked="checked"';
             }  
         }  
     }  
     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 ++;  
                                     }  
                                 }  
                             }  
                         }  
                     }                      }
                 }                  }
             }              } else {
             $onclick = ' onclick="toggleEmailOptions(this.form,'."'cancreate_emailoptions','$showcustom',".                  if (!exists($processing->{$type})) {
                                                      "'cancreate_emaildomain','$type'".');"';                      if ($option eq 'automatic') {
             $hashref = $emailoptions;                          $checked = ' checked="checked"';
             $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 {                  } else {
                     if (!exists($hashref->{$type})) {                      if ($processing->{$type} eq $option) {
                         if ($option eq $defoption) {                          $checked = ' checked="checked"';
                             $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>';  
                 }                  }
             }              }
           } elsif ($option eq 'automatic') {
               $checked = ' checked="checked"'; 
           }
           my $name = 'cancreate_emailprocess';
           if (($type ne '') && ($type ne 'default')) {
               $name .= '_'.$type;
           }
           $output .= '<span class="LC_nobreak"><label>'.
                      '<input type="radio" name="'.$name.'"'.
                      $checked.' value="'.$option.'" />'.
                      $choices{$option}.'</label></span>';
           if ($type eq '') {
               $output .= '&nbsp;';
           } else {
               $output .= '<br />';
         }          }
         $output .= '</td>'."\n";  
     }      }
     $output .= "</tr></table></td></tr>\n";      $$rowtotal ++;
     return $output;      return $output;
 }  }
   
 sub captcha_choice {  sub captcha_choice {
     my ($context,$settings,$itemcount,$customcss,$rowstyle) = @_;      my ($context,$settings,$itemcount) = @_;
     my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext,      my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext,
         $vertext,$currver);           $vertext,$currver);
     my %lt = &captcha_phrases();      my %lt = &captcha_phrases();
     $keyentry = 'hidden';      $keyentry = 'hidden';
     my $colspan=2;  
     if ($context eq 'cancreate') {      if ($context eq 'cancreate') {
         $rowname = &mt('CAPTCHA validation');          $rowname = &mt('CAPTCHA validation');
     } elsif ($context eq 'login') {      } elsif ($context eq 'login') {
         $rowname =  &mt('"Contact helpdesk" CAPTCHA validation');          $rowname =  &mt('"Contact helpdesk" CAPTCHA validation');
     } elsif ($context eq 'passwords') {  
         $rowname = &mt('"Forgot Password" CAPTCHA validation');  
         $colspan=1;  
     }      }
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if ($settings->{'captcha'}) {          if ($settings->{'captcha'}) {
Line 6247  sub captcha_choice { Line 5969  sub captcha_choice {
     } else {      } else {
         $checked{'original'} = ' checked="checked"';          $checked{'original'} = ' checked="checked"';
     }      }
     my $css_class;      my $css_class = $itemcount%2?' class="LC_odd_row"':'';
     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.'>'.      my $output = '<tr'.$css_class.'>'.
                  '<td class="LC_left_item">'.$rowname.'</td><td class="LC_left_item" colspan="'.$colspan.'">'."\n".                   '<td class="LC_left_item">'.$rowname.'</td><td class="LC_left_item" colspan="2">'."\n".
                  '<table><tr><td>'."\n";                   '<table><tr><td>'."\n";
     foreach my $option ('original','recaptcha','notused') {      foreach my $option ('original','recaptcha','notused') {
         $output .= '<span class="LC_nobreak"><label><input type="radio" name="'.$context.'_captcha" value="'.          $output .= '<span class="LC_nobreak"><label><input type="radio" name="'.$context.'_captcha" value="'.
Line 6279  sub captcha_choice { Line 5988  sub captcha_choice {
 # specified for use with the key should be broad enough to accommodate all servers in the LON-CAPA domain.  # specified for use with the key should be broad enough to accommodate all servers in the LON-CAPA domain.
 #  #
     $output .= '</td></tr>'."\n".      $output .= '</td></tr>'."\n".
                '<tr><td class="LC_zero_height">'."\n".                 '<tr><td>'."\n".
                '<span class="LC_nobreak"><span id="'.$context.'_recaptchapubtxt">'.$pubtext.'</span>&nbsp;'."\n".                 '<span class="LC_nobreak"><span id="'.$context.'_recaptchapubtxt">'.$pubtext.'</span>&nbsp;'."\n".
                '<input type="'.$keyentry.'" id="'.$context.'_recaptchapub" name="'.$context.'_recaptchapub" value="'.                 '<input type="'.$keyentry.'" id="'.$context.'_recaptchapub" name="'.$context.'_recaptchapub" value="'.
                $currpub.'" size="40" /></span><br />'."\n".                 $currpub.'" size="40" /></span><br />'."\n".
Line 6295  sub captcha_choice { Line 6004  sub captcha_choice {
 }  }
   
 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 6038  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 6499  sub print_defaults { Line 6196  sub print_defaults {
             $datatable .= '</td></tr>';              $datatable .= '</td></tr>';
             $rownum ++;              $rownum ++;
         }          }
       } elsif ($position eq 'middle') {
           my @items = ('intauth_cost','intauth_check','intauth_switch');
           my %defaults;
           if (ref($settings) eq 'HASH') {
               %defaults = %{$settings};
               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 ($rownum%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 wisth="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>';
               $rownum ++;
           }
     } else {      } else {
         my %defaults;          my %defaults;
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {              if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH') &&
                   (ref($settings->{'inststatusguest'}) eq 'ARRAY')) {
                 my $maxnum = @{$settings->{'inststatusorder'}};                  my $maxnum = @{$settings->{'inststatusorder'}};
                 for (my $i=0; $i<$maxnum; $i++) {                  for (my $i=0; $i<$maxnum; $i++) {
                     $css_class = $rownum%2?' class="LC_odd_row"':'';                      $css_class = $rownum%2?' class="LC_odd_row"':'';
                     my $item = $settings->{'inststatusorder'}->[$i];                      my $item = $settings->{'inststatusorder'}->[$i];
                     my $title = $settings->{'inststatustypes'}->{$item};                      my $title = $settings->{'inststatustypes'}->{$item};
                       my $guestok;
                       if (grep(/^\Q$item\E$/,@{$settings->{'inststatusguest'}})) {
                           $guestok = 1;
                       }
                     my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'$item'".');"';                      my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'$item'".');"';
                     $datatable .= '<tr'.$css_class.'>'.                      $datatable .= '<tr'.$css_class.'>'.
                                   '<td><span class="LC_nobreak">'.                                    '<td><span class="LC_nobreak">'.
Line 6520  sub print_defaults { Line 6301  sub print_defaults {
                         }                          }
                         $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';                          $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                     }                      }
                       my ($checkedon,$checkedoff);
                       $checkedoff = ' checked="checked"';
                       if ($guestok) {
                           $checkedon = $checkedoff;
                           $checkedoff = ''; 
                       }
                     $datatable .= '</select>&nbsp;'.&mt('Internal ID:').'&nbsp;<b>'.$item.'</b>&nbsp;'.                      $datatable .= '</select>&nbsp;'.&mt('Internal ID:').'&nbsp;<b>'.$item.'</b>&nbsp;'.
                                   '<input type="checkbox" name="inststatus_delete" value="'.$item.'" />'.                                    '<input type="checkbox" name="inststatus_delete" value="'.$item.'" />'.
                                   &mt('delete').'</span></td>'.                                    &mt('delete').'</span></td>'.
                                   '<td class="LC_left_item"><span class="LC_nobreak">'.&mt('Name displayed:').                                    '<td class="LC_left_item"><span class="LC_nobreak">'.&mt('Name displayed:').
                                   '<input type="text" size="20" name="inststatus_title_'.$item.'" value="'.$title.'" />'.                                    '<input type="text" size="20" name="inststatus_title_'.$item.'" value="'.$title.'" />'.
                                   '</span></td></tr>';                                    '</span></td>'.
                                     '<td class="LC_right_item"><span class="LC_nobreak">'.
                                     '<label><input type="radio" value="1" name="inststatus_guest_'.$item.'"'.$checkedon.' />'.
                                     &mt('Yes').'</label>'.('&nbsp;'x2).
                                     '<label><input type="radio" value="0" name="inststatus_guest_'.$item.'"'.$checkedoff.' />'.
                                     &mt('No').'</label></span></td></tr>';
                 }                  }
                 $css_class = $rownum%2?' class="LC_odd_row"':'';                  $css_class = $rownum%2?' class="LC_odd_row"':'';
                 my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'addinststatus_pos'".');"';                  my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'addinststatus_pos'".');"';
Line 6545  sub print_defaults { Line 6337  sub print_defaults {
                               '</span></td><td class="LC_left_item"><span class="LC_nobreak">'.                                '</span></td><td class="LC_left_item"><span class="LC_nobreak">'.
                               &mt('Name displayed:').                                &mt('Name displayed:').
                               '<input type="text" size="20" name="addinststatus_title" value="" /></span></td>'.                                '<input type="text" size="20" name="addinststatus_title" value="" /></span></td>'.
                                 '<td class="LC_right_item"><span class="LC_nobreak">'.
                                 '<label><input type="radio" value="1" name="addinststatus_guest" />'.
                                 &mt('Yes').'</label>'.('&nbsp;'x2).
                                 '<label><input type="radio" value="0" name="addinststatus_guest" />'.
                                 &mt('No').'</label></span></td></tr>';
                               '</tr>'."\n";                                '</tr>'."\n";
                 $rownum ++;                  $rownum ++;
             }              }
Line 6591  sub defaults_titles { Line 6388  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 6414  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 6424  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 6435  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 6816  sub legacy_scantronformat { Line 6561  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;
Line 6981  sub print_coursecategories { Line 6603  sub print_coursecategories {
                              '<input type="radio" name="coursecat_'.$item.'" value="'.$type.'"'.$ischecked.                               '<input type="radio" name="coursecat_'.$item.'" value="'.$type.'"'.$ischecked.
                              ' />'.$lt{$type}.'</label>&nbsp;';                               ' />'.$lt{$type}.'</label>&nbsp;';
            }             }
            $datatable .= '</span></td></tr>';             $datatable .= '</td></tr>';
            $itemcount ++;             $itemcount ++;
         }          }
         $$rowtotal += $itemcount;          $$rowtotal += $itemcount;
Line 6994  sub print_coursecategories { Line 6616  sub print_coursecategories {
         my $toggle_catscomm_dom = ' checked="checked" ';          my $toggle_catscomm_dom = ' checked="checked" ';
         my $can_catcomm_comm = ' ';          my $can_catcomm_comm = ' ';
         my $can_catcomm_dom = ' checked="checked" ';          my $can_catcomm_dom = ' checked="checked" ';
           my $toggle_catsplace_place = ' ';
           my $toggle_catsplace_dom = ' checked="checked" ';
           my $can_catplace_place = ' ';
           my $can_catplace_dom = ' checked="checked" ';
   
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if ($settings->{'togglecats'} eq 'crs') {              if ($settings->{'togglecats'} eq 'crs') {
Line 7012  sub print_coursecategories { Line 6638  sub print_coursecategories {
                 $can_catcomm_comm = $can_catcomm_dom;                  $can_catcomm_comm = $can_catcomm_dom;
                 $can_catcomm_dom = ' ';                  $can_catcomm_dom = ' ';
             }              }
               if ($settings->{'togglecatsplace'} eq 'place') {
                   $toggle_catsplace_place = $toggle_catsplace_dom;
                   $toggle_catsplace_dom = ' ';
               }
               if ($settings->{'categorizeplace'} eq 'place') {
                   $can_catplace_place = $can_catplace_dom;
                   $can_catplace_dom = ' ';
               }
         }          }
         my %title = &Apache::lonlocal::texthash (          my %title = &Apache::lonlocal::texthash (
                      togglecats     => 'Show/Hide a course in catalog',                       togglecats      => 'Show/Hide a course in catalog',
                      togglecatscomm => 'Show/Hide a community in catalog',                       togglecatscomm  => 'Show/Hide a community in catalog',
                      categorize     => 'Assign a category to a course',                       togglecatsplace => 'Show/Hide a placement test in catalog',
                      categorizecomm => 'Assign a category to a community',                       categorize      => 'Assign a category to a course',
                        categorizecomm  => 'Assign a category to a community',
                        categorizeplace => 'Assign a category to a placement test',
                     );                      );
         my %level = &Apache::lonlocal::texthash (          my %level = &Apache::lonlocal::texthash (
                      dom  => 'Set in Domain',                       dom   => 'Set in Domain',
                      crs  => 'Set in Course',                       crs   => 'Set in Course',
                      comm => 'Set in Community',                       comm  => 'Set in Community',
                        place => 'Set in Placement Test',
                     );                      );
         $datatable = '<tr class="LC_odd_row">'.          $datatable = '<tr class="LC_odd_row">'.
                   '<td>'.$title{'togglecats'}.'</td>'.                    '<td>'.$title{'togglecats'}.'</td>'.
Line 7052  sub print_coursecategories { Line 6689  sub print_coursecategories {
                   $can_catcomm_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.                    $can_catcomm_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.
                   '<label><input type="radio" name="categorizecomm"'.                    '<label><input type="radio" name="categorizecomm"'.
                   $can_catcomm_comm.'value="comm" />'.$level{'comm'}.'</label></span></td>'.                    $can_catcomm_comm.'value="comm" />'.$level{'comm'}.'</label></span></td>'.
                     '</tr><tr>'.
                     '<td>'.$title{'togglecatsplace'}.'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                     '<input type="radio" name="togglecatsplace"'.
                     $toggle_catsplace_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.
                     '<label><input type="radio" name="togglecatscomm"'.
                     $toggle_catsplace_place.' value="comm" />'.$level{'place'}.'</label></span></td>'.
                     '</tr><tr>'.
                     '<td>'.$title{'categorizeplace'}.'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak">'.
                     '<label><input type="radio" name="categorizeplace"'.
                     $can_catplace_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.
                     '<label><input type="radio" name="categorizeplace"'.
                     $can_catplace_place.'value="place" />'.$level{'place'}.'</label></span></td>'.
                   '</tr>';                    '</tr>';
         $$rowtotal += 4;          $$rowtotal += 6;
     } else {      } else {
         my $css_class;          my $css_class;
         my $itemcount = 1;          my $itemcount = 1;
Line 7078  sub print_coursecategories { Line 6729  sub print_coursecategories {
                     my %default_names = (                      my %default_names = (
                           instcode    => &mt('Official courses'),                            instcode    => &mt('Official courses'),
                           communities => &mt('Communities'),                            communities => &mt('Communities'),
                             placement   => &mt('Placement Tests'),
                     );                      );
   
                     if ((!grep(/^instcode$/,@{$cats[0]})) ||                       if ((!grep(/^instcode$/,@{$cats[0]})) || 
                         ($cathash->{'instcode::0'} eq '') ||                          ($cathash->{'instcode::0'} eq '') ||
                         (!grep(/^communities$/,@{$cats[0]})) ||                           (!grep(/^communities$/,@{$cats[0]})) || 
                         ($cathash->{'communities::0'} eq '')) {                          ($cathash->{'communities::0'} eq '') ||
                           (!grep(/^placement$/,@{$cats[0]})) ||
                           ($cathash->{'placement::0'} eq '')) {
                         $maxnum ++;                          $maxnum ++;
                     }                      }
                     my $lastidx;                      my $lastidx;
Line 7104  sub print_coursecategories { Line 6758  sub print_coursecategories {
                             $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';                              $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                         }                          }
                         $datatable .= '</select></span></td><td>';                          $datatable .= '</select></span></td><td>';
                         if ($parent eq 'instcode' || $parent eq 'communities') {                          if ($parent eq 'instcode' || $parent eq 'communities' || $parent eq 'placement') {
                             $datatable .=  '<span class="LC_nobreak">'                              $datatable .=  '<span class="LC_nobreak">'
                                            .$default_names{$parent}.'</span>';                                             .$default_names{$parent}.'</span>';
                             if ($parent eq 'instcode') {                              if ($parent eq 'instcode') {
Line 7127  sub print_coursecategories { Line 6781  sub print_coursecategories {
                             $datatable .= '<label><input type="radio" name="'                              $datatable .= '<label><input type="radio" name="'
                                           .$parent.'" value="0" />'                                            .$parent.'" value="0" />'
                                           .&mt('Do not display').'</label></span>';                                            .&mt('Do not display').'</label></span>';
                             if ($parent eq 'communities') {                              if (($parent eq 'communities') || ($parent eq 'placement')) {
                                 $datatable .= '</td></tr></table>';                                  $datatable .= '</td></tr></table>';
                             }                              }
                             $datatable .= '</td>';                              $datatable .= '</td>';
Line 7159  sub print_coursecategories { Line 6813  sub print_coursecategories {
                                   .'<input type="text" size="20" name="addcategory_name" value="" /></td>'                                    .'<input type="text" size="20" name="addcategory_name" value="" /></td>'
                                   .'</tr>'."\n";                                    .'</tr>'."\n";
                     $itemcount ++;                      $itemcount ++;
                     foreach my $default ('instcode','communities') {                      foreach my $default ('instcode','communities','placement') {
                         if ((!grep(/^\Q$default\E$/,@{$cats[0]})) || ($cathash->{$default.'::0'} eq '')) {                          if ((!grep(/^\Q$default\E$/,@{$cats[0]})) || ($cathash->{$default.'::0'} eq '')) {
                             $css_class = $itemcount%2?' class="LC_odd_row"':'';                              $css_class = $itemcount%2?' class="LC_odd_row"':'';
                             my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','$lastidx'".');"';                              my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','$lastidx'".');"';
Line 7192  sub print_coursecategories { Line 6846  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'}->[1]->{'col2'}.'</td>'
                           .&initialize_categories($itemcount);                            .&initialize_categories($itemcount);
         }          }
         $$rowtotal += $itemcount;          $$rowtotal += $itemcount;
Line 7240  sub print_serverstatuses { Line 6894  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 6902  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',              'checksums','clusterstatus','certstatus','metadata_keywords',
             'takeoffline','takeonline','showenv','toggledebug','ping','domconf',              'metadata_harvest','takeoffline','takeonline','showenv','toggledebug',
             'uniquecodes','diskusage','coursecatalog');              'ping','domconf','uniquecodes','diskusage','coursecatalog');
 }  }
   
 sub defaults_javascript {  sub defaults_javascript {
     my ($settings) = @_;      my ($settings) = @_;
     return unless (ref($settings) eq 'HASH');      my $intauthcheck = &mt('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.');
       my $intauthcost = &mt('Warning: bcrypt encryption cost for internal authentication must be an integer.');
       &js_escape(\$intauthcheck);
       &js_escape(\$intauthcost);
       my $intauthjs = <<"ENDSCRIPT";
   
   function warnIntAuth(field) {
       if (field.name == 'intauth_check') {
           if (field.value == '2') {
               alert('$intauthcheck');
           }
       }
       if (field.name == 'intauth_cost') {
           field.value.replace(/\s/g,'');
           if (field.value != '') {
               var regexdigit=/^\\d+\$/;
               if (!regexdigit.test(field.value)) {
                   alert('$intauthcost');
               }
           }
       }
       return;
   }
   
   ENDSCRIPT
   
       if (ref($settings) ne 'HASH') {
           return &Apache::lonhtmlcommon::scripttag($intauthjs);
       }
     if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {      if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {
         my $maxnum = scalar(@{$settings->{'inststatusorder'}});          my $maxnum = scalar(@{$settings->{'inststatusorder'}});
         if ($maxnum eq '') {          if ($maxnum eq '') {
Line 7309  $jstext Line 6991  $jstext
     return;      return;
 }  }
   
   $intauthjs
   
 // ]]>  // ]]>
 </script>  </script>
   
 ENDSCRIPT  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 {      } else {
         if (field.value == '0') {          return &Apache::lonhtmlcommon::scripttag($intauthjs);
             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 7428  sub coursecategories_javascript { Line 7026  sub coursecategories_javascript {
     }      }
     my $instcode_reserved = &mt('The name: [_1] is a reserved category.','"instcode"');      my $instcode_reserved = &mt('The name: [_1] is a reserved category.','"instcode"');
     my $communities_reserved = &mt('The name: [_1] is a reserved category.','"communities"');      my $communities_reserved = &mt('The name: [_1] is a reserved category.','"communities"');
       my $placement_reserved = &mt('The name: [_1] is a reserved category.','"placement"');
     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(\$instcode_reserved);
     &js_escape(\$communities_reserved);      &js_escape(\$communities_reserved);
       &js_escape(\$placement_reserved);
     &js_escape(\$choose_again);      &js_escape(\$choose_again);
     $output = <<"ENDSCRIPT";      $output = <<"ENDSCRIPT";
 <script type="text/javascript">  <script type="text/javascript">
Line 7500  function categoryCheck(form) { Line 7100  function categoryCheck(form) {
         alert('$communities_reserved\\n$choose_again');          alert('$communities_reserved\\n$choose_again');
         return false;          return false;
     }      }
       if (form.elements['addcategory_name'].value == 'placement') {
           alert('$placement_reserved\\n$choose_again');
           return false;
       }
     return true;      return true;
 }  }
   
Line 7516  sub initialize_categories { Line 7120  sub initialize_categories {
     my %default_names = (      my %default_names = (
                       instcode    => 'Official courses (with institutional codes)',                        instcode    => 'Official courses (with institutional codes)',
                       communities => 'Communities',                        communities => 'Communities',
                         placement   => 'Placement Tests',
                         );                          );
     my $select0 = ' selected="selected"';      my $select0 = ' selected="selected"';
     my $select1 = '';      my $select1 = '';
     foreach my $default ('instcode','communities') {      foreach my $default ('instcode','communities','placement') {
         $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') || ($default eq 'placement')) {
             $select1 = $select0;              $select1 = $select0;
             $select0 = '';              $select0 = '';
         }          }
Line 7546  sub initialize_categories { Line 7151  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 7603  sub build_category_rows { Line 7207  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 7230  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 7239  sub build_category_rows {
 }  }
   
 sub modifiable_userdata_row {  sub modifiable_userdata_row {
     my ($context,$item,$settings,$numinrow,$rowcount,$usertypes,$fieldsref,$titlesref,      my ($context,$item,$settings,$numinrow,$rowcount,$usertypes,$fieldsref,$titlesref) = @_;
         $rowid,$customcss,$rowstyle) = @_;  
     my ($role,$rolename,$statustype);      my ($role,$rolename,$statustype);
     $role = $item;      $role = $item;
     if ($context eq 'cancreate') {      if ($context eq 'cancreate') {
         if ($item =~ /^(emailusername)_(.+)$/) {          if ($item =~ /^emailusername_(.+)$/) {
             $role = $1;              $statustype = $1;
             $statustype = $2;              $role = 'emailusername';
             if (ref($usertypes) eq 'HASH') {              if (ref($usertypes) eq 'HASH') {
                 if ($usertypes->{$statustype}) {                  if ($usertypes->{$statustype}) {
                     $rolename = &mt('Data provided by [_1]',$usertypes->{$statustype});                      $rolename = &mt('Data provided by [_1]',$usertypes->{$statustype});
Line 7677  sub modifiable_userdata_row { Line 7280  sub modifiable_userdata_row {
         %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();          %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 7729  sub modifiable_userdata_row { Line 7315  sub modifiable_userdata_row {
             }              }
         }          }
     }      }
        
     my $total = scalar(@fields);      for (my $i=0; $i<@fields; $i++) {
     for (my $i=0; $i<$total; $i++) {          my $rem = $i%($numinrow);
         $rem = $i%($numinrow);  
         if ($rem == 0) {          if ($rem == 0) {
             if ($i > 0) {              if ($i > 0) {
                 $output .= '</tr>';                  $output .= '</tr>';
Line 7742  sub modifiable_userdata_row { Line 7327  sub modifiable_userdata_row {
         my $check = ' ';          my $check = ' ';
         unless ($role eq 'emailusername') {          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') {
Line 7774  sub modifiable_userdata_row { Line 7359  sub modifiable_userdata_row {
                        '</label>';                         '</label>';
         }          }
         $output .= '</span></td>';          $output .= '</span></td>';
           $rem = @fields%($numinrow);
     }      }
     $rem = $total%$numinrow;      my $colsleft = $numinrow - $rem;
     my $colsleft;      if ($colsleft > 1 ) {
     if ($rem) {  
         $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 7373  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,$rownum) = @_;
         $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') {
Line 7808  sub insttypes_row { Line 7387  sub insttypes_row {
     if ($context eq 'statustocreate') {      if ($context eq 'statustocreate') {
         $class = 'LC_right_item';          $class = 'LC_right_item';
     }      }
     my $css_class;      my $css_class = ' class="LC_odd_row"';
     if ($$rowtotal%2) {      if ($rownum ne '') { 
         $css_class = 'LC_odd_row';          $css_class = ($rownum%2? ' 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.'>'.      my $output = '<tr'.$css_class.'>'.
                  '<td>'.$lt{$context}.$showdom.                   '<td>'.$lt{$context}.$showdom.
Line 7845  sub insttypes_row { Line 7411  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 7418  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 8854  sub check_configuser { Line 8407  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 8883  sub check_authorstatus { Line 8436  sub check_authorstatus {
   
 sub publishlogo {  sub publishlogo {
     my ($r,$action,$formname,$dom,$confname,$subdir,$thumbwidth,$thumbheight,$savefileas) = @_;      my ($r,$action,$formname,$dom,$confname,$subdir,$thumbwidth,$thumbheight,$savefileas) = @_;
     my ($output,$fname,$logourl);      my ($output,$fname,$logourl,$madethumb);
     if ($action eq 'upload') {      if ($action eq 'upload') {
         $fname=$env{'form.'.$formname.'.filename'};          $fname=$env{'form.'.$formname.'.filename'};
         chop($env{'form.'.$formname});          chop($env{'form.'.$formname});
Line 8928  sub publishlogo { Line 8481  sub publishlogo {
     } 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 Authoring 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 8996  $env{'user.name'}.':'.$env{'user.domain' Line 8549  $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 9012  $env{'user.name'}.':'.$env{'user.domain' Line 8564  $env{'user.name'}.':'.$env{'user.domain'
                                     $r->set_handlers('PerlCleanupHandler' => [\&notifysubscribed,@{$handlers}]);                                      $r->set_handlers('PerlCleanupHandler' => [\&notifysubscribed,@{$handlers}]);
                                     $registered_cleanup=1;                                      $registered_cleanup=1;
                                 }                                  }
                                   $madethumb = 1;
                             } else {                              } else {
                                 print $logfile "\nUnable to write ".$copyfile.                                  print $logfile "\nUnable to write ".$copyfile.
                                                ':'.$!."\n";                                                 ':'.$!."\n";
Line 9024  $env{'user.name'}.':'.$env{'user.domain' Line 8577  $env{'user.name'}.':'.$env{'user.domain'
             $output = $versionresult;              $output = $versionresult;
         }          }
     }      }
     return ($output,$logourl);      return ($output,$logourl,$madethumb);
 }  }
   
 sub logo_versioning {  sub logo_versioning {
Line 9076  sub write_metadata { Line 8629  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=$_;
Line 9110  sub notifysubscribed { Line 8663  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 8689  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 9178  sub modify_quotas { Line 8731  sub modify_quotas {
         $context = $action;          $context = $action;
     }      }
     if ($context eq 'requestcourses') {      if ($context eq 'requestcourses') {
         @usertools = ('official','unofficial','community','textbook');          @usertools = ('official','unofficial','community','textbook','placement');
         @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();
Line 9227  sub modify_quotas { Line 8780  sub modify_quotas {
         my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval');          my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval');
         @approvalnotify = sort(@approvalnotify);          @approvalnotify = sort(@approvalnotify);
         $confhash{'notify'}{'approval'} = join(',',@approvalnotify);          $confhash{'notify'}{'approval'} = join(',',@approvalnotify);
         my @crstypes = ('official','unofficial','community','textbook');          my @crstypes = ('official','unofficial','community','textbook','placement');
         my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');          my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');
         foreach my $type (@hasuniquecode) {          foreach my $type (@hasuniquecode) {
             if (grep(/^\Q$type\E$/,@crstypes)) {              if (grep(/^\Q$type\E$/,@crstypes)) {
Line 9335  sub modify_quotas { Line 8888  sub modify_quotas {
                                     #FIXME need to obsolete item in RES space                                      #FIXME need to obsolete item in RES space
                                 } elsif ($env{'form.'.$type.'_image_'.$i.'.filename'}) {                                  } elsif ($env{'form.'.$type.'_image_'.$i.'.filename'}) {
                                     my ($cdom,$cnum) = split(/_/,$key);                                      my ($cdom,$cnum) = split(/_/,$key);
                                     if (&Apache::lonnet::homeserver($cnum,$cdom) eq 'no_host') {                                      my ($imgurl,$error) = &process_textbook_image($r,$dom,$confname,$type.'_image_'.$i,
                                         $errors .= '<li><span class="LC_error">'.&mt('Image not saved: could not find textbook course').'</li>';                                                                                    $cdom,$cnum,$type,$configuserok,
                                     } else {                                                                                    $switchserver,$author_ok);
                                         my ($imgurl,$error) = &process_textbook_image($r,$dom,$confname,$type.'_image_'.$i,                                      if ($imgurl) {
                                                                                       $cdom,$cnum,$type,$configuserok,                                          $confhash{$type}{$key}{'image'} = $imgurl;
                                                                                       $switchserver,$author_ok);                                          $changes{$type}{$key} = 1; 
                                         if ($imgurl) {                                      }
                                             $confhash{$type}{$key}{'image'} = $imgurl;                                      if ($error) {
                                             $changes{$type}{$key} = 1;                                           &Apache::lonnet::logthis($error);
                                         }                                          $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                                         if ($error) {  
                                             &Apache::lonnet::logthis($error);  
                                             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';  
                                         }  
                                     }                                       } 
                                 } elsif ($domconfig{$action}{$type}{$key}{'image'}) {                                  } elsif ($domconfig{$action}{$type}{$key}{'image'}) {
                                     $confhash{$type}{$key}{'image'} =                                       $confhash{$type}{$key}{'image'} = 
Line 9382  sub modify_quotas { Line 8931  sub modify_quotas {
                     if ($type eq 'textbooks') {                      if ($type eq 'textbooks') {
                         if ($env{'form.'.$type.'_addbook_image.filename'} ne '') {                          if ($env{'form.'.$type.'_addbook_image.filename'} ne '') {
                             my ($cdom,$cnum) = split(/_/,$newbook{$type});                              my ($cdom,$cnum) = split(/_/,$newbook{$type});
                             if (&Apache::lonnet::homeserver($cnum,$cdom) eq 'no_host') {                              my ($imageurl,$error) =
                                 $errors .= '<li><span class="LC_error">'.&mt('Image not saved: could not find textbook course').'</li>';                                  &process_textbook_image($r,$dom,$confname,$type.'_addbook_image',$cdom,$cnum,$type,
                             } else {                                                          $configuserok,$switchserver,$author_ok);
                                 my ($imageurl,$error) =                              if ($imageurl) {
                                     &process_textbook_image($r,$dom,$confname,$type.'_addbook_image',$cdom,$cnum,$type,                                  $confhash{$type}{$newbook{$type}}{'image'} = $imageurl;
                                                             $configuserok,$switchserver,$author_ok);                              }
                                 if ($imageurl) {                              if ($error) {
                                     $confhash{$type}{$newbook{$type}}{'image'} = $imageurl;                                  &Apache::lonnet::logthis($error);
                                 }                                  $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                                 if ($error) {  
                                     &Apache::lonnet::logthis($error);  
                                     $errors .= '<li><span class="LC_error">'.$error.'</span></li>';  
                                 }  
                             }                              }
                         }                          }
                     }                      }
Line 9886  sub process_textbook_image { Line 9431  sub process_textbook_image {
         } elsif ($author_ok eq 'ok') {          } elsif ($author_ok eq 'ok') {
             my ($result,$imageurl) =              my ($result,$imageurl) =
                 &publishlogo($r,'upload',$caller,$dom,$confname,                  &publishlogo($r,'upload',$caller,$dom,$confname,
                              "$type/$cdom/$cnum/cover",$width,$height);                               "$type/$dom/$cnum/cover",$width,$height);
             if ($result eq 'ok') {              if ($result eq 'ok') {
                 $url = $imageurl;                  $url = $imageurl;
             } else {              } else {
Line 9901  sub process_textbook_image { Line 9446  sub process_textbook_image {
     return ($url,$error);      return ($url,$error);
 }  }
   
   sub modify_ltitools {
       my ($r,$dom,$action,$lastactref,%domconfig) = @_;
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
       my ($newid,@allpos,%changes,%confhash,$errors,$resulttext);
       my $confname = $dom.'-domainconfig';
       my $servadm = $r->dir_config('lonAdmEMail');
       my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
       my (%posslti,%possfield);
       my @courseroles = ('cc','in','ta','ep','st');
       my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner);
       map { $posslti{$_} = 1; } @ltiroles;
       my @allfields = ('fullname','firstname','lastname','email','user','roles');
       map { $possfield{$_} = 1; } @allfields;
       my %lt = &ltitools_names(); 
       if ($env{'form.ltitools_add'}) {
           my $title = $env{'form.ltitools_add_title'};
           $title =~ s/(`)/'/g;
           ($newid,my $error) = &get_ltitools_id($dom,$title);
           if ($newid) {
               my $position = $env{'form.ltitools_add_pos'};
               $position =~ s/\D+//g;
               if ($position ne '') {
                   $allpos[$position] = $newid;
               }
               $changes{$newid} = 1;
               foreach my $item ('title','url','key','secret') {
                   $env{'form.ltitools_add_'.$item} =~ s/(`)/'/g;
                   if ($env{'form.ltitools_add_'.$item}) {
                       $confhash{$newid}{$item} = $env{'form.ltitools_add_'.$item};
                   }
               }
               if ($env{'form.ltitools_add_version'} eq 'LTI-1p0') {
                   $confhash{$newid}{'version'} = $env{'form.ltitools_add_version'};
               }
               if ($env{'form.ltitools_add_msgtype'} eq 'basic-lti-launch-request') {
                   $confhash{$newid}{'msgtype'} = $env{'form.ltitools_add_msgtype'};
               }
               foreach my $item ('width','height') {
                   $env{'form.ltitools_add_'.$item} =~ s/^\s+//;
                   $env{'form.ltitools_add_'.$item} =~ s/\s+$//;
                   if ($env{'form.ltitools_add_'.$item} =~ /^\d+$/) {
                       $confhash{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item};
                   }
               }
               if ($env{'form.ltitools_add_target'} eq 'window') {
                   $confhash{$newid}{'display'}{'target'} = $env{'form.ltitools_add_target'};
               } else {
                   $confhash{$newid}{'display'}{'target'} = 'iframe';
               }
               foreach my $item ('passback','roster') {
                   if ($env{'form.ltitools_add_'.$item}) {
                       $confhash{$newid}{$item} = 1;
                   }
               }
               if ($env{'form.ltitools_add_image.filename'} ne '') {
                   my ($imageurl,$error) =
                       &process_ltitools_image($r,$dom,$confname,'ltitools_add_image',$dom,
                                               $configuserok,$switchserver,$author_ok);
                   if ($imageurl) {
                       $confhash{$newid}{'image'} = $imageurl;
                   }
                   if ($error) {
                       &Apache::lonnet::logthis($error);
                       $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                   }
               }
               my @fields = &Apache::loncommon::get_env_multiple('form.ltitools_add_fields');
               foreach my $field (@fields) {
                   if ($possfield{$field}) {
                       if ($field eq 'roles') {
                           foreach my $role (@courseroles) {
                               my $choice = $env{'form.ltitools_add_roles_'.$role};
                               if (($choice ne '') && ($posslti{$choice})) {
                                   $confhash{$newid}{'roles'}{$role} = $choice;
                                   if ($role eq 'cc') {
                                       $confhash{$newid}{'roles'}{'co'} = $choice; 
                                   }
                               }
                           }
                       } else {
                           $confhash{$newid}{'fields'}{$field} = 1;
                       }
                   }
               }
               my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig');
               foreach my $item (@courseconfig) {
                   $confhash{$newid}{'crsconf'}{$item} = 1;
               }
               if ($env{'form.ltitools_add_custom'}) {
                   my $name = $env{'form.ltitools_add_custom_name'};
                   my $value = $env{'form.ltitools_add_custom_value'};
                   $value =~ s/(`)/'/g;
                   $name =~ s/(`)/'/g;
                   $confhash{$newid}{'custom'}{$name} = $value;
               }
           } else {
               my $error = &mt('Failed to acquire unique ID for new external tool');   
               $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
           }
       }
       if (ref($domconfig{$action}) eq 'HASH') {
           my %deletions;
           my @todelete = &Apache::loncommon::get_env_multiple('form.ltitools_del');
           if (@todelete) {
               map { $deletions{$_} = 1; } @todelete;
           }
           my %customadds;
           my @newcustom = &Apache::loncommon::get_env_multiple('form.ltitools_customadd');
           if (@newcustom) {
               map { $customadds{$_} = 1; } @newcustom;
           } 
           my %imgdeletions;
           my @todeleteimages = &Apache::loncommon::get_env_multiple('form.ltitools_image_del');
           if (@todeleteimages) {
               map { $imgdeletions{$_} = 1; } @todeleteimages;
           }
           my $maxnum = $env{'form.ltitools_maxnum'};
           for (my $i=0; $i<=$maxnum; $i++) {
               my $itemid = $env{'form.ltitools_id_'.$i};
               if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
                   if ($deletions{$itemid}) {
                       if ($domconfig{$action}{$itemid}{'image'}) {
                           #FIXME need to obsolete item in RES space
                       }
                       $changes{$itemid} = $domconfig{$action}{$itemid}{'title'};
                       next;
                   } else {
                       my $newpos = $env{'form.ltitools_'.$itemid};
                       $newpos =~ s/\D+//g;
                       foreach my $item ('title','url','key','secret') {
                           $confhash{$itemid}{$item} = $env{'form.ltitools_'.$item.'_'.$i};
                           if ($domconfig{$action}{$itemid}{$item} ne $confhash{$itemid}{$item}) {
                               $changes{$itemid} = 1;
                           }
                       }
                       if ($env{'form.ltitools_version_'.$i} eq 'LTI-1p0') {
                           $confhash{$itemid}{'version'} = $env{'form.ltitools_version_'.$i};
                       }
                       if ($env{'form.ltitools_msgtype_'.$i} eq 'basic-lti-launch-request') {
                           $confhash{$itemid}{'msgtype'} = $env{'form.ltitools_msgtype_'.$i};
                       }
                       foreach my $size ('width','height') {
                           $env{'form.ltitools_'.$size.'_'.$i} =~ s/^\s+//;
                           $env{'form.ltitools_'.$size.'_'.$i} =~ s/\s+$//;
                           if ($env{'form.ltitools_'.$size.'_'.$i} =~ /^\d+$/) {
                               $confhash{$itemid}{'display'}{$size} = $env{'form.ltitools_'.$size.'_'.$i};
                               if (ref($domconfig{$action}{$itemid}{'display'}) eq 'HASH') {
                                   if ($domconfig{$action}{$itemid}{'display'}{$size} ne $confhash{$itemid}{'display'}{$size}) {
                                       $changes{$itemid} = 1;
                                   }
                               } else {
                                   $changes{$itemid} = 1;
                               }
                           }
                       }
                       if ($env{'form.ltitools_target_'.$i} eq 'window') {
                           $confhash{$itemid}{'display'}{'target'} = $env{'form.ltitools_target_'.$i};
                       } else {
                           $confhash{$itemid}{'display'}{'target'} = 'iframe';
                       }
                       if (ref($domconfig{$action}{$itemid}{'display'}) eq 'HASH') {
                           if ($domconfig{$action}{$itemid}{'display'}{'target'} ne $confhash{$itemid}{'display'}{'target'}) {
                               $changes{$itemid} = 1;
                           }
                       } else {
                           $changes{$itemid} = 1;
                       }
                       foreach my $extra ('passback','roster') {
                           if ($env{'form.ltitools_'.$extra.'_'.$i}) {
                               $confhash{$itemid}{$extra} = 1;
                           }
                           if ($domconfig{$action}{$itemid}{$extra} ne $confhash{$itemid}{$extra}) {
                               $changes{$itemid} = 1;
                           }
                       }
                       my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig_'.$i);
                       foreach my $item ('label','title','target') {
                           if (grep(/^\Q$item\E$/,@courseconfig)) {
                               $confhash{$itemid}{'crsconf'}{$item} = 1;
                               if (ref($domconfig{$action}{$itemid}{'crsconf'}) eq 'HASH') {
                                   if ($domconfig{$action}{$itemid}{'crsconf'}{$item} ne $confhash{$itemid}{'crsconf'}{$item}) {
                                       $changes{$itemid} = 1;
                                   }
                               } else {
                                   $changes{$itemid} = 1;
                               }
                           }
                       }
                       my @fields = &Apache::loncommon::get_env_multiple('form.ltitools_fields_'.$i);
                       foreach my $field (@fields) {
                           if ($possfield{$field}) {
                               if ($field eq 'roles') {
                                   foreach my $role (@courseroles) {
                                       my $choice = $env{'form.ltitools_roles_'.$role.'_'.$i};
                                       if (($choice ne '') && ($posslti{$choice})) {
                                           $confhash{$itemid}{'roles'}{$role} = $choice;
                                           if ($role eq 'cc') {
                                               $confhash{$itemid}{'roles'}{'co'} = $choice;
                                           }
                                       }
                                       if (ref($domconfig{$action}{$itemid}{'roles'}) eq 'HASH') {
                                           if ($domconfig{$action}{$itemid}{'roles'}{$role} ne $confhash{$itemid}{'roles'}{$role}) {
                                               $changes{$itemid} = 1;
                                           }
                                       } elsif ($confhash{$itemid}{'roles'}{$role}) {
                                           $changes{$itemid} = 1;
                                       }
                                   }
                               } else {
                                   $confhash{$itemid}{'fields'}{$field} = 1;
                                   if (ref($domconfig{$action}{$itemid}{'fields'}) eq 'HASH') {
                                       if ($domconfig{$action}{$itemid}{'fields'}{$field} ne $confhash{$itemid}{'fields'}{$field}) {
                                           $changes{$itemid} = 1;
                                       }
                                   } else {
                                       $changes{$itemid} = 1;
                                   }
                               }
                           }
                       }
                       $allpos[$newpos] = $itemid;
                   }
                   if ($imgdeletions{$itemid}) {
                       $changes{$itemid} = 1;
                       #FIXME need to obsolete item in RES space
                   } elsif ($env{'form.ltitools_image_'.$i.'.filename'}) {
                       my ($imgurl,$error) = &process_ltitools_image($r,$dom,$confname,'ltitools_image_'.$i,
                                                                    $itemid,$configuserok,$switchserver,
                                                                    $author_ok);
                       if ($imgurl) {
                           $confhash{$itemid}{'image'} = $imgurl;
                           $changes{$itemid} = 1;
                       }
                       if ($error) {
                           &Apache::lonnet::logthis($error);
                           $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                       }
                   } elsif ($domconfig{$action}{$itemid}{'image'}) {
                       $confhash{$itemid}{'image'} =
                          $domconfig{$action}{$itemid}{'image'};
                   }
                   if ($customadds{$i}) {
                       my $name = $env{'form.ltitools_custom_name_'.$i};
                       $name =~ s/(`)/'/g;
                       $name =~ s/^\s+//;
                       $name =~ s/\s+$//;
                       my $value = $env{'form.ltitools_custom_value_'.$i};
                       $value =~ s/(`)/'/g;
                       $value =~ s/^\s+//;
                       $value =~ s/\s+$//;
                       if ($name ne '') {
                           $confhash{$itemid}{'custom'}{$name} = $value;
                           $changes{$itemid} = 1;
                       }
                   }
                   my %customdels;
                   my @customdeletions = &Apache::loncommon::get_env_multiple('form.ltitools_customdel_'.$i); 
                   if (@customdeletions) {
                       $changes{$itemid} = 1;
                   }
                   map { $customdels{$_} = 1; } @customdeletions;
                   if (ref($domconfig{$action}{$itemid}{'custom'}) eq 'HASH') {
                       foreach my $key (keys(%{$domconfig{$action}{$itemid}{'custom'}})) {
                           unless ($customdels{$key}) {
                               if ($env{'form.ltitools_customval_'.$key.'_'.$i} ne '') {
                                   $confhash{$itemid}{'custom'}{$key} = $env{'form.ltitools_customval_'.$key.'_'.$i}; 
                               }
                               if ($domconfig{$action}{$itemid}{'custom'}{$key} ne $env{'form.ltitools_customval_'.$key.'_'.$i}) {
                                   $changes{$itemid} = 1;
                               }
                           }
                       }
                   }
                   unless ($changes{$itemid}) {
                       foreach my $key (keys(%{$domconfig{$action}{$itemid}})) {
                           if (ref($domconfig{$action}{$itemid}{$key}) eq 'HASH') {
                               if (ref($confhash{$itemid}{$key}) eq 'HASH') {
                                   foreach my $innerkey (keys(%{$domconfig{$action}{$itemid}{$key}})) {
                                       unless (exists($confhash{$itemid}{$key}{$innerkey})) {
                                           $changes{$itemid} = 1;
                                           last;
                                       }
                                   }
                               } elsif (keys(%{$domconfig{$action}{$itemid}{$key}}) > 0) {
                                   $changes{$itemid} = 1;
                               }
                           }
                           last if ($changes{$itemid});
                       }
                   }
               }
           }
       }
       if (@allpos > 0) {
           my $idx = 0;
           foreach my $itemid (@allpos) {
               if ($itemid ne '') {
                   $confhash{$itemid}{'order'} = $idx;
                   if (ref($domconfig{$action}) eq 'HASH') {
                       if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
                           if ($domconfig{$action}{$itemid}{'order'} ne $idx) {
                               $changes{$itemid} = 1;
                           }
                       }
                   }
                   $idx ++;
               }
           }
       }
       my %ltitoolshash = (
                             $action => { %confhash }
                          );
       my $putresult = &Apache::lonnet::put_dom('configuration',\%ltitoolshash,
                                                $dom);
       if ($putresult eq 'ok') {
           if (keys(%changes) > 0) {
               my $cachetime = 24*60*60;
               &Apache::lonnet::do_cache_new('ltitools',$dom,\%confhash,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'ltitools'} = 1;
               }
               $resulttext = &mt('Changes made:').'<ul>';
               my %bynum;
               foreach my $itemid (sort(keys(%changes))) {
                   my $position = $confhash{$itemid}{'order'};
                   $bynum{$position} = $itemid;
               }
               foreach my $pos (sort { $a <=> $b } keys(%bynum)) {
                   my $itemid = $bynum{$pos}; 
                   if (ref($confhash{$itemid}) ne 'HASH') {
                       $resulttext .= '<li>'.&mt('Deleted: [_1]',$changes{$itemid}).'</li>';
                   } else {
                       $resulttext .= '<li><b>'.$confhash{$itemid}{'title'}.'</b>';
                       if ($confhash{$itemid}{'image'}) {
                           $resulttext .= '&nbsp;'.
                                          '<img src="'.$confhash{$itemid}{'image'}.'"'.
                                          ' alt="'.&mt('Tool Provider icon').'" />';
                       }
                       $resulttext .= '</li><ul>';
                       my $position = $pos + 1;
                       $resulttext .= '<li>'.&mt('Order: [_1]',$position).'</li>';
                       foreach my $item ('version','msgtype','url','key') {
                           if ($confhash{$itemid}{$item} ne '') {
                               $resulttext .= '<li>'.$lt{$item}.':&nbsp;'.$confhash{$itemid}{$item}.'</li>';
                           }
                       }
                       if ($confhash{$itemid}{'secret'} ne '') {
                           $resulttext .= '<li>'.$lt{'secret'}.':&nbsp;';
                           my $num = length($confhash{$itemid}{'secret'});
                           $resulttext .= ('*'x$num).'</li>';
                       }
                       $resulttext .= '<li>'.&mt('Configurable in course:');
                       my @possconfig = ('label','title','target');
                       my $numconfig = 0; 
                       if (ref($confhash{$itemid}{'crsconf'}) eq 'HASH') { 
                           foreach my $item (@possconfig) {
                               if ($confhash{$itemid}{'crsconf'}{$item}) {
                                   $numconfig ++;
                                   $resulttext .= ' '.$lt{'crs'.$item};
                               }
                           }
                       }
                       if (!$numconfig) {
                           $resulttext .= &mt('None');
                       }
                       $resulttext .= '</li>';
                       foreach my $item ('passback','roster') {
                           $resulttext .= '<li>'.$lt{$item}.'&nbsp;';
                           if ($confhash{$itemid}{$item}) {
                               $resulttext .= &mt('Yes');
                           } else {
                               $resulttext .= &mt('No');
                           }
                           $resulttext .= '</li>';
                       }
                       if (ref($confhash{$itemid}{'display'}) eq 'HASH') {
                           my $displaylist;
                           if ($confhash{$itemid}{'display'}{'target'}) {
                               $displaylist = &mt('Display target').':&nbsp;'.
                                              $confhash{$itemid}{'display'}{'target'}.',';
                           }
                           foreach my $size ('width','height') { 
                               if ($confhash{$itemid}{'display'}{$size}) {
                                   $displaylist .= ('&nbsp;'x2).$lt{$size}.':&nbsp;'.
                                                   $confhash{$itemid}{'display'}{$size}.',';
                               }
                           }
                           if ($displaylist) {
                               $displaylist =~ s/,$//;
                               $resulttext .= '<li>'.$displaylist.'</li>';
                           }
                       } 
                       if (ref($confhash{$itemid}{'fields'}) eq 'HASH') {
                           my $fieldlist;
                           foreach my $field (@allfields) {
                               if ($confhash{$itemid}{'fields'}{$field}) {
                                   $fieldlist .= ('&nbsp;'x2).$lt{$field}.',';
                               }
                           }
                           if ($fieldlist) {
                               $fieldlist =~ s/,$//;
                               $resulttext .= '<li>'.&mt('Data sent').':'.$fieldlist.'</li>';
                           }
                       }
                       if (ref($confhash{$itemid}{'roles'}) eq 'HASH') {
                           my $rolemaps;
                           foreach my $role (@courseroles) {
                               if ($confhash{$itemid}{'roles'}{$role}) {
                                   $rolemaps .= ('&nbsp;'x2).&Apache::lonnet::plaintext($role,'Course').'='.
                                                $confhash{$itemid}{'roles'}{$role}.',';
                               }
                           }
                           if ($rolemaps) {
                               $rolemaps =~ s/,$//; 
                               $resulttext .= '<li>'.&mt('Role mapping:').$rolemaps.'</li>';
                           }
                       }
                       if (ref($confhash{$itemid}{'custom'}) eq 'HASH') {
                           my $customlist;
                           if (keys(%{$confhash{$itemid}{'custom'}})) {
                               foreach my $key (sort(keys(%{$confhash{$itemid}{'custom'}}))) {
                                   $customlist .= $key.':'.$confhash{$itemid}{'custom'}{$key}.('&nbsp;'x2);
                               } 
                           }
                           if ($customlist) {
                               $resulttext .= '<li>'.&mt('Custom items').':'.$customlist.'</li>';
                           }
                       } 
                       $resulttext .= '</ul></li>';
                   }
               }
               $resulttext .= '</ul>';
           } else {
               $resulttext = &mt('No changes made.');
           }
       } else {
           $errors .= '<li><span class="LC_error">'.&mt('Failed to save changes').'</span></li>';
       }
       if ($errors) {
           $resulttext .= &mt('The following errors occurred: ').'<ul>'.
                          $errors.'</ul>';
       }
       return $resulttext;
   }
   
   sub process_ltitools_image {
       my ($r,$dom,$confname,$caller,$itemid,$configuserok,$switchserver,$author_ok) = @_;
       my $filename = $env{'form.'.$caller.'.filename'};
       my ($error,$url);
       my ($width,$height) = (21,21);
       if ($configuserok eq 'ok') {
           if ($switchserver) {
               $error = &mt('Upload of Tool Provider (LTI) icon is not permitted to this server: [_1]',
                            $switchserver);
           } elsif ($author_ok eq 'ok') {
               my ($result,$imageurl,$madethumb) =
                   &publishlogo($r,'upload',$caller,$dom,$confname,
                                "ltitools/$itemid/icon",$width,$height);
               if ($result eq 'ok') {
                   if ($madethumb) {
                       my ($path,$imagefile) = ($imageurl =~ m{^(.+)/([^/]+)$});
                       my $imagethumb = "$path/tn-".$imagefile;
                       $url = $imagethumb;
                   } else {
                       $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 get_ltitools_id {
       my ($cdom,$title) = @_;
       # get lock on ltitools db
       my $lockhash = {
                         lock => $env{'user.name'}.
                                 ':'.$env{'user.domain'},
                      };
       my $tries = 0;
       my $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
       my ($id,$error);
    
       while (($gotlock ne 'ok') && ($tries<10)) {
           $tries ++;
           sleep (0.1);
           $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
       }
       if ($gotlock eq 'ok') {
           my %currids = &Apache::lonnet::dump_dom('ltitools',$cdom);
           if ($currids{'lock'}) {
               delete($currids{'lock'});
               if (keys(%currids)) {
                   my @curr = sort { $a <=> $b } keys(%currids);
                   if ($curr[-1] =~ /^\d+$/) {
                       $id = 1 + $curr[-1];
                   }
               } else {
                   $id = 1;
               }
               if ($id) {
                   unless (&Apache::lonnet::newput_dom('ltitools',{ $id => $title },$cdom) eq 'ok') {
                       $error = 'nostore';
                   }
               } else {
                   $error = 'nonumber';
               }
           }
           my $dellockoutcome = &Apache::lonnet::del_dom('ltitools',['lock'],$cdom);
       } else {
           $error = 'nolock';
       }
       return ($id,$error);
   }
   
 sub modify_autoenroll {  sub modify_autoenroll {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,%changes);      my ($resulttext,%changes);
Line 9986  sub modify_autoenroll { Line 10052  sub modify_autoenroll {
             }              }
             if ($changes{'autofailsafe'}) {              if ($changes{'autofailsafe'}) {
                 if ($failsafe ne '') {                  if ($failsafe ne '') {
                     $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section set to: [_1]',$failsafe).'</li>';                      $resulttext .= '<li>'.&mt("$title{'failsafe'} set to [_1]",$failsafe).'</li>';
                 } else {                  } else {
                     $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section: deleted');                      $resulttext .= '<li>'.&mt("$title{'failsafe'} deleted");
                 }                  }
                 &Apache::lonnet::get_domain_defaults($dom,1);                  &Apache::lonnet::get_domain_defaults($dom,1);
                 if (ref($lastactref) eq 'HASH') {                  if (ref($lastactref) eq 'HASH') {
Line 10267  sub modify_autocreate { Line 10333  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 10461  sub modify_directorysrch { Line 10527  sub modify_directorysrch {
                 $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 directory search settings');
         }          }
Line 10486  sub modify_contacts { Line 10548  sub modify_contacts {
     my (%others,%to,%bcc,%includestr,%includeloc);      my (%others,%to,%bcc,%includestr,%includeloc);
     my @contacts = ('supportemail','adminemail');      my @contacts = ('supportemail','adminemail');
     my @mailings = ('errormail','packagesmail','helpdeskmail','otherdomsmail',      my @mailings = ('errormail','packagesmail','helpdeskmail','otherdomsmail',
                     'lonstatusmail','requestsmail','updatesmail','idconflictsmail','hostipmail');                      'lonstatusmail','requestsmail','updatesmail','idconflictsmail');
     my @toggles = ('reporterrors','reportupdates');      my @toggles = ('reporterrors','reportupdates');
     my ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();      my ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();
     foreach my $type (@mailings) {      foreach my $type (@mailings) {
Line 10526  sub modify_contacts { Line 10588  sub modify_contacts {
                 my $value = $env{'form.helpform_'.$field};                  my $value = $env{'form.helpform_'.$field};
                 $value =~ s/^\s+|\s+$//g;                  $value =~ s/^\s+|\s+$//g;
                 if (grep(/^\Q$value\E$/,@{$possoptions->{$field}})) {                  if (grep(/^\Q$value\E$/,@{$possoptions->{$field}})) {
                     $contacts_hash{'contacts'}{'helpform'}{$field} = $value;                      $contacts_hash{contacts}{'helpform'}{$field} = $value;
                     if ($field eq 'screenshot') {                      if ($field eq 'screenshot') {
                         $env{'form.helpform_maxsize'} =~ s/^\s+|\s+$//g;                          $env{'form.helpform_maxsize'} =~ s/^\s+|\s+$//g;
                         if ($env{'form.helpform_maxsize'} =~ /^\d+\.?\d*$/) {                          if ($env{'form.helpform_maxsize'} =~ /^\d+\.?\d*$/) {
                             $contacts_hash{'contacts'}{'helpform'}{'maxsize'} = $env{'form.helpform_maxsize'};                              $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 10631  sub modify_contacts { Line 10653  sub modify_contacts {
                 }                  }
             }              }
         }          }
         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 {
         my %default;          my %default;
         $default{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};          $default{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};
Line 10669  sub modify_contacts { Line 10664  sub modify_contacts {
         $default{'lonstatusmail'} = 'adminemail';          $default{'lonstatusmail'} = 'adminemail';
         $default{'requestsmail'} = 'adminemail';          $default{'requestsmail'} = 'adminemail';
         $default{'updatesmail'} = '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;
Line 10759  sub modify_contacts { Line 10753  sub modify_contacts {
                             $resulttext .= $bcctext.': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';                              $resulttext .= $bcctext.': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';
                         } elsif (!@text) {                          } elsif (!@text) {
                             $resulttext .= &mt('No one');                              $resulttext .= &mt('No one');
                         }                          }   
                         if ($includestr{$type} ne '') {                          if ($includestr{$type} ne '') {
                             if ($includeloc{$type} eq 'b') {                              if ($includeloc{$type} eq 'b') {
                                 $resulttext .= '<br />'.&mt('Text automatically added to e-mail body:').' '.$includestr{$type};                                  $resulttext .= '<br />'.&mt('Text automatically added to e-mail body:').' '.$includestr{$type};
Line 10773  sub modify_contacts { Line 10767  sub modify_contacts {
                     $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');              my @offon = ('off','on');
             if ($changes{'reporterrors'}) {              if ($changes{'reporterrors'}) {
                 $resulttext .= '<li>'.                  $resulttext .= '<li>'.
Line 10882  sub modify_contacts { Line 10822  sub modify_contacts {
                                    &mt('Max size for file uploaded to help form by logged-in user set to [_1] MB.',                                     &mt('Max size for file uploaded to help form by logged-in user set to [_1] MB.',
                                        $contacts_hash{'contacts'}{'helpform'}{'maxsize'}).                                         $contacts_hash{'contacts'}{'helpform'}{'maxsize'}).
                                    '</li>';                                     '</li>';
   
                 }                  }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
Line 10895  sub modify_contacts { Line 10836  sub modify_contacts {
     return $resulttext;      return $resulttext;
 }  }
   
 sub modify_passwords {  
     my ($r,$dom,$confname,$lastactref,%domconfig) = @_;  
     my ($resulttext,%current,%changes,%newvalues,@oktypes,$errors,  
         $updatedefaults,$updateconf);  
     my $customfn = 'resetpw.html';  
     if (ref($domconfig{'passwords'}) eq 'HASH') {  
         %current = %{$domconfig{'passwords'}};  
     }  
     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 $servadm = $r->dir_config('lonAdmEMail');  
         my $servadm = $r->dir_config('lonAdmEMail');  
         my ($configuserok,$author_ok,$switchserver) =  
             &config_check($dom,$confname,$servadm);  
         my $error;  
         if ($configuserok eq 'ok') {  
             if ($switchserver) {  
                 $error = &mt("Upload of file containing domain-specific text is not permitted to this server: [_1]",$switchserver);  
             } else {  
                 if ($author_ok eq 'ok') {  
                     my ($result,$customurl) =  
                         &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 {  
             $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);  
         }  
         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') {  
         if ($save_defaults{'intauth_'.$item} ne $domdefaults{'intauth_'.$item}) {  
             $domdefaults{'intauth_'.$item} = $save_defaults{'intauth_'.$item};  
             $updatedefaults = 1;  
         }  
     }  
     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 {  
             if (@chars > 0) {  
                 $changes{'rules'} = 1;  
             }  
         }  
     }  
     my %crsownerchg = (  
                         by => [],  
                         for => [],  
                       );  
     foreach my $item ('by','for') {  
         my @posstypes = &Apache::loncommon::get_env_multiple('form.passwords_crsowner_'.$item);  
         foreach my $type (sort(@posstypes)) {  
             if (grep(/^\Q$type\E$/,@oktypes)) {  
                 push(@{$crsownerchg{$item}},$type);  
             }  
         }  
     }  
     $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 {  
                             $resulttext .= '<li>'.&mt('Users can enter both a username and an e-mail address in "Forgot Password" web form').'</li>';  
                         }  
                         if (ref($confighash{'passwords'}{'resetpostlink'}) eq 'HASH') {  
                             my $output;  
                             if (ref($types) eq 'ARRAY') {  
                                 foreach my $type (@{$types}) {  
                                     if (ref($confighash{'passwords'}{'resetpostlink'}{$type}) eq 'ARRAY') {  
                                         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') {  
                                 if (@{$confighash{'passwords'}{'resetpostlink'}{'default'}} == 0) {  
                                     $output .= $othertitle.' -- '.&mt('none');  
                                 } else {  
                                     $output .= $othertitle.' -- '.  
                                                join(', ',map { $titles{$_}; } (@{$confighash{'passwords'}{'resetpostlink'}{'default'}}));  
                                 }  
                             }  
                             if ($output) {  
                                 $resulttext .= '<li>'.&mt('Information required for new password form (by user type) set to: [_1]',$output).'</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>';  
                             }  
                         } 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 ($rule eq 'min') {  
                                     $resulttext .= '<li>'.&mt('[_1] not set.',$titles{$rule});  
                                                    ' '.&mt('Default of [_1] will be used',  
                                                            $Apache::lonnet::passwdmin).'</li>';  
                                 } else {  
                                     $resulttext .= '<li>'.&mt('[_1] set to none',$titles{$rule}).'</li>';  
                                 }  
                             } else {  
                                 $resulttext .= '<li>'.&mt('[_1] set to [_2]',$titles{$rule},$confighash{'passwords'}{$rule}).'</li>';  
                             }  
                         }  
                         if (ref($confighash{'passwords'}{'chars'}) eq 'ARRAY') {  
                             if (@{$confighash{'passwords'}{'chars'}} > 0) {  
                                 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',  
                                                    );  
                                 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 {  sub modify_usercreation {
     my ($dom,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate,%save_usercreate);      my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate,%save_usercreate);
Line 11447  sub modify_usercreation { Line 10845  sub modify_usercreation {
             if ($key eq 'cancreate') {              if ($key eq 'cancreate') {
                 if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {                  if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {
                     foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {                      foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
                         if (($item eq 'requestcrs') || ($item eq 'course') || ($item eq 'author')) {                          if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||
                             $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};                              ($item eq 'captcha') || ($item eq 'recaptchakeys') ||
                         } else {                              ($item eq 'recaptchaversion')) {
                             $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};                              $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
                           } else {
                               $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
                         }                          }
                     }                      }
                 }                  }
Line 11653  sub modify_usercreation { Line 11053  sub modify_usercreation {
 }  }
   
 sub modify_selfcreation {  sub modify_selfcreation {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,$warningmsg,%curr_usercreation,%curr_usermodify,%curr_inststatus,%changes,%cancreate);      my ($resulttext,$warningmsg,%curr_usercreation,%curr_usermodify,%changes,%cancreate);
     my (%save_usercreate,%save_usermodify,%save_inststatus,@types,%usertypes);      my (%save_usercreate,%save_usermodify);
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);      my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
     my ($othertitle,$usertypesref,$typesref) = &Apache::loncommon::sorted_inst_types($dom);      if (ref($types) eq 'ARRAY') {
     if (ref($typesref) eq 'ARRAY') {          $usertypes->{'default'} = $othertitle;
         @types = @{$typesref};          push(@{$types},'default');
     }  
     if (ref($usertypesref) eq 'HASH') {  
         %usertypes = %{$usertypesref};  
     }      }
     $usertypes{'default'} = $othertitle;  
 #  #
 # Retrieve current domain configuration for self-creation of usernames from $domconfig{'usercreation'}.  # Retrieve current domain configuration for self-creation of usernames from $domconfig{'usercreation'}.
 #  #
Line 11674  sub modify_selfcreation { Line 11070  sub modify_selfcreation {
                 if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {                  if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {
                     foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {                      foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
                         if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||                          if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||
                             ($item eq 'captcha') || ($item eq 'recaptchakeys') ||                              ($item eq 'captcha') || ($item eq 'recaptchakeys') || 
                             ($item eq 'recaptchaversion') || ($item eq 'notify') ||                              ($item eq 'recaptchaversion') ||
                             ($item eq 'emailusername') || ($item eq 'shibenv') ||                              ($item eq 'emailusername') || ($item eq 'notify') ||
                             ($item eq 'selfcreateprocessing') || ($item eq 'emailverified') ||                              ($item eq 'selfcreateprocessing') || ($item eq 'shibenv')) {
                             ($item eq 'emailoptions') || ($item eq 'emaildomain')) {  
                             $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};                              $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
                         } else {                          } else {
                             $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};                              $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
Line 11704  sub modify_selfcreation { Line 11099  sub modify_selfcreation {
             }              }
         }          }
     }      }
 #  
 # 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');      my @contexts = ('selfcreate');
     @{$cancreate{'selfcreate'}} = ();      @{$cancreate{'selfcreate'}} = ();
     %{$cancreate{'emailusername'}} = ();      %{$cancreate{'emailusername'}} = ();
     if (@types) {      @{$cancreate{'statustocreate'}} = ();
         @{$cancreate{'statustocreate'}} = ();  
     }  
     %{$cancreate{'selfcreateprocessing'}} = ();      %{$cancreate{'selfcreateprocessing'}} = ();
     %{$cancreate{'shibenv'}} = ();      %{$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 username',
                           );                            );
 #  #
 # Populate $cancreate{'selfcreate'} array reference with types of user, for which self-creation of user accounts  # Populate $cancreate{'selfcreate'} array reference with types of user, for which self-creation of user accounts
 # is permitted.  # is permitted.
 #  #
   
     my ($emailrules,$emailruleorder) = &Apache::lonnet::inst_userrules($dom,'email');      my @statuses;
       if (ref($domconfig{'inststatus'}) eq 'HASH') {
           if (ref($domconfig{'inststatus'}{'inststatusguest'}) eq 'ARRAY') {
               @statuses = @{$domconfig{'inststatus'}{'inststatusguest'}};
           }
       }
       push(@statuses,'default');
   
     my (@statuses,%email_rule);  
     foreach my $item ('login','sso','email') {      foreach my $item ('login','sso','email') {
         if ($item eq 'email') {          if ($item eq 'email') {
             if ($env{'form.cancreate_email'}) {              if ($env{'form.cancreate_email'}) {
                 if (@types) {                  push(@{$cancreate{'selfcreate'}},'email');
                     my @poss_statuses = &Apache::loncommon::get_env_multiple('form.selfassign');                  push(@contexts,'selfcreateprocessing');
                     foreach my $status (@poss_statuses) {                  foreach my $type (@statuses) {
                         if (grep(/^\Q$status\E$/,(@types,'default'))) {                      if ($type eq 'default') {
                             push(@statuses,$status);                          $cancreate{'selfcreateprocessing'}{$type} = $env{'form.cancreate_emailprocess'};
                         }                      } else { 
                     }                          $cancreate{'selfcreateprocessing'}{$type} = $env{'form.cancreate_emailprocess_'.$type};
                     $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');  
                     }                      }
                 }                  }
             }              }
Line 11868  sub modify_selfcreation { Line 11143  sub modify_selfcreation {
             }              }
         }          }
     }      }
     my (%userinfo,%savecaptcha);      my (@email_rule,%userinfo,%savecaptcha);
     my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();      my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();
 #  #
 # Populate $cancreate{'emailusername'}{$type} hash ref with information fields (if new user will provide data  # Populate $cancreate{'emailusername'}{$type} hash ref with information fields (if new user will provide data
Line 11877  sub modify_selfcreation { Line 11152  sub modify_selfcreation {
   
     if ($env{'form.cancreate_email'}) {      if ($env{'form.cancreate_email'}) {
         push(@contexts,'emailusername');          push(@contexts,'emailusername');
         if (@statuses) {          if (ref($types) eq 'ARRAY') {
             foreach my $type (@statuses) {              foreach my $type (@{$types}) {
                 if (ref($infofields) eq 'ARRAY') {                  if (ref($infofields) eq 'ARRAY') {
                     foreach my $field (@{$infofields}) {                      foreach my $field (@{$infofields}) {
                         if ($env{'form.canmodify_emailusername_'.$type.'_'.$field} =~ /^(required|optional)$/) {                          if ($env{'form.canmodify_emailusername_'.$type.'_'.$field} =~ /^(required|optional)$/) {
Line 11890  sub modify_selfcreation { Line 11165  sub modify_selfcreation {
         }          }
 #  #
 # Populate $cancreate{'notify'} hash ref with names of Domain Coordinators who are to be notified of  # 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.  # queued requests for self-creation of account using e-mail address as username
 #  #
   
         my @approvalnotify = &Apache::loncommon::get_env_multiple('form.selfcreationnotifyapproval');          my @approvalnotify = &Apache::loncommon::get_env_multiple('form.selfcreationnotifyapproval');
Line 11910  sub modify_selfcreation { Line 11185  sub modify_selfcreation {
             push(@{$changes{'cancreate'}},'notify');              push(@{$changes{'cancreate'}},'notify');
         }          }
   
   #
   # Retrieve rules (if any) governing types of e-mail address which may be used as a username
   #
           @email_rule = &Apache::loncommon::get_env_multiple('form.email_rule');
         &process_captcha('cancreate',\%changes,\%savecaptcha,$curr_usercreation{'cancreate'});          &process_captcha('cancreate',\%changes,\%savecaptcha,$curr_usercreation{'cancreate'});
           if (ref($curr_usercreation{'email_rule'}) eq 'ARRAY') {
               if (@{$curr_usercreation{'email_rule'}} > 0) {
                   foreach my $type (@{$curr_usercreation{'email_rule'}}) {
                       if (!grep(/^\Q$type\E$/,@email_rule)) {
                           push(@{$changes{'email_rule'}},$type);
                       }
                   }
               }
               if (@email_rule > 0) {
                   foreach my $type (@email_rule) {
                       if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'email_rule'}})) {
                           push(@{$changes{'email_rule'}},$type);
                       }
                   }
               }
           } elsif (@email_rule > 0) {
               push(@{$changes{'email_rule'}},@email_rule);
           }
     }      }
 #    #  
 # Check if domain default is set appropriately, if self-creation of accounts is to be available for  # Check if domain default is set appropriately, if self-creation of accounts is to be available for
 # institutional log-in.  # institutional log-in.
 #  #
     if (grep(/^login$/,@{$cancreate{'selfcreate'}})) {      if (grep(/^login$/,@{$cancreate{'selfcreate'}})) {
           my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
         if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) ||           if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) || 
                ($domdefaults{'auth_def'} eq 'localauth'))) {                 ($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.').' '.              $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.').' '.
Line 11935  sub modify_selfcreation { Line 11233  sub modify_selfcreation {
 # which the user may supply, if institutional data is unavailable.  # which the user may supply, if institutional data is unavailable.
 #  #
     if (($env{'form.cancreate_login'}) || ($env{'form.cancreate_sso'})) {      if (($env{'form.cancreate_login'}) || ($env{'form.cancreate_sso'})) {
         if (@types) {          if (ref($types) eq 'ARRAY') {
             @{$cancreate{'statustocreate'}} = &Apache::loncommon::get_env_multiple('form.statustocreate');              if (@{$types} > 1) {
             push(@contexts,'statustocreate');                  @{$cancreate{'statustocreate'}} = &Apache::loncommon::get_env_multiple('form.statustocreate');
             foreach my $type (@types) {                  push(@contexts,'statustocreate');
               } else {
                   undef($cancreate{'statustocreate'});
               } 
               foreach my $type (@{$types}) {
                 my @modifiable =  &Apache::loncommon::get_env_multiple('form.canmodify_'.$type);                  my @modifiable =  &Apache::loncommon::get_env_multiple('form.canmodify_'.$type);
                 foreach my $field (@fields) {                  foreach my $field (@fields) {
                     if (grep(/^\Q$field\E$/,@modifiable)) {                      if (grep(/^\Q$field\E$/,@modifiable)) {
Line 11949  sub modify_selfcreation { Line 11251  sub modify_selfcreation {
                 }                  }
             }              }
             if (ref($curr_usermodify{'selfcreate'}) eq 'HASH') {              if (ref($curr_usermodify{'selfcreate'}) eq 'HASH') {
                 foreach my $type (@types) {                  foreach my $type (@{$types}) {
                     if (ref($curr_usermodify{'selfcreate'}{$type}) eq 'HASH') {                      if (ref($curr_usermodify{'selfcreate'}{$type}) eq 'HASH') {
                         foreach my $field (@fields) {                          foreach my $field (@fields) {
                             if ($save_usermodify{'selfcreate'}{$type}{$field} ne                              if ($save_usermodify{'selfcreate'}{$type}{$field} ne
Line 11961  sub modify_selfcreation { Line 11263  sub modify_selfcreation {
                     }                      }
                 }                  }
             } else {              } else {
                 foreach my $type (@types) {                  foreach my $type (@{$types}) {
                     push(@{$changes{'selfcreate'}},$type);                      push(@{$changes{'selfcreate'}},$type);
                 }                  }
             }              }
Line 12010  sub modify_selfcreation { Line 11312  sub modify_selfcreation {
             }              }
         } elsif (ref($curr_usercreation{'cancreate'}{$item}) eq 'HASH') {          } elsif (ref($curr_usercreation{'cancreate'}{$item}) eq 'HASH') {
             if (ref($cancreate{$item}) eq 'HASH') {              if (ref($cancreate{$item}) eq 'HASH') {
                 foreach my $type (keys(%{$curr_usercreation{'cancreate'}{$item}})) {                  foreach my $curr (keys(%{$curr_usercreation{'cancreate'}{$item}})) {
                     if (ref($curr_usercreation{'cancreate'}{$item}{$type}) eq 'HASH') {                      if (ref($curr_usercreation{'cancreate'}{$item}{$curr}) eq 'HASH') {
                         foreach my $field (keys(%{$curr_usercreation{'cancreate'}{$item}{$type}})) {                          foreach my $field (keys(%{$curr_usercreation{'cancreate'}{$item}{$curr}})) {
                             unless ($curr_usercreation{'cancreate'}{$item}{$type}{$field} eq $cancreate{$item}{$type}{$field}) {                              unless ($curr_usercreation{'cancreate'}{$item}{$curr}{$field} eq $cancreate{$item}{$curr}{$field}) {
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {                                  if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                     push(@{$changes{'cancreate'}},$item);                                      push(@{$changes{'cancreate'}},$item);
                                 }                                  }
                             }                              }
                         }                          }
                     } elsif (($item eq 'selfcreateprocessing') || ($item eq 'emailverified') || ($item eq 'emailoptions')) {                      } elsif ($item eq 'selfcreateprocessing') {
                         if ($cancreate{$item}{$type} ne $curr_usercreation{'cancreate'}{$item}{$type}) {                          if ($cancreate{$item}{$curr} ne $curr_usercreation{'cancreate'}{$item}{$curr}) {
                               if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                   push(@{$changes{'cancreate'}},$item);
                               }
                           }
                       } else {
                           if (!$cancreate{$item}{$curr}) {
                             if (!grep(/^$item$/,@{$changes{'cancreate'}})) {                              if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                 push(@{$changes{'cancreate'}},$item);                                  push(@{$changes{'cancreate'}},$item);
                             }                              }
                         }                          }
                     }                      }
                 }                  }
                 foreach my $type (keys(%{$cancreate{$item}})) {                  foreach my $field (keys(%{$cancreate{$item}})) {
                     if (ref($cancreate{$item}{$type}) eq 'HASH') {                      if (ref($cancreate{$item}{$field}) eq 'HASH') {
                         foreach my $field (keys(%{$cancreate{$item}{$type}})) {                          foreach my $inner (keys(%{$cancreate{$item}{$field}})) {
                             if (ref($curr_usercreation{'cancreate'}{$item}{$type}) eq 'HASH') {                              if (ref($curr_usercreation{'cancreate'}{$item}{$field}) eq 'HASH') {
                                 unless ($curr_usercreation{'cancreate'}{$item}{$type}{$field} eq $cancreate{$item}{$type}{$field}) {                                  unless ($curr_usercreation{'cancreate'}{$item}{$field}{$inner} eq $cancreate{$item}{$field}{$inner}) {
                                     if (!grep(/^$item$/,@{$changes{'cancreate'}})) {                                      if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                         push(@{$changes{'cancreate'}},$item);                                          push(@{$changes{'cancreate'}},$item);
                                     }                                      }
Line 12042  sub modify_selfcreation { Line 11350  sub modify_selfcreation {
                                 }                                  }
                             }                              }
                         }                          }
                     } elsif (($item eq 'selfcreateprocessing') || ($item eq 'emailverified') || ($item eq 'emailoptions')) {                      } elsif ($item eq 'selfcreateprocessing') {
                         if ($cancreate{$item}{$type} ne $curr_usercreation{'cancreate'}{$item}{$type}) {                          if ($cancreate{$item}{$field} ne $curr_usercreation{'cancreate'}{$item}{$field}) {
                               if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                   push(@{$changes{'cancreate'}},$item);
                               }
                           }
                       } else {
                           if (!$curr_usercreation{'cancreate'}{$item}{$field}) {
                             if (!grep(/^$item$/,@{$changes{'cancreate'}})) {                              if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                 push(@{$changes{'cancreate'}},$item);                                  push(@{$changes{'cancreate'}},$item);
                             }                              }
Line 12058  sub modify_selfcreation { Line 11372  sub modify_selfcreation {
                         push(@{$changes{'cancreate'}},$item);                          push(@{$changes{'cancreate'}},$item);
                     }                      }
                 }                  }
             }              } elsif (ref($cancreate{$item}) eq 'HASH') {
         } elsif (($item eq 'selfcreateprocessing') || ($item eq 'emailverified') || ($item eq 'emailoptions')) {                  if (!$cancreate{$item}{$curr_usercreation{'cancreate'}{$item}}) {
             if (ref($cancreate{$item}) eq 'HASH') {                      if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {                          push(@{$changes{'cancreate'}},$item);
                     push(@{$changes{'cancreate'}},$item);                      }
                 }                  }
             }              }
         } elsif ($item eq 'emailusername') {          } elsif ($item eq 'emailusername') {
Line 12095  sub modify_selfcreation { Line 11409  sub modify_selfcreation {
     if (ref($cancreate{'selfcreateprocessing'}) eq 'HASH') {      if (ref($cancreate{'selfcreateprocessing'}) eq 'HASH') {
         $save_usercreate{'cancreate'}{'selfcreateprocessing'} = $cancreate{'selfcreateprocessing'};          $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') {      if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {
         $save_usercreate{'cancreate'}{'statustocreate'} = $cancreate{'statustocreate'};          $save_usercreate{'cancreate'}{'statustocreate'} = $cancreate{'statustocreate'};
     }      }
Line 12111  sub modify_selfcreation { Line 11416  sub modify_selfcreation {
         $save_usercreate{'cancreate'}{'shibenv'} = $cancreate{'shibenv'};          $save_usercreate{'cancreate'}{'shibenv'} = $cancreate{'shibenv'};
     }      }
     $save_usercreate{'cancreate'}{'emailusername'} = $cancreate{'emailusername'};      $save_usercreate{'cancreate'}{'emailusername'} = $cancreate{'emailusername'};
     $save_usercreate{'email_rule'} = \%email_rule;      $save_usercreate{'emailrule'} = \@email_rule;
   
     my %userconfig_hash = (      my %userconfig_hash = (
             usercreation     => \%save_usercreate,              usercreation     => \%save_usercreate,
             usermodification => \%save_usermodify,              usermodification => \%save_usermodify,
             inststatus       => \%save_inststatus,  
     );      );
   
     my $putresult = &Apache::lonnet::put_dom('configuration',\%userconfig_hash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%userconfig_hash,
                                              $dom);                                               $dom);
 #  #
 # Accumulate details of changes to domain configuration for self-creation of usernames in $resulttext  # Accumulate details of changes to domain cofiguration for self-creation of usernames in $resulttext
 #  #
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
Line 12130  sub modify_selfcreation { Line 11433  sub modify_selfcreation {
             if (ref($changes{'cancreate'}) eq 'ARRAY') {              if (ref($changes{'cancreate'}) eq 'ARRAY') {
                 my %lt = &selfcreation_types();                  my %lt = &selfcreation_types();
                 foreach my $type (@{$changes{'cancreate'}}) {                  foreach my $type (@{$changes{'cancreate'}}) {
                     my $chgtext = '';                      my $chgtext;
                     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('Self creation of a new user account is not permitted.');
Line 12145  sub modify_selfcreation { Line 11448  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 />'.
                                                         &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts via log-in or single sign-on.").                                                          '<span class="LC_warning">'.
                                                         '</span><br />';                                                          &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").
                                                           '</span>';
                                         }                                          }
                                     }                                      }
                                 }                                  }
                                 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') {                      } elsif ($type eq 'shibenv') {
                         if (keys(%{$cancreate{$type}}) == 0) {                          if (keys(%{$cancreate{$type}}) == 0) {
                             $chgtext .= &mt('Shibboleth-autheticated user does not use environment variables to set user information').'<br />';                               $chgtext .= &mt('Shibboleth-autheticated user does not use environment variables to set user information'); 
                         } else {                          } else {
                             $chgtext .= &mt('Shibboleth-autheticated user information set from environment variables, as follows:').                              $chgtext .= &mt('Shibboleth-autheticated user information set from environment variables, as follows:').
                                         '<ul>';                                          '<ul>';
Line 12176  sub modify_selfcreation { Line 11472  sub modify_selfcreation {
                                 }                                  }
                             }                              }
                             $chgtext .= '</ul>';                              $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')) {
Line 12189  sub modify_selfcreation { Line 11485  sub modify_selfcreation {
                                                     &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").                                                      &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").
                                                     '</span>';                                                      '</span>';
                                     }                                      }
                                 } elsif (keys(%usertypes) > 0) {                                  } elsif (ref($usertypes) eq 'HASH') {
                                     if (grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {                                      if (grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {
                                         $chgtext .= &mt('Creation of a new account for an institutional user is restricted to the following institutional affiliation(s):');                                          $chgtext .= &mt('Creation of a new account for an institutional user is restricted to the following institutional affiliation(s):');
                                     } else {                                      } else {
Line 12200  sub modify_selfcreation { Line 11496  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.').                                                      &mt('However, users authenticated by institutional login/single sign on are not currently permitted to create accounts.').
                                                     '</span>';                                                      '</span>';
                                     }                                      }
Line 12217  sub modify_selfcreation { Line 11513  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') {                      } elsif ($type eq 'selfcreateprocessing') {
                         my %choices = &Apache::lonlocal::texthash (                          my %choices = &Apache::lonlocal::texthash (
                                                                     automatic => 'Automatic approval',                                                                      automatic => 'Automatic approval',
                                                                     approval  => 'Queued for approval',                                                                      approval  => 'Queued for approval',
                                                                   );                                                                    );
                         if (@types) {                          if (@statuses > 1) {
                             if (@statuses) {                              $chgtext .= &mt('Processing of requests to create account with e-mail address as username set as follows:'). 
                                 $chgtext .= &mt('Processing of requests to create account with e-mail verification set as follows:').                                          '<ul>';
                                             '<ul>';                             foreach my $type (@statuses) {
                                 foreach my $status (@statuses) {                                 if ($type eq 'default') {
                                     if ($status eq 'default') {                                     $chgtext .= '<li>'.$othertitle.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$type}}.'</li>';
                                         $chgtext .= '<li>'.$othertitle.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$status}}.'</li>';                                 } else {
                                     } else {                                     $chgtext .= '<li>'.$usertypes->{$type}.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$type}}.'</li>';
                                         $chgtext .= '<li>'.$usertypes{$status}.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$status}}.'</li>';                                 }
                                     }                             }
                                 }                             $chgtext .= '</ul>';
                                 $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') {  
                         my %options = &Apache::lonlocal::texthash (  
                                                                     any     => 'Any e-mail',  
                                                                     inst    => 'Institutional only',  
                                                                     noninst => 'Non-institutional only',  
                                                                     custom  => 'Custom restrictions',  
                                                                   );  
                         if (@types) {  
                             if (@statuses) {  
                                 $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 {                          } else {
                             if ($cancreate{'emailoptions'}{'default'} eq 'any') {                             $chgtext .= &mt('Processing of requests to create account with e-mail address as username set to: "[_1]"',
                                 $chgtext .= &mt('For self-created accounts verified by e-mail address, any e-mail may be used');                                           $choices{$cancreate{'selfcreateprocessing'}{'default'}});
                             } 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') {                      } elsif ($type eq 'captcha') {
                         if ($savecaptcha{$type} eq 'notused') {                          if ($savecaptcha{$type} eq 'notused') {
Line 12376  sub modify_selfcreation { Line 11569  sub modify_selfcreation {
                         }                          }
                     } elsif ($type eq 'emailusername') {                      } elsif ($type eq 'emailusername') {
                         if (ref($cancreate{'emailusername'}) eq 'HASH') {                          if (ref($cancreate{'emailusername'}) eq 'HASH') {
                             if (@statuses) {                              if (ref($types) eq 'ARRAY') {
                                 foreach my $type (@statuses) {                                  foreach my $type (@{$types}) {
                                     if (ref($cancreate{'emailusername'}{$type}) eq 'HASH') {                                      if (ref($cancreate{'emailusername'}{$type}) eq 'HASH') {
                                         if (keys(%{$cancreate{'emailusername'}{$type}}) > 0) {                                          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}'").                                              $chgtext .= &mt('When self-creating account with e-mail as username, the following information will be provided by [_1]:',"'$usertypes->{$type}'").
                                                     '<ul>';                                                      '<ul>';
                                             foreach my $field (@{$infofields}) {                                              foreach my $field (@{$infofields}) {
                                                 if ($cancreate{'emailusername'}{$type}{$field}) {                                                  if ($cancreate{'emailusername'}{$type}{$field}) {
Line 12389  sub modify_selfcreation { Line 11582  sub modify_selfcreation {
                                             }                                              }
                                             $chgtext .= '</ul>';                                              $chgtext .= '</ul>';
                                         } else {                                          } 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 />';                                              $chgtext .= &mt('When self creating account with e-mail as username, no information besides e-mail address will be provided by [_1].',"'$usertypes->{$type}'").'<br />';
                                         }                                          }
                                     } else {                                      } 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 />';                                          $chgtext .= &mt('When self creating account with e-mail as username, no information besides e-mail address will be provided by [_1].',"'$usertypes->{$type}'").'<br />';
                                     }                                      }
                                 }                                  }
                             }                              }
                         }                          }
                     } elsif ($type eq 'notify') {                      } elsif ($type eq 'notify') {
                         my $numapprove = 0;                          $chgtext = &mt('No Domain Coordinators will receive notification of username requests requiring approval.');
                         if (ref($changes{'cancreate'}) eq 'ARRAY') {                          if (ref($changes{'cancreate'}) eq 'ARRAY') {
                             if ((grep(/^notify$/,@{$changes{'cancreate'}})) && (ref($cancreate{'notify'}) eq 'HASH')) {                              if ((grep(/^notify$/,@{$changes{'cancreate'}})) && (ref($cancreate{'notify'}) eq 'HASH')) {
                                 if ($cancreate{'notify'}{'approval'}) {                                  if ($cancreate{'notify'}{'approval'}) {
                                     $chgtext .= &mt('Notification of username requests requiring approval will be sent to: ').$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) {                      if ($chgtext) {
                         $resulttext .= '<li>'.$chgtext.'</li>';                          $resulttext .= '<li>'.$chgtext.'</li>';
                     }                      }
                 }                  }
             }              }
             if ((ref($changes{'email_rule'}) eq 'ARRAY') && (@{$changes{'email_rule'}} > 0)) {              if (ref($changes{'email_rule'}) eq 'ARRAY') {
                 my ($emailrules,$emailruleorder) =                  my ($emailrules,$emailruleorder) =
                     &Apache::lonnet::inst_userrules($dom,'email');                      &Apache::lonnet::inst_userrules($dom,'email');
                 foreach my $type (@{$changes{'email_rule'}}) {                  my $chgtext = '<ul>';
                     if (ref($email_rule{$type}) eq 'ARRAY') {                  foreach my $type (@email_rule) {
                         my $chgtext = '<ul>';                      if (ref($emailrules->{$type}) eq 'HASH') {
                         foreach my $rule (@{$email_rule{$type}}) {                          $chgtext .= '<li>'.$emailrules->{$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 (ref($changes{'inststatus'}) eq 'ARRAY') {                  if (@email_rule > 0) {
                 if (ref($save_inststatus{'inststatusguest'}) eq 'ARRAY') {                      $resulttext .= '<li>'.
                     if (@{$save_inststatus{'inststatusguest'}} > 0) {                                     &mt('Accounts may not be created by users self-enrolling with e-mail addresses of the following types: ').
                         my $chgtext = '<ul>';                                         $chgtext.
                         foreach my $type (@{$save_inststatus{'inststatusguest'}}) {                                     '</li>';
                             $chgtext .= '<li>'.$usertypes{$type}.'</li>';                  } else {
                         }                      $resulttext .= '<li>'.
                         $chgtext .= '</ul>';                                     &mt('There are now no restrictions on e-mail addresses which may be used as a username when self-enrolling.').
                         $resulttext .= '<li>'.                                     '</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>';  
                     }  
                 }                  }
             }              }
             if (ref($changes{'selfcreate'}) eq 'ARRAY') {              if (ref($changes{'selfcreate'}) eq 'ARRAY') {
Line 12476  sub modify_selfcreation { Line 11631  sub modify_selfcreation {
                 my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();                  my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
                 foreach my $type (@{$changes{'selfcreate'}}) {                  foreach my $type (@{$changes{'selfcreate'}}) {
                     my $typename = $type;                      my $typename = $type;
                     if (keys(%usertypes) > 0) {                      if (ref($usertypes) eq 'HASH') {
                         if ($usertypes{$type} ne '') {                          if ($usertypes->{$type} ne '') {
                             $typename = $usertypes{$type};                              $typename = $usertypes->{$type};
                         }                          }
                     }                      }
                     my @modifiable;                      my @modifiable;
Line 12501  sub modify_selfcreation { Line 11656  sub modify_selfcreation {
                 $resulttext .= '</ul></li>';                  $resulttext .= '</ul></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 self-creation settings');
         }          }
Line 12521  sub modify_selfcreation { Line 11670  sub modify_selfcreation {
 }  }
   
 sub process_captcha {  sub process_captcha {
     my ($container,$changes,$newsettings,$currsettings) = @_;      my ($container,$changes,$newsettings,$current) = @_;
     return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH'));      return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH') || (ref($current) eq 'HASH'));
     $newsettings->{'captcha'} = $env{'form.'.$container.'_captcha'};      $newsettings->{'captcha'} = $env{'form.'.$container.'_captcha'};
     unless ($newsettings->{'captcha'} eq 'recaptcha' || $newsettings->{'captcha'} eq 'notused') {      unless ($newsettings->{'captcha'} eq 'recaptcha' || $newsettings->{'captcha'} eq 'notused') {
         $newsettings->{'captcha'} = 'original';          $newsettings->{'captcha'} = 'original';
     }      }
     my %current;      if ($current->{'captcha'} ne $newsettings->{'captcha'}) {
     if (ref($currsettings) eq 'HASH') {  
         %current = %{$currsettings};  
     }  
     if ($current{'captcha'} ne $newsettings->{'captcha'}) {  
         if ($container eq 'cancreate') {          if ($container eq 'cancreate') {
             if (ref($changes->{'cancreate'}) eq 'ARRAY') {              if (ref($changes->{'cancreate'}) eq 'ARRAY') {
                 push(@{$changes->{'cancreate'}},'captcha');                  push(@{$changes->{'cancreate'}},'captcha');
             } elsif (!defined($changes->{'cancreate'})) {              } elsif (!defined($changes->{'cancreate'})) {
                 $changes->{'cancreate'} = ['captcha'];                  $changes->{'cancreate'} = ['captcha'];
             }              }
         } elsif ($container eq 'passwords') {  
             $changes->{'reset'} = 1;  
         } else {          } else {
             $changes->{'captcha'} = 1;              $changes->{'captcha'} = 1;
         }          }
Line 12561  sub process_captcha { Line 11704  sub process_captcha {
         }          }
         $newsettings->{'recaptchaversion'} = $newversion;          $newsettings->{'recaptchaversion'} = $newversion;
     }      }
     if (ref($current{'recaptchakeys'}) eq 'HASH') {      if (ref($current->{'recaptchakeys'}) eq 'HASH') {
         $currpub = $current{'recaptchakeys'}{'public'};          $currpub = $current->{'recaptchakeys'}{'public'};
         $currpriv = $current{'recaptchakeys'}{'private'};          $currpriv = $current->{'recaptchakeys'}{'private'};
         unless ($newsettings->{'captcha'} eq 'recaptcha') {          unless ($newsettings->{'captcha'} eq 'recaptcha') {
             $newsettings->{'recaptchakeys'} = {              $newsettings->{'recaptchakeys'} = {
                                                  public  => '',                                                   public  => '',
Line 12571  sub process_captcha { Line 11714  sub process_captcha {
                                               }                                                }
         }          }
     }      }
     if ($current{'captcha'} eq 'recaptcha') {      if ($current->{'captcha'} eq 'recaptcha') {
         $currversion = $current{'recaptchaversion'};          $currversion = $current->{'recaptchaversion'};
         if ($currversion ne '2') {          if ($currversion ne '2') {
             $currversion = 1;              $currversion = 1;
         }          }
Line 12584  sub process_captcha { Line 11727  sub process_captcha {
             } elsif (!defined($changes->{'cancreate'})) {              } elsif (!defined($changes->{'cancreate'})) {
                 $changes->{'cancreate'} = ['recaptchaversion'];                  $changes->{'cancreate'} = ['recaptchaversion'];
             }              }
         } elsif ($container eq 'passwords') {  
             $changes->{'reset'} = 1;  
         } else {          } else {
             $changes->{'recaptchaversion'} = 1;              $changes->{'recaptchaversion'} = 1;
         }          }
Line 12597  sub process_captcha { Line 11738  sub process_captcha {
             } elsif (!defined($changes->{'cancreate'})) {              } elsif (!defined($changes->{'cancreate'})) {
                 $changes->{'cancreate'} = ['recaptchakeys'];                  $changes->{'cancreate'} = ['recaptchakeys'];
             }              }
         } elsif ($container eq 'passwords') {  
             $changes->{'reset'} = 1;  
         } else {          } else {
             $changes->{'recaptchakeys'} = 1;              $changes->{'recaptchakeys'} = 1;
         }          }
Line 12714  sub modify_defaults { Line 11853  sub modify_defaults {
     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,1);
     my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def',      my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def',
                  'portal_def');                   'portal_def','intauth_cost','intauth_check','intauth_switch');
     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 12756  sub modify_defaults { Line 11895  sub modify_defaults {
                     push(@errors,$item);                      push(@errors,$item);
                 }                  }
             }              }
           } elsif ($item eq 'intauth_cost') {
               if ($newvalues{$item} ne '') {
                   if ($newvalues{$item} =~ /\D/) {
                       push(@errors,$item);
                   }
               }
           } elsif ($item eq 'intauth_check') {
               if ($newvalues{$item} ne '') {
                   unless ($newvalues{$item} =~ /^(0|1|2)$/) {
                       push(@errors,$item);
                   }
               }
           } elsif ($item eq 'intauth_switch') {
               if ($newvalues{$item} ne '') {
                   unless ($newvalues{$item} =~ /^(0|1|2)$/) {
                       push(@errors,$item);
                   }
               }
         }          }
         if (grep(/^\Q$item\E$/,@errors)) {          if (grep(/^\Q$item\E$/,@errors)) {
             $newvalues{$item} = $domdefaults{$item};              $newvalues{$item} = $domdefaults{$item};
Line 12764  sub modify_defaults { Line 11921  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,
                         );                          );
Line 12794  sub modify_defaults { Line 11939  sub modify_defaults {
     }      }
     my @todelete = &Apache::loncommon::get_env_multiple('form.inststatus_delete');      my @todelete = &Apache::loncommon::get_env_multiple('form.inststatus_delete');
     my @allpos;      my @allpos;
       my %guests;
     my %alltypes;      my %alltypes;
     my @inststatusguest;      my ($currtitles,$currguests,$currorder);
     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) eq 'HASH') {
         if (ref($currinststatus->{'inststatusorder'}) eq 'ARRAY') {          if (ref($currinststatus->{'inststatusorder'}) eq 'ARRAY') {
             foreach my $type (@{$currinststatus->{'inststatusorder'}}) {              foreach my $type (@{$currinststatus->{'inststatusorder'}}) {
Line 12820  sub modify_defaults { Line 11956  sub modify_defaults {
                     $allpos[$position] = $type;                      $allpos[$position] = $type;
                     $alltypes{$type} = $env{'form.inststatus_title_'.$type};                      $alltypes{$type} = $env{'form.inststatus_title_'.$type};
                     $alltypes{$type} =~ s/`//g;                      $alltypes{$type} =~ s/`//g;
                       if ($env{'form.inststatus_guest_'.$type}) {
                           $guests{$type} = 1;
                       }
                 }                  }
             }              }
               if (ref($currinststatus->{'inststatusguest'}) eq 'ARRAY') {
                   $currguests = join(',',@{$currinststatus->{'inststatusguest'}});
               }
             $currorder = join(',',@{$currinststatus->{'inststatusorder'}});              $currorder = join(',',@{$currinststatus->{'inststatusorder'}});
             $currtitles =~ s/,$//;              $currtitles =~ s/,$//;
         }          }
Line 12830  sub modify_defaults { Line 11972  sub modify_defaults {
         my $newtype = $env{'form.addinststatus'};          my $newtype = $env{'form.addinststatus'};
         $newtype =~ s/\W//g;          $newtype =~ s/\W//g;
         unless (exists($alltypes{$newtype})) {          unless (exists($alltypes{$newtype})) {
               if ($env{'form.addinststatus_guest'}) {
                   $guests{$newtype} = 1;
               }
             $alltypes{$newtype} = $env{'form.addinststatus_title'};              $alltypes{$newtype} = $env{'form.addinststatus_title'};
             $alltypes{$newtype} =~ s/`//g;               $alltypes{$newtype} =~ s/`//g; 
             my $position = $env{'form.addinststatus_pos'};              my $position = $env{'form.addinststatus_pos'};
Line 12839  sub modify_defaults { Line 11984  sub modify_defaults {
             }              }
         }          }
     }      }
     my @orderedstatus;      my (@orderedstatus,@orderedguests);
     foreach my $type (@allpos) {      foreach my $type (@allpos) {
         unless (($type eq '') || (grep(/^\Q$type\E$/,@orderedstatus))) {          unless (($type eq '') || (grep(/^\Q$type\E$/,@orderedstatus))) {
             push(@orderedstatus,$type);              push(@orderedstatus,$type);
               if ($guests{$type}) {
                   push(@orderedguests,$type);
               }
         }          }
     }      }
     foreach my $type (keys(%alltypes)) {      foreach my $type (keys(%alltypes)) {
Line 12853  sub modify_defaults { Line 12001  sub modify_defaults {
     $defaults_hash{'inststatus'} = {      $defaults_hash{'inststatus'} = {
                                      inststatustypes => \%alltypes,                                       inststatustypes => \%alltypes,
                                      inststatusorder => \@orderedstatus,                                       inststatusorder => \@orderedstatus,
                                      inststatusguest => \@inststatusguest,                                       inststatusguest => \@orderedguests,
                                    };                                     };
     if (ref($defaults_hash{'inststatus'}) eq 'HASH') {      if (ref($defaults_hash{'inststatus'}) eq 'HASH') {
         foreach my $item ('inststatustypes','inststatusorder','inststatusguest') {          foreach my $item ('inststatustypes','inststatusorder','inststatusguest') {
Line 12863  sub modify_defaults { Line 12011  sub modify_defaults {
     if ($currorder ne join(',',@orderedstatus)) {      if ($currorder ne join(',',@orderedstatus)) {
         $changes{'inststatus'}{'inststatusorder'} = 1;          $changes{'inststatus'}{'inststatusorder'} = 1;
     }      }
       if ($currguests ne join(',',@orderedguests)) {
           $changes{'inststatus'}{'inststatusguest'} = 1;
       }
     my $newtitles;      my $newtitles;
     foreach my $item (@orderedstatus) {      foreach my $item (@orderedstatus) {
         $newtitles .= $alltypes{$item}.',';          $newtitles .= $alltypes{$item}.',';
Line 12881  sub modify_defaults { Line 12032  sub modify_defaults {
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
                 if ($item eq 'inststatus') {                  if ($item eq 'inststatus') {
                     if (ref($changes{'inststatus'}) eq 'HASH') {                      if (ref($changes{'inststatus'}) eq 'HASH') {
                         if (@orderedstatus) {                          if (($changes{'inststatus'}{'inststatustypes'}) || $changes{'inststatus'}{'inststatusorder'}) {
                             $resulttext .= '<li>'.&mt('Institutional user status types set to:').' ';                              $resulttext .= '<li>'.&mt('Institutional user status types set to:').' ';
                             foreach my $type (@orderedstatus) {                               foreach my $type (@orderedstatus) { 
                                 $resulttext .= $alltypes{$type}.', ';                                  $resulttext .= $alltypes{$type}.', ';
                             }                              }
                             $resulttext =~ s/, $//;                              $resulttext =~ s/, $//;
                             $resulttext .= '</li>';                              $resulttext .= '</li>';
                         } else {                          }
                             $resulttext .= '<li>'.&mt('Institutional user status types deleted').'</li>';                          if ($changes{'inststatus'}{'inststatusguest'}) {
                               $resulttext .= '<li>'; 
                               if (@orderedguests) {
                                   $resulttext .= &mt('Types assignable to "non-institutional" usernames set to:').' ';
                                   foreach my $type (@orderedguests) {
                                       $resulttext .= $alltypes{$type}.', ';
                                   }
                                   $resulttext =~ s/, $//;
                               } else {
                                   $resulttext .= &mt('Types assignable to "non-institutional" usernames set to none.');
                               }
                               $resulttext .= '</li>';
                         }                          }
                     }                      }
                 } else {                  } else {
Line 12905  sub modify_defaults { Line 12067  sub modify_defaults {
                                           localauth  => 'loc',                                            localauth  => 'loc',
                         );                          );
                         $value = $authnames{$shortauth{$value}};                          $value = $authnames{$shortauth{$value}};
                       } elsif ($item eq 'intauth_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 'intauth_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]"',$title->{$item},$value).'</li>';                      $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$item},$value).'</li>';
                     $mailmsgtext .= "$title->{$item} set to $value\n";                        $mailmsgtext .= "$title->{$item} set to $value\n";  
Line 12953  sub modify_scantron { Line 12137  sub modify_scantron {
     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 12172  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 12182  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') {                  if (ref($lastactref) eq 'HASH') {
                     $lastactref->{'domainconfig'} = 1;                      $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 13149  sub modify_coursecategories { Line 12237  sub modify_coursecategories {
         if ($domconfig{'coursecategories'}{'categorizecomm'} ne $env{'form.categorizecomm'}) {          if ($domconfig{'coursecategories'}{'categorizecomm'} ne $env{'form.categorizecomm'}) {
             $changes{'categorizecomm'} = 1;              $changes{'categorizecomm'} = 1;
             $domconfig{'coursecategories'}{'categorizecomm'} = $env{'form.categorizecomm'};              $domconfig{'coursecategories'}{'categorizecomm'} = $env{'form.categorizecomm'};
   
           }
           if ($domconfig{'coursecategories'}{'togglecatsplace'} ne $env{'form.togglecatsplace'}) {
               $changes{'togglecatsplace'} = 1;
               $domconfig{'coursecategories'}{'togglecatsplace'} = $env{'form.togglecatsplace'};
           }
           if ($domconfig{'coursecategories'}{'categorizeplace'} ne $env{'form.categorizeplace'}) {
               $changes{'categorizeplace'} = 1;
               $domconfig{'coursecategories'}{'categorizeplace'} = $env{'form.categorizeplace'};
         }          }
         foreach my $item (@catitems) {          foreach my $item (@catitems) {
             if (grep(/^\Q$env{'form.coursecat_'.$item}\E$/,@cattypes)) {              if (grep(/^\Q$env{'form.coursecat_'.$item}\E$/,@cattypes)) {
Line 13163  sub modify_coursecategories { Line 12260  sub modify_coursecategories {
         $changes{'categorize'} = 1;          $changes{'categorize'} = 1;
         $changes{'togglecatscomm'} = 1;          $changes{'togglecatscomm'} = 1;
         $changes{'categorizecomm'} = 1;          $changes{'categorizecomm'} = 1;
           $changes{'togglecatsplace'} = 1;
           $changes{'categorizeplace'} = 1;
         $domconfig{'coursecategories'} = {          $domconfig{'coursecategories'} = {
                                              togglecats => $env{'form.togglecats'},                                               togglecats => $env{'form.togglecats'},
                                              categorize => $env{'form.categorize'},                                               categorize => $env{'form.categorize'},
                                              togglecatscomm => $env{'form.togglecatscomm'},                                               togglecatscomm => $env{'form.togglecatscomm'},
                                              categorizecomm => $env{'form.categorizecomm'},                                               categorizecomm => $env{'form.categorizecomm'},
                                                togglecatsplace => $env{'form.togglecatsplace'},
                                                categorizeplace => $env{'form.categorizeplace'},
                                          };                                           };
         foreach my $item (@catitems) {          foreach my $item (@catitems) {
             if ($env{'form.coursecat_'.$item} ne 'std') {              if ($env{'form.coursecat_'.$item} ne 'std') {
Line 13185  sub modify_coursecategories { Line 12286  sub modify_coursecategories {
         if (($domconfig{'coursecategories'}{'cats'}{'communities::0'} ne '')  && ($env{'form.communities'} == 0)) {          if (($domconfig{'coursecategories'}{'cats'}{'communities::0'} ne '')  && ($env{'form.communities'} == 0)) {
             push(@deletecategory,'communities::0');              push(@deletecategory,'communities::0');
         }          }
           if (($domconfig{'coursecategories'}{'cats'}{'placement::0'} ne '')  && ($env{'form.placement'} == 0)) {
               push(@deletecategory,'placement::0');
           }
     }      }
     my (@predelcats,@predeltrails,%predelallitems,%sort_by_deltrail);      my (@predelcats,@predeltrails,%predelallitems,%sort_by_deltrail);
     if (ref($cathash) eq 'HASH') {      if (ref($cathash) eq 'HASH') {
Line 13247  sub modify_coursecategories { Line 12351  sub modify_coursecategories {
             $adds{$newitem} = 1;              $adds{$newitem} = 1;
         }          }
     }      }
       if ($env{'form.placement'} eq '1') {
           if (ref($cathash) eq 'HASH') {
               my $newitem = 'placement::0';
               if ($cathash->{$newitem} eq '') {
                   $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.placement_pos'};
                   $adds{$newitem} = 1;
               }
           } else {
               my $newitem = 'placement::0';
               $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.placement_pos'};
               $adds{$newitem} = 1;
           }
       }
     if ($env{'form.addcategory_name'} ne '') {      if ($env{'form.addcategory_name'} ne '') {
         if (($env{'form.addcategory_name'} ne 'instcode') &&          if (($env{'form.addcategory_name'} ne 'instcode') &&
             ($env{'form.addcategory_name'} ne 'communities')) {              ($env{'form.addcategory_name'} ne 'communities') &&
               ($env{'form.addcategory_name'} ne 'placement')) {
             my $newitem = &escape($env{'form.addcategory_name'}).'::0';              my $newitem = &escape($env{'form.addcategory_name'}).'::0';
             $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.addcategory_pos'};              $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.addcategory_pos'};
             $adds{$newitem} = 1;              $adds{$newitem} = 1;
Line 13365  sub modify_coursecategories { Line 12483  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'}) {              if ($changes{'unauth'} || $changes{'auth'}) {
Line 13765  sub modify_helpsettings { Line 12879  sub modify_helpsettings {
                                                                    order  => 'Order',                                                                     order  => 'Order',
                                                                    desc   => 'Role description',                                                                     desc   => 'Role description',
                                                                    access => 'Role usage',                                                                     access => 'Role usage',
                                                                    status => 'Allowed institutional types',                                                                     status => 'Allowed instituional types',
                                                                    exc    => 'Allowed personnel',                                                                     exc    => 'Allowed personnel',
                                                                    inc    => 'Disallowed personnel',                                                                     inc    => 'Disallowed personnel',
                         );                          );
Line 13848  sub modify_coursedefaults { Line 12962  sub modify_coursedefaults {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,$errors,%changes,%defaultshash);      my ($resulttext,$errors,%changes,%defaultshash);
     my %defaultchecked = (      my %defaultchecked = (
                              'canuse_pdfforms' => 'off',
                            'uselcmath'       => 'on',                             'uselcmath'       => 'on',
                            'usejsme'         => 'on'                             'usejsme'         => 'on'
                          );                           );
     my @toggles = ('uselcmath','usejsme');      my @toggles = ('canuse_pdfforms','uselcmath','usejsme');
     my @numbers = ('anonsurvey_threshold','uploadquota_official','uploadquota_unofficial',      my @numbers = ('anonsurvey_threshold','uploadquota_official','uploadquota_unofficial',
                    'uploadquota_community','uploadquota_textbook','mysqltables_official',                     'uploadquota_community','uploadquota_textbook','uploadquota_placement',
                    'mysqltables_unofficial','mysqltables_community','mysqltables_textbook');                     'mysqltables_official','mysqltables_unofficial','mysqltables_community',
     my @types = ('official','unofficial','community','textbook');                     'mysqltables_textbook','mysqltables_placement');
       my @types = ('official','unofficial','community','textbook','placement');
     my %staticdefaults = (      my %staticdefaults = (
                            anonsurvey_threshold => 10,                             anonsurvey_threshold => 10,
                            uploadquota          => 500,                             uploadquota          => 500,
                            postsubmit           => 60,                             postsubmit           => 60,
                            mysqltables          => 172800,                             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 13913  sub modify_coursedefaults { Line 13025  sub modify_coursedefaults {
                 $defaultshash{'coursedefaults'}{$setting}{$type} = $newdef;                  $defaultshash{'coursedefaults'}{$setting}{$type} = $newdef;
             }              }
             if ($currdef ne $newdef) {              if ($currdef ne $newdef) {
                   my $staticdef;
                 if ($item eq 'anonsurvey_threshold') {                  if ($item eq 'anonsurvey_threshold') {
                     unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) {                      unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) {
                         $changes{$item} = 1;                          $changes{$item} = 1;
Line 13925  sub modify_coursedefaults { Line 13038  sub modify_coursedefaults {
                 }                  }
             }              }
         }          }
         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 $currclone = $domconfig{'coursedefaults'}{'canclone'};
         my @currclonecode;          my @currclonecode;
         if (ref($currclone) eq 'HASH') {          if (ref($currclone) eq 'HASH') {
Line 14058  sub modify_coursedefaults { Line 13156  sub modify_coursedefaults {
     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);              my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
             if (($changes{'uploadquota'}) || ($changes{'postsubmit'}) ||              if (($changes{'canuse_pdfforms'}) || ($changes{'uploadquota'}) || ($changes{'postsubmit'}) ||
                 ($changes{'coursecredits'}) || ($changes{'uselcmath'}) || ($changes{'usejsme'}) ||                  ($changes{'coursecredits'}) || ($changes{'uselcmath'}) || ($changes{'usejsme'}) ||
                 ($changes{'canclone'}) || ($changes{'mysqltables'}) || ($changes{'texengine'})) {                  ($changes{'canclone'}) || ($changes{'mysqltables'})) {
                 foreach my $item ('uselcmath','usejsme','texengine') {                  foreach my $item ('canuse_pdfforms','uselcmath','usejsme') { 
                     if ($changes{$item}) {                      if ($changes{$item}) {
                         $domdefaults{$item}=$defaultshash{'coursedefaults'}{$item};                          $domdefaults{$item}=$defaultshash{'coursedefaults'}{$item};
                     }                      }
Line 14112  sub modify_coursedefaults { Line 13210  sub modify_coursedefaults {
             }              }
             $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') {
                           $resulttext .= '<li>'.&mt("Course/Community users can create/upload PDF forms set to 'on'").'</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('Course/Community users can create/upload PDF forms set to "off"').'</li>';
                       }
                   } elsif ($item eq 'uselcmath') {
                     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('Math preview uses LON-CAPA previewer (javascript), if supported by browser.').'</li>';
                     } else {                      } else {
Line 14124  sub modify_coursedefaults { Line 13228  sub modify_coursedefaults {
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('Molecule editor uses JME (Java), if supported by client OS.').'</li>';                          $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') {                  } elsif ($item eq 'uploadquota') {
Line 14137  sub modify_coursedefaults { Line 13236  sub modify_coursedefaults {
                                        '<li>'.&mt('Official courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'official'}.'</b>').'</li>'.                                         '<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('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('Textbook courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'textbook'}.'</b>').'</li>'.
                                          '<li>'.&mt('Placement tests: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'placement'}.'</b>').'</li>'. 
                                        '<li>'.&mt('Communities: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'community'}.'</b>').'</li>'.                                         '<li>'.&mt('Communities: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'community'}.'</b>').'</li>'.
                                        '</ul>'.                                         '</ul>'.
                                        '</li>';                                         '</li>';
Line 14150  sub modify_coursedefaults { Line 13249  sub modify_coursedefaults {
                                        '<li>'.&mt('Official courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'official'}.'</b>').'</li>'.                                         '<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('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('Textbook courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'textbook'}.'</b>').'</li>'.
                                          '<li>'.&mt('Placement tests: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'placement'}.'</b>').'</li>'.
                                        '<li>'.&mt('Communities: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'community'}.'</b>').'</li>'.                                         '<li>'.&mt('Communities: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'community'}.'</b>').'</li>'.
                                        '</ul>'.                                         '</ul>'.
                                        '</li>';                                         '</li>';
Line 14185  sub modify_coursedefaults { Line 13285  sub modify_coursedefaults {
                                     $resulttext .= &mt('Unofficial courses');                                      $resulttext .= &mt('Unofficial courses');
                                 } elsif ($type eq 'textbook') {                                  } elsif ($type eq 'textbook') {
                                     $resulttext .= &mt('Textbook courses');                                      $resulttext .= &mt('Textbook courses');
                                   } elsif ($type eq 'placement') {
                                       $resulttext .= &mt('Placement tests');
                                 }                                  }
                                 $resulttext .= ' -- '.$display.'</li>';                                  $resulttext .= ' -- '.$display.'</li>';
                             }                              }
Line 14236  sub modify_coursedefaults { Line 13338  sub modify_coursedefaults {
 sub modify_selfenrollment {  sub modify_selfenrollment {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,$errors,%changes,%selfenrollhash,%ordered);      my ($resulttext,$errors,%changes,%selfenrollhash,%ordered);
     my @types = ('official','unofficial','community','textbook');      my @types = ('official','unofficial','community','textbook','placement');
     my %titles = &tool_titles();      my %titles = &tool_titles();
     my %descs = &Apache::lonuserutils::selfenroll_default_descs();      my %descs = &Apache::lonuserutils::selfenroll_default_descs();
     ($ordered{'admin'},my $titlesref) = &Apache::lonuserutils::get_selfenroll_titles();      ($ordered{'admin'},my $titlesref) = &Apache::lonuserutils::get_selfenroll_titles();
Line 14453  sub modify_selfenrollment { Line 13555  sub modify_selfenrollment {
                         $resulttext .= '</ul></li>';                           $resulttext .= '</ul></li>'; 
                     }                      }
                 }                  }
             }                  if ((exists($changes{'admin'})) || (exists($changes{'default'}))) {
             if ((exists($changes{'admin'})) || (exists($changes{'default'}))) {                      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') {
                 if (ref($lastactref) eq 'HASH') {                          $lastactref->{'domdefaults'} = 1;
                     $lastactref->{'domdefaults'} = 1;                      }
                 }                  }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
Line 14483  sub modify_usersessions { Line 13585  sub modify_usersessions {
                 );                  );
     my @prefixes = ('remote','hosted','spares');      my @prefixes = ('remote','hosted','spares');
     my @lcversions = &Apache::lonnet::all_loncaparevs();      my @lcversions = &Apache::lonnet::all_loncaparevs();
     my (%by_ip,%by_location,@intdoms);      my (%by_ip,%by_location,@intdoms,@instdoms);
     &build_location_hashes(\@intdoms,\%by_ip,\%by_location);      &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
     my @locations = sort(keys(%by_location));      my @locations = sort(keys(%by_location));
     my (%defaultshash,%changes);      my (%defaultshash,%changes);
     foreach my $prefix (@prefixes) {      foreach my $prefix (@prefixes) {
Line 14639  sub modify_usersessions { Line 13741  sub modify_usersessions {
         }          }
     }      }
     $defaultshash{'usersessions'}{'offloadnow'} = {};      $defaultshash{'usersessions'}{'offloadnow'} = {};
     $defaultshash{'usersessions'}{'offloadoth'} = {};  
     my @offloadnow = &Apache::loncommon::get_env_multiple('form.offloadnow');      my @offloadnow = &Apache::loncommon::get_env_multiple('form.offloadnow');
     my @okoffload;      my @okoffload;
     if (@offloadnow) {      if (@offloadnow) {
Line 14656  sub modify_usersessions { Line 13757  sub modify_usersessions {
             }              }
         }          }
     }      }
     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 13767  sub modify_usersessions {
         } else {          } else {
             $savespares = 1;              $savespares = 1;
         }          }
         foreach my $offload ('offloadnow','offloadoth') {          if (ref($domconfig{'usersessions'}{'offloadnow'}) eq 'HASH') {
             if (ref($domconfig{'usersessions'}{$offload}) eq 'HASH') {              foreach my $lonhost (keys(%{$domconfig{'usersessions'}{'offloadnow'}})) {
                 foreach my $lonhost (keys(%{$domconfig{'usersessions'}{$offload}})) {                  unless ($defaultshash{'usersessions'}{'offloadnow'}{$lonhost}) {
                     unless ($defaultshash{'usersessions'}{$offload}{$lonhost}) {                      $changes{'offloadnow'} = 1;
                         $changes{$offload} = 1;                      last;
                         last;  
                     }  
                 }                  }
                 unless ($changes{$offload}) {              }
                     foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{$offload}})) {              unless ($changes{'offloadnow'}) {
                         unless ($domconfig{'usersessions'}{$offload}{$lonhost}) {                  foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{'offloadnow'}})) {
                             $changes{$offload} = 1;                      unless ($domconfig{'usersessions'}{'offloadnow'}{$lonhost}) {
                             last;                          $changes{'offloadnow'} = 1;
                         }                          last;
                     }                      }
                 }                  }
             } else {  
                 if (($offload eq 'offloadnow') && (@okoffload)) {  
                      $changes{'offloadnow'} = 1;  
                 }  
                 if (($offload eq 'offloadoth') && (@okoffloadoth)) {  
                     $changes{'offloadoth'} = 1;  
                 }  
             }              }
         }          } elsif (@okoffload) {
     } else {  
         if (@okoffload) {  
             $changes{'offloadnow'} = 1;              $changes{'offloadnow'} = 1;
         }          }
         if (@okoffloadoth) {      } elsif (@okoffload) {
             $changes{'offloadoth'} = 1;          $changes{'offloadnow'} = 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)) {
Line 14730  sub modify_usersessions { Line 13803  sub modify_usersessions {
                 if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {                  if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
                     $domdefaults{'offloadnow'} = $defaultshash{'usersessions'}{'offloadnow'};                      $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') {              if (ref($lastactref) eq 'HASH') {
                 $lastactref->{'domdefaults'} = 1;                  $lastactref->{'domdefaults'} = 1;
                 $lastactref->{'usersessions'} = 1;  
             }              }
             if (keys(%changes) > 0) {              if (keys(%changes) > 0) {
                 my %lt = &usersession_titles();                  my %lt = &usersession_titles();
Line 14806  sub modify_usersessions { Line 13874  sub modify_usersessions {
                 if ($changes{'offloadnow'}) {                  if ($changes{'offloadnow'}) {
                     if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {                      if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
                         if (keys(%{$defaultshash{'usersessions'}{'offloadnow'}}) > 0) {                          if (keys(%{$defaultshash{'usersessions'}{'offloadnow'}}) > 0) {
                             $resulttext .= '<li>'.&mt('Switch any active user on next access, for server(s):').'<ul>';                              $resulttext .= '<li>'.&mt('Switch active users on next access, for server(s):').'<ul>';
                             foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadnow'}}))) {                              foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadnow'}}))) {
                                 $resulttext .= '<li>'.$lonhost.'</li>';                                  $resulttext .= '<li>'.$lonhost.'</li>';
                             }                              }
                             $resulttext .= '</ul>';                              $resulttext .= '</ul>';
                         } else {                          } else {
                             $resulttext .= '<li>'.&mt('No servers now set to switch any active user on next access.');                              $resulttext .= '<li>'.&mt('No servers now set to switch active users on next access.');
                         }                          }
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('No servers now set to switch any active user on next access.').'</li>';                          $resulttext .= '<li>'.&mt('No servers now set to switch active users on next access.').'</li>';
                     }                      }
                 }                  }
                 if ($changes{'offloadoth'}) {                  $resulttext .= '</ul>';
                     if (ref($defaultshash{'usersessions'}{'offloadoth'}) eq 'HASH') {              } else {
                         if (keys(%{$defaultshash{'usersessions'}{'offloadoth'}}) > 0) {                  $resulttext = $nochgmsg;
                             $resulttext .= '<li>'.&mt('Switch other institutions on next access, for server(s):').'<ul>';              }
                             foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadoth'}}))) {          } else {
                                 $resulttext .= '<li>'.$lonhost.'</li>';              $resulttext = '<span class="LC_error">'.
                             &mt('An error occurred: [_1]',$putresult).'</span>';
           }
       } else {
           $resulttext = $nochgmsg;
       }
       return $resulttext;
   }
   
   sub modify_ssl {
       my ($dom,$lastactref,%domconfig) = @_;
       my (%by_ip,%by_location,@intdoms,@instdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
       my @locations = sort(keys(%by_location));
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my (%defaultshash,%changes);
       my $action = 'ssl';
       my @prefixes = ('connto','connfrom','replication');
       foreach my $prefix (@prefixes) {
           $defaultshash{$action}{$prefix} = {};
       }
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
       my $resulttext;
       my %iphost = &Apache::lonnet::get_iphost();
       my @reptypes = ('certreq','nocertreq');
       my @connecttypes = ('dom','intdom','other');
       my %types = (
                     connto      => \@connecttypes,
                     connfrom    => \@connecttypes,
                     replication => \@reptypes,
                   );
       foreach my $prefix (sort(keys(%types))) {
           foreach my $type (@{$types{$prefix}}) {
               if (($prefix eq 'connto') || ($prefix eq 'connfrom')) {
                   my $value = 'yes';
                   if ($env{'form.'.$prefix.'_'.$type} =~ /^(no|req)$/) {
                       $value = $env{'form.'.$prefix.'_'.$type};
                   }
                   if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
                       if ($domconfig{$action}{$prefix}{$type} ne '') {
                           if ($value ne $domconfig{$action}{$prefix}{$type}) {
                               $changes{$prefix}{$type} = 1;
                           }
                           $defaultshash{$action}{$prefix}{$type} = $value;
                       } else {
                           $defaultshash{$action}{$prefix}{$type} = $value;
                           $changes{$prefix}{$type} = 1;
                       }
                   } else {
                       $defaultshash{$action}{$prefix}{$type} = $value;
                       $changes{$prefix}{$type} = 1;
                   }
                   if (($type eq 'dom') && (keys(%servers) == 1)) {
                       delete($changes{$prefix}{$type});
                   } elsif (($type eq 'intdom') && (@instdoms == 1)) {
                       delete($changes{$prefix}{$type});
                   } elsif (($type eq 'other') && (keys(%by_location) == 0)) { 
                       delete($changes{$prefix}{$type});
                   }
               } elsif ($prefix eq 'replication') {
                   if (@locations > 0) {
                       my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
                       my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
                       my @okvals;
                       foreach my $val (@vals) {
                           if ($val =~ /:/) {
                               my @items = split(/:/,$val);
                               foreach my $item (@items) {
                                   if (ref($by_location{$item}) eq 'ARRAY') {
                                       push(@okvals,$item);
                                   }
                             }                              }
                             $resulttext .= '</ul>';  
                         } else {                          } else {
                             $resulttext .= '<li>'.&mt('No servers now set to switch other institutions on next access.');                              if (ref($by_location{$val}) eq 'ARRAY') {
                                   push(@okvals,$val);
                               }
                           }
                       }
                       @okvals = sort(@okvals);
                       if (ref($domconfig{$action}) eq 'HASH') {
                           if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
                               if (ref($domconfig{$action}{$prefix}{$type}) eq 'ARRAY') {
                                   if ($inuse == 0) {
                                       $changes{$prefix}{$type} = 1;
                                   } else {
                                       $defaultshash{$action}{$prefix}{$type} = \@okvals;
                                       my @changed = &Apache::loncommon::compare_arrays($domconfig{$action}{$prefix}{$type},$defaultshash{$action}{$prefix}{$type});
                                       if (@changed > 0) {
                                           $changes{$prefix}{$type} = 1;
                                       }
                                   }
                               } else {
                                   if ($inuse == 1) {
                                       $defaultshash{$action}{$prefix}{$type} = \@okvals;
                                       $changes{$prefix}{$type} = 1;
                                   }
                               }
                           } else {
                               if ($inuse == 1) {
                                   $defaultshash{$action}{$prefix}{$type} = \@okvals;
                                   $changes{$prefix}{$type} = 1;
                               }
                           }
                       } else {
                           if ($inuse == 1) {
                               $defaultshash{$action}{$prefix}{$type} = \@okvals;
                               $changes{$prefix}{$type} = 1;
                           }
                       }
                   }
               }
           }
       }
       my $nochgmsg = &mt('No changes made to LON-CAPA SSL settings');
       if (keys(%changes) > 0) {
           my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                                    $dom);
           if ($putresult eq 'ok') {
               if (ref($defaultshash{$action}) eq 'HASH') {
                   if (ref($defaultshash{$action}{'replication'}) eq 'HASH') {
                       $domdefaults{'replication'} = $defaultshash{$action}{'replication'};
                   }
                   if (ref($defaultshash{$action}{'connto'}) eq 'HASH') {
                       $domdefaults{'connto'} = $domconfig{$action}{'connto'};
                   }
                   if (ref($defaultshash{$action}{'connfrom'}) eq 'HASH') {
                       $domdefaults{'connfrom'} = $domconfig{$action}{'connfrom'};
                   }
               }
               my $cachetime = 24*60*60;
               &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
               }
               if (keys(%changes) > 0) {
                   my %titles = &ssl_titles();
                   $resulttext = &mt('Changes made:').'<ul>';
                   foreach my $prefix (@prefixes) {
                       if (ref($changes{$prefix}) eq 'HASH') {
                           $resulttext .= '<li>'.$titles{$prefix}.'<ul>';
                           foreach my $type (@{$types{$prefix}}) {
                               if (defined($changes{$prefix}{$type})) {
                                   my $newvalue;
                                   if (ref($defaultshash{$action}) eq 'HASH') {
                                       if (ref($defaultshash{$action}{$prefix})) {
                                           if (($prefix eq 'connto') || ($prefix eq 'connfrom')) {
                                               $newvalue = $titles{$defaultshash{$action}{$prefix}{$type}};
                                           } elsif (ref($defaultshash{$action}{$prefix}{$type}) eq 'ARRAY') {
                                               if (@{$defaultshash{$action}{$prefix}{$type}} > 0) {
                                                   $newvalue = join(', ',@{$defaultshash{$action}{$prefix}{$type}});
                                               }
                                           }
                                       }
                                       if ($newvalue eq '') {
                                           $resulttext .= '<li>'.&mt('[_1] set to: none',$titles{$type}).'</li>';
                                       } else {
                                           $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$titles{$type},$newvalue).'</li>';
                                       }
                                   }
                               }
                           }
                           $resulttext .= '</ul>';
                       }
                   }
               } else {
                   $resulttext = $nochgmsg;
               }
           } else {
               $resulttext = '<span class="LC_error">'.
                             &mt('An error occurred: [_1]',$putresult).'</span>';
           }
       } else {
           $resulttext = $nochgmsg;
       }
       return $resulttext;
   }
   
   sub modify_trust {
       my ($dom,$lastactref,%domconfig) = @_;
       my (%by_ip,%by_location,@intdoms,@instdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
       my @locations = sort(keys(%by_location));
       my @prefixes = qw(content shared enroll othcoau coaurem domroles catalog reqcrs msg);
       my @types = ('exc','inc');
       my (%defaultshash,%changes);
       foreach my $prefix (@prefixes) {
           $defaultshash{'trust'}{$prefix} = {};
       }
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
       my $resulttext;
       foreach my $prefix (@prefixes) {
           foreach my $type (@types) {
               my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
               my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
               my @okvals;
               foreach my $val (@vals) {
                   if ($val =~ /:/) {
                       my @items = split(/:/,$val);
                       foreach my $item (@items) {
                           if (ref($by_location{$item}) eq 'ARRAY') {
                               push(@okvals,$item);
                           }
                       }
                   } else {
                       if (ref($by_location{$val}) eq 'ARRAY') {
                           push(@okvals,$val);
                       }
                   }
               }
               @okvals = sort(@okvals);
               if (ref($domconfig{'trust'}) eq 'HASH') {
                   if (ref($domconfig{'trust'}{$prefix}) eq 'HASH') {
                       if (ref($domconfig{'trust'}{$prefix}{$type}) eq 'ARRAY') {
                           if ($inuse == 0) {
                               $changes{$prefix}{$type} = 1;
                           } else {
                               $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                               my @changed = &Apache::loncommon::compare_arrays($domconfig{'trust'}{$prefix}{$type},$defaultshash{'trust'}{$prefix}{$type});
                               if (@changed > 0) {
                                   $changes{$prefix}{$type} = 1;
                               }
                         }                          }
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('No servers now set to switch other institutions on next access.').'</li>';                          if ($inuse == 1) {
                               $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                               $changes{$prefix}{$type} = 1;
                           }
                       }
                   } else {
                       if ($inuse == 1) {
                           $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                           $changes{$prefix}{$type} = 1;
                       }
                   }
               } else {
                   if ($inuse == 1) {
                       $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                       $changes{$prefix}{$type} = 1;
                   }
               }
           }
       }
       my $nochgmsg = &mt('No changes made to trust settings.');
       if (keys(%changes) > 0) {
           my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                                    $dom);
           if ($putresult eq 'ok') {
               if (ref($defaultshash{'trust'}) eq 'HASH') {
                   foreach my $prefix (@prefixes) {
                       if (ref($defaultshash{'trust'}{$prefix}) eq 'HASH') {
                           $domdefaults{'trust'.$prefix} = $defaultshash{'trust'}{$prefix};
                       }
                   }
               }
               my $cachetime = 24*60*60;
               &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
               }
               if (keys(%changes) > 0) {
                   my %lt = &trust_titles();
                   $resulttext = &mt('Changes made:').'<ul>';
                   foreach my $prefix (@prefixes) {
                       if (ref($changes{$prefix}) eq 'HASH') {
                           $resulttext .= '<li>'.$lt{$prefix}.'<ul>';
                           foreach my $type (@types) {
                               if (defined($changes{$prefix}{$type})) {
                                   my $newvalue;
                                   if (ref($defaultshash{'trust'}) eq 'HASH') {
                                       if (ref($defaultshash{'trust'}{$prefix})) {
                                           if (ref($defaultshash{'trust'}{$prefix}{$type}) eq 'ARRAY') {
                                               if (@{$defaultshash{'trust'}{$prefix}{$type}} > 0) {
                                                   $newvalue = join(', ',@{$defaultshash{'trust'}{$prefix}{$type}});
                                               }
                                           }
                                       }
                                   }
                                   if ($newvalue eq '') {
                                       $resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';
                                   } else {
                                       $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';
                                   }
                               }
                           }
                           $resulttext .= '</ul>';
                     }                      }
                 }                  }
                 $resulttext .= '</ul>';                  $resulttext .= '</ul>';
Line 14858  sub modify_loadbalancing { Line 14203  sub modify_loadbalancing {
     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);      my (%currbalancer,%currtargets,%currrules,%existing);
     if (ref($domconfig{'loadbalancing'}) eq 'HASH') {      if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
         %existing = %{$domconfig{'loadbalancing'}};          %existing = %{$domconfig{'loadbalancing'}};
     }      }
     &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,      &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
                               \%currtargets,\%currrules,\%currcookies);                                \%currtargets,\%currrules);
     my ($saveloadbalancing,%defaultshash,%changes);      my ($saveloadbalancing,%defaultshash,%changes);
     my ($alltypes,$othertypes,$titles) =      my ($alltypes,$othertypes,$titles) =
         &loadbalancing_titles($dom,$intdom,$usertypes,$types);          &loadbalancing_titles($dom,$intdom,$usertypes,$types);
Line 14915  sub modify_loadbalancing { Line 14260  sub modify_loadbalancing {
             }              }
             $defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto;              $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{$balancer}) eq 'HASH') {
             foreach my $sparetype (@sparestypes) {              foreach my $sparetype (@sparestypes) {
                 if (ref($currtargets{$balancer}{$sparetype}) eq 'ARRAY') {                  if (ref($currtargets{$balancer}{$sparetype}) eq 'ARRAY') {
Line 15080  sub modify_loadbalancing { Line 14413  sub modify_loadbalancing {
                                 }                                  }
                             }                              }
                         }                          }
                         if ($changes{'curr'}{$balancer}{'cookie'}) {                          if (keys(%toupdate)) {
                             $resulttext .= '<li>'.&mt('Load Balancer: [_1] -- cookie use enabled',                              my %thismachine;
                                                       $balancer).'</li>';                              my $updatedhere;
                         }                              my $cachetime = 60*60*24;
                     }                              map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
                 }                              foreach my $lonhost (keys(%toupdate)) {
                 if (keys(%toupdate)) {                                  if ($thismachine{$lonhost}) {
                     my %thismachine;                                      unless ($updatedhere) {
                     my $updatedhere;                                          &Apache::lonnet::do_cache_new('loadbalancing',$dom,
                     my $cachetime = 60*60*24;                                                                        $defaultshash{'loadbalancing'},
                     map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();                                                                        $cachetime);
                     foreach my $lonhost (keys(%toupdate)) {                                          $updatedhere = 1;
                         if ($thismachine{$lonhost}) {                                      }
                             unless ($updatedhere) {                                  } else {
                                 &Apache::lonnet::do_cache_new('loadbalancing',$dom,                                      my $cachekey = &escape('loadbalancing').':'.&escape($dom);
                                                               $defaultshash{'loadbalancing'},                                      &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
                                                               $cachetime);                                  }
                                 $updatedhere = 1;  
                             }                              }
                         } else {  
                             my $cachekey = &escape('loadbalancing').':'.&escape($dom);  
                             &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);  
                         }                          }
                     }                      }
                 }                  }
Line 15313  sub lonbalance_targets_js { Line 14642  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);      my (%currbalancer,%currtargets,%currrules,%existing);
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         %existing = %{$settings};          %existing = %{$settings};
     }      }
     &get_loadbalancers_config($servers,\%existing,\%currbalancer,      &get_loadbalancers_config($servers,\%existing,\%currbalancer,
                               \%currtargets,\%currrules,\%currcookies);                                \%currtargets,\%currrules);
     my $balancers = join("','",sort(keys(%currbalancer)));      my $balancers = join("','",sort(keys(%currbalancer)));
     return <<"END";      return <<"END";
   
Line 15803  function toggleDisplay(domForm,caller) { Line 15132  function toggleDisplay(domForm,caller) {
         var optionsElement = domForm.coursecredits;          var optionsElement = domForm.coursecredits;
         var checkval = 1;          var checkval = 1;
         var dispval = 'block';          var dispval = 'block';
         var selfcreateRegExp = /^cancreate_emailverified/;  
         if (caller == 'emailoptions') {          if (caller == 'emailoptions') {
             optionsElement = domForm.cancreate_email;               optionsElement = domForm.cancreate_email; 
         }          }
Line 15814  function toggleDisplay(domForm,caller) { Line 15142  function toggleDisplay(domForm,caller) {
             optionsElement = domForm.canclone;              optionsElement = domForm.canclone;
             checkval = 'instcode';              checkval = 'instcode';
         }          }
         if (selfcreateRegExp.test(caller)) {  
             optionsElement = domForm.elements[caller];  
             checkval = 'other';  
             dispval = 'inline'  
         }  
         if (optionsElement.length) {          if (optionsElement.length) {
             var currval;              var currval;
             for (var i=0; i<optionsElement.length; i++) {              for (var i=0; i<optionsElement.length; i++) {
Line 15860  sub devalidate_remote_domconfs { Line 15183  sub devalidate_remote_domconfs {
     my %servers = &Apache::lonnet::internet_dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
     my %thismachine;      my %thismachine;
     map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();      map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
     my @posscached = ('domainconfig','domdefaults','usersessions',      my @posscached = ('domainconfig','domdefaults','ltitools');
                       'directorysrch','passwdconf','cats');  
     if (keys(%servers)) {      if (keys(%servers)) {
         foreach my $server (keys(%servers)) {          foreach my $server (keys(%servers)) {
             next if ($thismachine{$server});              next if ($thismachine{$server});

Removed from v.1.160.6.106  
changed lines
  Added in v.1.294


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