Diff for /loncom/interface/domainprefs.pm between versions 1.160.6.118.2.1 and 1.396

version 1.160.6.118.2.1, 2021/12/30 03:45:13 version 1.396, 2021/12/06 03:31:54
Line 27 Line 27
 #  #
 #  #
 ###############################################################  ###############################################################
 ##############################################################  ###############################################################
   
 =pod  =pod
   
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, placement, and lti).  
 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 );
 use Net::CIDR;  use Net::CIDR;
   
 my $registered_cleanup;  my $registered_cleanup;
Line 218  sub handler { Line 220  sub handler {
                 'serverstatuses','requestcourses','helpsettings',                  'serverstatuses','requestcourses','helpsettings',
                 'coursedefaults','usersessions','loadbalancing',                  'coursedefaults','usersessions','loadbalancing',
                 'requestauthor','selfenrollment','inststatus',                  'requestauthor','selfenrollment','inststatus',
                 'passwords','ltitools','wafproxy','ipaccess'],$dom);                  'ltitools','ssl','trust','lti','privacy','passwords',
                   'proctoring','wafproxy','ipaccess'],$dom);
       my %encconfig =
           &Apache::lonnet::get_dom('encconfig',['ltitools','lti','proctoring'],$dom,undef,1);
     if (ref($domconfig{'ltitools'}) eq 'HASH') {      if (ref($domconfig{'ltitools'}) eq 'HASH') {
         my %encconfig =  
             &Apache::lonnet::get_dom('encconfig',['ltitools'],$dom,undef,1);  
         if (ref($encconfig{'ltitools'}) eq 'HASH') {          if (ref($encconfig{'ltitools'}) eq 'HASH') {
             foreach my $id (keys(%{$domconfig{'ltitools'}})) {              foreach my $id (keys(%{$domconfig{'ltitools'}})) {
                 if (ref($domconfig{'ltitools'}{$id}) eq 'HASH') {                  if ((ref($domconfig{'ltitools'}{$id}) eq 'HASH') &&
                       (ref($encconfig{'ltitools'}{$id}) eq 'HASH')) {
                     foreach my $item ('key','secret') {                      foreach my $item ('key','secret') {
                         $domconfig{'ltitools'}{$id}{$item} = $encconfig{'ltitools'}{$id}{$item};                          $domconfig{'ltitools'}{$id}{$item} = $encconfig{'ltitools'}{$id}{$item};
                     }                      }
Line 232  sub handler { Line 236  sub handler {
             }              }
         }          }
     }      }
       if (ref($domconfig{'lti'}) eq 'HASH') {
           if (ref($encconfig{'lti'}) eq 'HASH') {
               foreach my $id (keys(%{$domconfig{'lti'}})) {
                   if ((ref($domconfig{'lti'}{$id}) eq 'HASH') &&
                       (ref($encconfig{'lti'}{$id}) eq 'HASH')) {
                       foreach my $item ('key','secret') {
                           $domconfig{'lti'}{$id}{$item} = $encconfig{'lti'}{$id}{$item};
                       }
                   }
               }
           }
       }
       if (ref($domconfig{'proctoring'}) eq 'HASH') {
           if (ref($encconfig{'proctoring'}) eq 'HASH') {
               foreach my $provider (keys(%{$domconfig{'proctoring'}})) {
                   if ((ref($domconfig{'proctoring'}{$provider}) eq 'HASH') &&
                       (ref($encconfig{'proctoring'}{$provider}) eq 'HASH')) {
                       foreach my $item ('key','secret') {
                           $domconfig{'proctoring'}{$provider}{$item} = $encconfig{'proctoring'}{$provider}{$item};
                       }
                   }
               }
           }
       }
     my @prefs_order = ('rolecolors','login','ipaccess','defaults','wafproxy','passwords',      my @prefs_order = ('rolecolors','login','ipaccess','defaults','wafproxy','passwords',
                        'quotas','autoenroll','autoupdate','autocreate','directorysrch',                         'quotas','autoenroll','autoupdate','autocreate','directorysrch',
                        'contacts','usercreation','selfcreation','usermodification',                         'contacts','privacy','usercreation','selfcreation',
                        'scantron','requestcourses','requestauthor','coursecategories',                         'usermodification','scantron','requestcourses','requestauthor',
                        'serverstatuses','helpsettings','coursedefaults',                         'coursecategories','serverstatuses','helpsettings','coursedefaults',
                        'ltitools','selfenrollment','usersessions');                         'ltitools','proctoring','selfenrollment','usersessions','ssl',
                          'trust','lti');
     my %existing;      my %existing;
     if (ref($domconfig{'loadbalancing'}) eq 'HASH') {      if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
         %existing = %{$domconfig{'loadbalancing'}};          %existing = %{$domconfig{'loadbalancing'}};
Line 496  sub handler { Line 525  sub handler {
                   print => \&print_selfenrollment,                    print => \&print_selfenrollment,
                   modify => \&modify_selfenrollment,                    modify => \&modify_selfenrollment,
                  },                   },
           'privacy' => 
                    {text   => 'Availability of User Information',
                     help   => 'Domain_Configuration_User_Privacy',
                     header => [{col1 => 'Role assigned in different domain',
                                 col2 => 'Approval options'},
                                {col1 => 'Role assigned in different domain to user of type',
                                 col2 => 'User information available in that domain'},
                                {col1 => "Role assigned in user's domain",
                                 col2 => 'Information viewable by privileged user'},
                                {col1 => "Role assigned in user's domain",
                                 col2 => 'Information viewable by unprivileged user'}],
                     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 519  sub handler { Line 562  sub handler {
                   print => \&print_loadbalancing,                    print => \&print_loadbalancing,
                   modify => \&modify_loadbalancing,                    modify => \&modify_loadbalancing,
                  },                   },
         'ltitools' =>          'ltitools' => 
                  {text => 'External Tools (LTI)',                   {text => 'External Tools (LTI)',
                   help => 'Domain_Configuration_LTI_Tools',                    help => 'Domain_Configuration_LTI_Tools',
                   header => [{col1 => 'Setting',                    header => [{col1 => 'Setting',
Line 527  sub handler { Line 570  sub handler {
                   print => \&print_ltitools,                    print => \&print_ltitools,
                   modify => \&modify_ltitools,                    modify => \&modify_ltitools,
                  },                   },
          'ipaccess' =>          'proctoring' =>
                    {text => 'Remote Proctoring Integration',
                     help => 'Domain_Configuration_Proctoring',
                     header => [{col1 => 'Name',
                                 col2 => 'Configuration'}],
                     print => \&print_proctoring,
                     modify => \&modify_proctoring,
                    },
           '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,
                    },
             'lti' =>
                    {text => 'LTI Provider',
                     help => 'Domain_Configuration_LTI_Provider',
                     header => [{col1 => 'Setting',
                                 col2 => 'Value',}],
                     print => \&print_lti,
                     modify => \&modify_lti,
                    },
              'ipaccess' =>
                        {text => 'IP-based access control',                         {text => 'IP-based access control',
                         help => 'Domain_Configuration_IP_Access',                          help => 'Domain_Configuration_IP_Access',
                         header => [{col1 => 'Setting',                          header => [{col1 => 'Setting',
Line 722  sub process_changes { Line 819  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') {  
         $output = &modify_passwords($r,$dom,$confname,$lastactref,%domconfig);  
     } elsif ($action eq 'ltitools') {      } elsif ($action eq 'ltitools') {
         $output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig);          $output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig);
       } elsif ($action eq 'proctoring') {
           $output = &modify_proctoring($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);
       } elsif ($action eq 'lti') {
           $output = &modify_lti($r,$dom,$action,$lastactref,%domconfig);
       } elsif ($action eq 'privacy') {
           $output = &modify_privacy($dom,%domconfig);
       } elsif ($action eq 'passwords') {
           $output = &modify_passwords($r,$dom,$confname,$lastactref,%domconfig);
     } elsif ($action eq 'wafproxy') {      } elsif ($action eq 'wafproxy') {
         $output = &modify_wafproxy($dom,$action,$lastactref,%domconfig);          $output = &modify_wafproxy($dom,$action,$lastactref,%domconfig);
     } elsif ($action eq 'ipaccess') {      } elsif ($action eq 'ipaccess') {
Line 758  sub print_config_box { Line 865  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);
     } elsif ($action eq 'ltitools') {      } elsif ($action eq 'ltitools') {
         $output .= &ltitools_javascript($settings);          $output .= &ltitools_javascript($settings);
       } elsif ($action eq 'lti') {
           $output .= &lti_javascript($settings);
       } elsif ($action eq 'proctoring') {
           $output .= &proctoring_javascript($settings);
     } elsif ($action eq 'wafproxy') {      } elsif ($action eq 'wafproxy') {
         $output .= &wafproxy_javascript($dom);          $output .= &wafproxy_javascript($dom);
     } elsif ($action eq 'autoupdate') {      } elsif ($action eq 'autoupdate') {
         $output .= &autoupdate_javascript();          $output .= &autoupdate_javascript();
     } elsif ($action eq 'autoenroll') {  
         $output .= &autoenroll_javascript();  
     } elsif ($action eq 'login') {      } elsif ($action eq 'login') {
         $output .= &saml_javascript();          $output .= &saml_javascript();
     } elsif ($action eq 'ipaccess') {      } elsif ($action eq 'ipaccess') {
Line 788  sub print_config_box { Line 897  sub print_config_box {
     if ($numheaders > 1) {      if ($numheaders > 1) {
         my $colspan = '';          my $colspan = '';
         my $rightcolspan = '';          my $rightcolspan = '';
         my $leftnobr = '';            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 < 5))) {              (($action eq 'login') && ($numheaders < 5))) {
Line 811  sub print_config_box { Line 920  sub print_config_box {
         $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 'wafproxy')) {              ($action eq 'directorysrch') || ($action eq 'trust') || ($action eq 'helpsettings') ||
               ($action eq 'contacts') || ($action eq 'privacy') || ($action eq 'wafproxy')) {
             $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);              $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'passwords') {          } elsif ($action eq 'passwords') {
             $output .= $item->{'print'}->('top',$dom,$confname,$settings,\$rowtotal);              $output .= $item->{'print'}->('top',$dom,$confname,$settings,\$rowtotal);
Line 846  sub print_config_box { Line 956  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 'privacy') || ($action eq 'passwords')) {
             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 'trust') {
                   $output .= $item->{'print'}->('shared',$dom,$settings,\$rowtotal);
             } elsif ($action eq 'passwords') {              } elsif ($action eq 'passwords') {
                 $output .= $item->{'print'}->('middle',$dom,$confname,$settings,\$rowtotal);                  $output .= $item->{'print'}->('middle',$dom,$confname,$settings,\$rowtotal);
             } else {              } else {
                 $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);                  $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);
             }              }
             $output .= '              if ($action eq 'trust') {
                   $output .= '
               </table>
             </td>
            </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>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[$trusthdrs[$i]]->{'col1'}).'</td>
                 <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[$trusthdrs[$i]]->{'col2'}).'</td></tr>'.
                              $item->{'print'}->($prefixes[$i],$dom,$settings,\$rowtotal).'
               </table>
             </td>
            </tr>';
                   }
                   $output .= '
            <tr>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[8]->{'col1'}).'</td>
                 <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[8]->{'col2'}).'</td></tr>'.
                              $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
               } else {
                   $output .= '
            </table>             </table>
           </td>            </td>
          </tr>           </tr>
Line 867  sub print_config_box { Line 1009  sub print_config_box {
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>                <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
              </tr>'."\n";               </tr>'."\n";
             if ($action eq 'coursecategories') {                  if ($action eq 'coursecategories') {
                 $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);                      $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
             } elsif (($action eq 'contacts') || ($action eq 'passwords')) {                  } elsif (($action eq 'contacts') || ($action eq 'privacy') || ($action eq 'passwords')) {
                 if ($action eq 'passwords') {                      if ($action eq 'passwords') {
                     $output .= $item->{'print'}->('lower',$dom,$confname,$settings,\$rowtotal);                          $output .= $item->{'print'}->('lower',$dom,$confname,$settings,\$rowtotal);
                 } else {                      } else {
                     $output .= $item->{'print'}->('lower',$dom,$settings,\$rowtotal);                          $output .= $item->{'print'}->('lower',$dom,$settings,\$rowtotal);
                 }                      }
                 $output .= '                      $output .= '
              </tr>               </tr>
             </table>              </table>
            </td>             </td>
Line 886  sub print_config_box { Line 1028  sub print_config_box {
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item'.$leftnobr.'"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>                <td class="LC_left_item'.$leftnobr.'"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'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'}->[3]->{'col2'}).'</td></tr>'."\n";
                 if ($action eq 'passwords') {                      if ($action eq 'passwords') {
                     $output .= $item->{'print'}->('bottom',$dom,$confname,$settings,\$rowtotal);                          $output .= $item->{'print'}->('bottom',$dom,$confname,$settings,\$rowtotal);
                 } else {                      } else {
                     $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);                          $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
                 }                      }
                 $output .= '                      $output .= '
             </table>              </table>
           </td>            </td>
          </tr>           </tr>
          <tr>';           <tr>';
             } else {                  } else {
                 $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);                      $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
                   }
             }              }
             $rowtotal ++;              $rowtotal ++;
         } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||          } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||
Line 906  sub print_config_box { Line 1049  sub print_config_box {
             $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);              $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'scantron') {          } elsif ($action eq 'scantron') {
             $output .= $item->{'print'}->($r,'bottom',$dom,$confname,$settings,\$rowtotal);              $output .= $item->{'print'}->($r,'bottom',$dom,$confname,$settings,\$rowtotal);
           } elsif ($action eq 'ssl') {
               $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 == 5) {              if ($numheaders == 5) {
                 $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'                  $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'
Line 996  sub print_config_box { Line 1161  sub print_config_box {
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.' valign="top">'.&mt($item->{'header'}->[4]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.' style="vertical-align: top">'.&mt($item->{'header'}->[4]->{'col1'}).'</td>
               <td class="LC_right_item" valign="top">'.&mt($item->{'header'}->[4]->{'col2'}).'</td>                <td class="LC_right_item" style="vertical-align: top">'.&mt($item->{'header'}->[4]->{'col2'}).'</td>
              </tr>'.               </tr>'.
             &print_validation_rows('requestcourses',$dom,$settings,\$rowtotal);              &print_validation_rows('requestcourses',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'requestauthor') {          } elsif ($action eq 'requestauthor') {
Line 1012  sub print_config_box { Line 1177  sub print_config_box {
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.' valign="top">'.                <td class="LC_left_item"'.$colspan.' style="vertical-align: top">'.
                &mt($item->{'header'}->[2]->{'col1'}).'</td>                 &mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item" valign="top">'.                <td class="LC_right_item" style="vertical-align: top">'.
                &mt($item->{'header'}->[2]->{'col2'}).'</td>                 &mt($item->{'header'}->[2]->{'col2'}).'</td>
              </tr>'.               </tr>'.
             &print_rolecolors($phase,'author',$dom,$confname,$settings,\$rowtotal).'              &print_rolecolors($phase,'author',$dom,$confname,$settings,\$rowtotal).'
Line 1042  sub print_config_box { Line 1207  sub print_config_box {
               <td class="LC_left_item" colspan="2">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';                <td class="LC_left_item" colspan="2">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
         } elsif ($action eq 'serverstatuses') {          } elsif ($action eq 'serverstatuses') {
             $output .= '              $output .= '
               <td class="LC_left_item" valign="top">'.&mt($item->{'header'}->[0]->{'col1'}).                <td class="LC_left_item" style="vertical-align: top">'.&mt($item->{'header'}->[0]->{'col1'}).
               '<br />('.&mt('Automatic access for Dom. Coords.').')</td>';                '<br />('.&mt('Automatic access for Dom. Coords.').')</td>';
   
         } else {          } else {
             $output .= '              $output .= '
               <td class="LC_left_item" valign="top">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';                <td class="LC_left_item" style="vertical-align: top">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
         }          }
         if (defined($item->{'header'}->[0]->{'col3'})) {          if (defined($item->{'header'}->[0]->{'col3'})) {
             $output .= '<td class="LC_left_item" valign="top">'.              $output .= '<td class="LC_left_item" style="vertical-align: top">'.
                        &mt($item->{'header'}->[0]->{'col2'});                         &mt($item->{'header'}->[0]->{'col2'});
             if ($action eq 'serverstatuses') {              if ($action eq 'serverstatuses') {
                 $output .= '<br />(<tt>'.&mt('user1:domain1,user2:domain2 etc.').'</tt>)';                  $output .= '<br />(<tt>'.&mt('user1:domain1,user2:domain2 etc.').'</tt>)';
             }               } 
         } else {          } else {
             $output .= '<td class="LC_right_item" valign="top">'.              $output .= '<td class="LC_right_item" style="vertical-align: top">'.
                        &mt($item->{'header'}->[0]->{'col2'});                         &mt($item->{'header'}->[0]->{'col2'});
         }          }
         $output .= '</td>';          $output .= '</td>';
         if ($item->{'header'}->[0]->{'col3'}) {          if ($item->{'header'}->[0]->{'col3'}) {
             if (defined($item->{'header'}->[0]->{'col4'})) {              if (defined($item->{'header'}->[0]->{'col4'})) {
                 $output .= '<td class="LC_left_item" valign="top">'.                  $output .= '<td class="LC_left_item" style="vertical-align: top">'.
                             &mt($item->{'header'}->[0]->{'col3'});                              &mt($item->{'header'}->[0]->{'col3'});
             } else {              } else {
                 $output .= '<td class="LC_right_item" valign="top">'.                  $output .= '<td class="LC_right_item" style="vertical-align: top">'.
                            &mt($item->{'header'}->[0]->{'col3'});                             &mt($item->{'header'}->[0]->{'col3'});
             }              }
             if ($action eq 'serverstatuses') {              if ($action eq 'serverstatuses') {
Line 1074  sub print_config_box { Line 1239  sub print_config_box {
             $output .= '</td>';              $output .= '</td>';
         }          }
         if ($item->{'header'}->[0]->{'col4'}) {          if ($item->{'header'}->[0]->{'col4'}) {
             $output .= '<td class="LC_right_item" valign="top">'.              $output .= '<td class="LC_right_item" style="vertical-align: top">'.
                        &mt($item->{'header'}->[0]->{'col4'});                         &mt($item->{'header'}->[0]->{'col4'});
         }          }
         $output .= '</tr>';          $output .= '</tr>';
Line 1082  sub print_config_box { Line 1247  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') || ($action eq 'ipaccess')) {                   ($action eq 'ltitools') || ($action eq 'lti') ||
                    ($action eq 'proctoring') || ($action eq 'ipaccess')) {
             $output .= $item->{'print'}->($dom,$settings,\$rowtotal);              $output .= $item->{'print'}->($dom,$settings,\$rowtotal);
         }          }
     }      }
Line 1103  sub print_login { Line 1269  sub print_login {
         %lt = &login_file_options();          %lt = &login_file_options();
         $switchserver = &check_switchserver($dom,$confname);          $switchserver = &check_switchserver($dom,$confname);
     }      }
   
     if ($caller eq 'service') {      if ($caller eq 'service') {
         my %servers = &Apache::lonnet::internet_dom_servers($dom);          my %servers = &Apache::lonnet::internet_dom_servers($dom);
         my $choice = $choices{'disallowlogin'};          my $choice = $choices{'disallowlogin'};
         $css_class = ' class="LC_odd_row"';          $css_class = ' class="LC_odd_row"';
         $datatable .= '<tr'.$css_class.'><td>'.$choice.'</td>'.          $datatable .= '<tr'.$css_class.'><td>'.$choice.'</td>'.
                       '<td align="right"><table><tr><th>'.$choices{'hostid'}.'</th>'.                        '<td style="text-align: right"><table><tr><th>'.$choices{'hostid'}.'</th>'.
                       '<th>'.$choices{'server'}.'</th>'.                        '<th>'.$choices{'server'}.'</th>'.
                       '<th>'.$choices{'serverpath'}.'</th>'.                        '<th>'.$choices{'serverpath'}.'</th>'.
                       '<th>'.$choices{'custompath'}.'</th>'.                        '<th>'.$choices{'custompath'}.'</th>'.
Line 1382  sub print_login { Line 1547  sub print_login {
         my $choice = $choices{'headtag'};          my $choice = $choices{'headtag'};
         $css_class = ' class="LC_odd_row"';          $css_class = ' class="LC_odd_row"';
         $datatable .= '<tr'.$css_class.'><td colspan="2">'.$choice.'</td>'.          $datatable .= '<tr'.$css_class.'><td colspan="2">'.$choice.'</td>'.
                       '<td align="left"><table><tr><th>'.$choices{'hostid'}.'</th>'.                        '<td style="text-align: left"><table><tr><th>'.$choices{'hostid'}.'</th>'.
                       '<th>'.$choices{'current'}.'</th>'.                        '<th>'.$choices{'current'}.'</th>'.
                       '<th>'.$choices{'action'}.'</th>'.                        '<th>'.$choices{'action'}.'</th>'.
                       '<th>'.$choices{'exempt'}.'</th></tr>'."\n";                        '<th>'.$choices{'exempt'}.'</th></tr>'."\n";
Line 1728  sub commblocktype_text { Line 1893  sub commblocktype_text {
         'printout' => 'Printouts',          'printout' => 'Printouts',
         'passwd' => 'Change Password',          'passwd' => 'Change Password',
         'grades' => 'Gradebook',          'grades' => 'Gradebook',
         'search' => 'Course search',  
         'wishlist' => 'Stored links',  
         'annotate' => 'Annotations',  
     );      );
     my $typeorder = ['com','chat','boards','port','groups','blogs','about','wishlist','printout','grades','search','annotate','passwd'];      my $typeorder = ['com','chat','boards','port','groups','blogs','about','printout','grades','passwd'];
     return ($typeorder,\%types);      return ($typeorder,\%types);
 }  }
   
Line 2007  sub display_color_options { Line 2169  sub display_color_options {
                   '<table border="0"><tr>';                    '<table border="0"><tr>';
   
     foreach my $item (@{$bgs}) {      foreach my $item (@{$bgs}) {
         $datatable .= '<td align="center">'.$choices->{$item};          $datatable .= '<td style="text-align: center">'.$choices->{$item};
  my $color = $designs->{'bgs'}{$item} ? $designs->{'bgs'}{$item} : $defaults->{'bgs'}{$item};   my $color = $designs->{'bgs'}{$item} ? $designs->{'bgs'}{$item} : $defaults->{'bgs'}{$item};
         if ($designs->{'bgs'}{$item}) {          if ($designs->{'bgs'}{$item}) {
             $datatable .= '&nbsp;';              $datatable .= '&nbsp;';
Line 2035  sub display_color_options { Line 2197  sub display_color_options {
                   '<table border="0"><tr>';                    '<table border="0"><tr>';
     foreach my $item (@{$links}) {      foreach my $item (@{$links}) {
  my $color = $designs->{'links'}{$item} ? $designs->{'links'}{$item} : $defaults->{'links'}{$item};   my $color = $designs->{'links'}{$item} ? $designs->{'links'}{$item} : $defaults->{'links'}{$item};
         $datatable .= '<td align="center">'.$choices->{$item}."\n";          $datatable .= '<td style="text-align: center">'.$choices->{$item}."\n";
         if ($designs->{'links'}{$item}) {          if ($designs->{'links'}{$item}) {
             $datatable.='&nbsp;';              $datatable.='&nbsp;';
         }          }
Line 2096  sub login_text_colors { Line 2258  sub login_text_colors {
     my ($img,$role,$logintext,$phase,$choices,$designs,$defaults) = @_;      my ($img,$role,$logintext,$phase,$choices,$designs,$defaults) = @_;
     my $color_menu = '<table border="0"><tr>';      my $color_menu = '<table border="0"><tr>';
     foreach my $item (@{$logintext}) {      foreach my $item (@{$logintext}) {
         $color_menu .= '<td align="center">'.$choices->{$item};          $color_menu .= '<td style="text-align: center">'.$choices->{$item};
         my $color = $designs->{'logintext'}{$item} ? $designs->{'logintext'}{$item} : $defaults->{'logintext'}{$item};          my $color = $designs->{'logintext'}{$item} ? $designs->{'logintext'}{$item} : $defaults->{'logintext'}{$item};
         $color_menu .= '<br /><input type="text" class="colorchooser" size="8" name="'.$role.'_'.$item.'" value="'.$color.          $color_menu .= '<br /><input type="text" class="colorchooser" size="8" name="'.$role.'_'.$item.'" value="'.$color.
                       '" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>';                        '" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>';
Line 2129  sub image_changes { Line 2291  sub image_changes {
                        $role.'_del_'.$img.'" value="1" />'.&mt('Delete?').                         $role.'_del_'.$img.'" value="1" />'.&mt('Delete?').
                        '</label>&nbsp;'.&mt('Replace:').'</span><br />';                         '</label>&nbsp;'.&mt('Replace:').'</span><br />';
         } else {          } else {
             $output .= '<td valign="middle">'.$logincolors.&mt('Upload:').'<br />';              $output .= '<td class="LC_middle">'.$logincolors.&mt('Upload:').'<br />';
         }          }
     }      }
     return $output;      return $output;
Line 2148  sub print_quotas { Line 2310  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','lti');
         @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 2612  sub print_studentcode { Line 2774  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','lti');
     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 2943  sub ltitools_toggle_js { Line 3105  sub ltitools_toggle_js {
 function toggleLTITools(form,setting,item) {  function toggleLTITools(form,setting,item) {
     var radioname = '';      var radioname = '';
     var divid = '';      var divid = '';
       if ((setting == 'passback') || (setting == 'roster')) {
           radioname = 'ltitools_'+setting+'_'+item;
           divid = 'ltitools_'+setting+'time_'+item;
           var num = form.elements[radioname].length;
           if (num) {
               var setvis = '';
               for (var i=0; i<num; i++) {
                   if (form.elements[radioname][i].checked) {
                       if (form.elements[radioname][i].value == '1') {
                           if (document.getElementById(divid)) {
                               document.getElementById(divid).style.display = 'inline-block';
                           }
                           setvis = 1;
                       }
                       break;
                   }
               }
           }
           if (!setvis) {
               if (document.getElementById(divid)) {
                   document.getElementById(divid).style.display = 'none';
               }
           }
       }
     if (setting == 'user') {      if (setting == 'user') {
         divid = 'ltitools_'+setting+'_div_'+item;          divid = 'ltitools_'+setting+'_div_'+item;
         var checkid = 'ltitools_'+setting+'_field_'+item;          var checkid = 'ltitools_'+setting+'_field_'+item;
Line 3079  function toggleWAF() { Line 3265  function toggleWAF() {
 ENDSCRIPT  ENDSCRIPT
 }  }
   
 sub autoupdate_javascript {  sub proctoring_javascript {
       my ($settings) = @_;
       my (%ordered,$total,%jstext);
       $total = 0;
       if (ref($settings) eq 'HASH') {
           foreach my $item (keys(%{$settings})) {
               if (ref($settings->{$item}) eq 'HASH') {
                   my $num = $settings->{$item}{'order'};
                   $ordered{$num} = $item;
               }
           }
           $total = scalar(keys(%{$settings}));
       } else {
           %ordered = (
                          0 => 'proctorio',
                          1 => 'examity',
                      );
           $total = 2; 
       }
       my @jsarray = ();
       foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
           push(@jsarray,$ordered{$item});
       }
       my $jstext = '    var proctors = Array('."'".join("','",@jsarray)."'".');'."\n";
     return <<"ENDSCRIPT";      return <<"ENDSCRIPT";
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
 function toggleLastActiveDays(form) {  function reorderProctoring(form,item) {
     var radioname = 'lastactive';      var changedVal;
     var divid = 'lastactive_div';  $jstext
     var num = form.elements[radioname].length;      var maxh = $total;
     if (num) {      var current = new Array;
       var changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
       for (var i=0; i<proctors.length; i++) {
           var elementName = 'proctoring_pos_'+proctors[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;
   }
   
   function toggleProctoring(form,item) {
       var fieldsets = document.getElementsByClassName('proctoring_'+item);
       if (fieldsets.length) {
           var radioname = 'proctoring_available_'+item;
           var num = form.elements[radioname].length;
           if (num) {
               var setvis = '';
               for (var i=0; i<num; i++) {
                   if (form.elements[radioname][i].checked) {
                       if (form.elements[radioname][i].value == '1') {
                          setvis = 1;
                          break;
                       }
                   }
               }
               for (var j=0; j<fieldsets.length; j++) {
                   if (setvis) {
                       fieldsets[j].style.display = 'block';
                   } else {
                       fieldsets[j].style.display = 'none';
                   }
               }
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   ENDSCRIPT
   }
   
   
   sub lti_javascript {
       my ($settings) = @_;
       my $togglejs = &lti_toggle_js();
       unless (ref($settings) eq 'HASH') {
           return $togglejs;
       }
       my (%ordered,$total,%jstext);
       $total = scalar(keys(%{$settings}));
       foreach my $item (keys(%{$settings})) {
           if (ref($settings->{$item}) eq 'HASH') {
               my $num = $settings->{$item}{'order'};
               if ($num eq '') {
                   $num = $total - 1;
               }
               $ordered{$num} = $item;
           }
       }
       my @jsarray = ();
       foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
           push(@jsarray,$ordered{$item});
       }
       my $jstext = '    var lti = Array('."'".join("','",@jsarray)."'".');'."\n";
       return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   function reorderLTI(form,item) {
       var changedVal;
   $jstext
       var newpos = 'lti_pos_add';
       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<lti.length; i++) {
           var elementName = 'lti_pos_'+lti[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>
   
   $togglejs
   
   ENDSCRIPT
   }
   
   sub lti_toggle_js {
       my %lcauthparmtext = &Apache::lonlocal::texthash (
                               localauth => 'Local auth argument',
                               krb       => 'Kerberos domain',
                            );
       my $crsincalert = &mt('"User\'s identity sent" needs to be set to "Yes" first,[_1] before setting "Course\'s identity sent" to "Yes"',"\n");
       &js_escape(\$crsincalert);
       return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   
   function toggleLTI(form,setting,item) {
       if ((setting == 'requser') || (setting == 'crsinc')) {
           var usrfieldsets = document.getElementsByClassName('ltioption_usr_'+item);
         var setvis = '';          var setvis = '';
         for (var i=0; i<num; i++) {          var radioname = 'lti_requser_'+item;
             if (form.elements[radioname][i].checked) {          var num = form.elements[radioname].length;
                 if (form.elements[radioname][i].value == '1') {          if (num) {
                     if (document.getElementById(divid)) {              for (var i=0; i<num; i++) {
                         document.getElementById(divid).style.display = 'inline-block';                  if (form.elements[radioname][i].checked) {
                       if (form.elements[radioname][i].value == '1') {
                           setvis = 1;
                           break;
                       }
                   }
               }
           }
           if (usrfieldsets.length) {
               for (var j=0; j<usrfieldsets.length; j++) {
                   if (setvis) {
                       usrfieldsets[j].style.display = 'block';
                   } else {
                       usrfieldsets[j].style.display = 'none';
                   }
               }
           }
           var crsfieldsets = document.getElementsByClassName('ltioption_crs_'+item);
           if (crsfieldsets.length) {
               radioname = 'lti_crsinc_'+item;
               var num = form.elements[radioname].length;
               if (num) {
                   var crsvis = '';
                   for (var i=0; i<num; i++) {
                       if (form.elements[radioname][i].checked) {
                           if (form.elements[radioname][i].value == '1') {
                               if (setvis == '') {
                                   if (setting == 'crsinc'){
                                       alert("$crsincalert");
                                       form.elements[radioname][0].checked = true;
                                   }
                               } else {
                                   crsvis = 1;
                               }
                               break;
                           }
                     }                      }
                     setvis = 1;  
                 }                  }
                   setvis = crsvis;
               }
               for (var j=0; j<crsfieldsets.length; j++) {
                   if (setvis) {
                       crsfieldsets[j].style.display = 'block';
                   } else {
                       crsfieldsets[j].style.display = 'none';
                   }
               }
           }
       } else if ((setting == 'user') || (setting == 'crs') || (setting == 'passback') || (setting == 'callback')) {
           var radioname = '';
           var divid = '';
           if (setting == 'user') {
               radioname = 'lti_mapuser_'+item;
               divid = 'lti_userfield_'+item;
           } else if (setting == 'crs') {
               radioname = 'lti_mapcrs_'+item;
               divid = 'lti_crsfield_'+item;
           } else if (setting == 'callback') {
               radioname = 'lti_callback_'+item;
               divid = 'lti_callbackfield_'+item;
           } else {
               radioname = 'lti_passback_'+item;
               divid =  'lti_passback_'+item;
           }
           var num = form.elements[radioname].length;
           if (num) {
               var setvis = '';
               for (var i=0; i<num; i++) {
                  if (form.elements[radioname][i].checked) {
                      if ((setting == 'passback') || (setting == 'callback')) {
                          if (form.elements[radioname][i].value == '1') {
                              if (document.getElementById(divid)) {
                                  document.getElementById(divid).style.display = 'inline-block';
                              }
                              setvis = 1;
                              break;
                          }
                      } else {
                          if (form.elements[radioname][i].value == 'other') {
                              if (document.getElementById(divid)) {
                                  document.getElementById(divid).style.display = 'inline-block';
                              }
                              setvis = 1;
                              break;
                          }
                      }
                  } 
               }
               if (!setvis) {
                   if (document.getElementById(divid)) {
                       document.getElementById(divid).style.display = 'none';
                   }
               }
           }
       } else if ((setting == 'sec') || (setting == 'secsrc')) {
           var numsec = form.elements['lti_crssec_'+item].length;
           if (numsec) {
               var setvis = '';
               for (var i=0; i<numsec; i++) {
                   if (form.elements['lti_crssec_'+item][i].checked) {
                       if (form.elements['lti_crssec_'+item][i].value == '1') {
                           if (document.getElementById('lti_crssecfield_'+item)) {
                               document.getElementById('lti_crssecfield_'+item).style.display = 'inline-block';
                               setvis = 1;
                               var numsrcsec = form.elements['lti_crssecsrc_'+item].length;
                               if (numsrcsec) {
                                   var setsrcvis = '';
                                   for (var j=0; j<numsrcsec; j++) {
                                       if (form.elements['lti_crssecsrc_'+item][j].checked) {
                                           if (form.elements['lti_crssecsrc_'+item][j].value == 'other') {
                                               if (document.getElementById('lti_secsrcfield_'+item)) {
                                                   document.getElementById('lti_secsrcfield_'+item).style.display = 'inline-block';
                                                   setsrcvis = 1;
                                               }
                                           }
                                       }
                                   }
                                   if (!setsrcvis) {
                                       if (document.getElementById('lti_secsrcfield_'+item)) {
                                           document.getElementById('lti_secsrcfield_'+item).style.display = 'none';
                                       }
                                   }
                               }
                           }
                       }
                   }
               }
               if (!setvis) {
                   if (document.getElementById('lti_crssecfield_'+item)) {
                       document.getElementById('lti_crssecfield_'+item).style.display = 'none';
                   }
                   if (document.getElementById('lti_secsrcfield_'+item)) {
                       document.getElementById('lti_secsrcfield_'+item).style.display = 'none';
                   }
               }
           }
       } else if (setting == 'lcauth') {
           var numauth = form.elements['lti_lcauth_'+item].length;
           if (numauth) {
               for (var i=0; i<numauth; i++) {
                   if (form.elements['lti_lcauth_'+item][i].checked) {
                       if (document.getElementById('lti_'+setting+'_parmrow_'+item)) {
                           if ((form.elements['lti_'+setting+'_'+item][i].value == 'internal') || (form.elements['lti_'+setting+'_'+item][i].value == 'lti')) {
                               document.getElementById('lti_'+setting+'_parmrow_'+item).style.display = 'none';
                           } else {
                               document.getElementById('lti_'+setting+'_parmrow_'+item).style.display = 'table-row';
                               if (document.getElementById('lti_'+setting+'_parmtext_'+item)) {
                                   if (form.elements['lti_'+setting+'_'+item][i].value == 'localauth') {
                                       document.getElementById('lti_'+setting+'_parmtext_'+item).innerHTML = "$lcauthparmtext{'localauth'}";
                                   } else {
                                       document.getElementById('lti_'+setting+'_parmtext_'+item).innerHTML = "$lcauthparmtext{'krb'}";
                                   }
                               }
                           }
                       }
                   }
               }
           }
       } else if (setting == 'lcmenu') {
           var menus = new Array('lti_topmenu_'+item,'lti_inlinemenu_'+item);
           var divid = 'lti_menufield_'+item;
           var setvis = '';
           for (var i=0; i<menus.length; i++) {
               var radioname = menus[i];  
               var num = form.elements[radioname].length;
               if (num) {
                   for (var j=0; j<num; j++) {
                       if (form.elements[radioname][j].checked) {
                           if (form.elements[radioname][j].value == '1') {
                               if (document.getElementById(divid)) {
                                   document.getElementById(divid).style.display = 'inline-block';
                               }
                               setvis = 1;
                               break;
                           }
                       }
                   }
               }
               if (setvis == 1) {
                 break;                  break;
             }              }
         }          }
Line 3114  function toggleLastActiveDays(form) { Line 3650  function toggleLastActiveDays(form) {
 ENDSCRIPT  ENDSCRIPT
 }  }
   
 sub autoenroll_javascript {  sub autoupdate_javascript {
     return <<"ENDSCRIPT";      return <<"ENDSCRIPT";
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
 function toggleFailsafe(form) {  function toggleLastActiveDays(form) {
     var radioname = 'autoenroll_failsafe';      var radioname = 'lastactive';
     var divid = 'autoenroll_failsafe_div';      var divid = 'lastactive_div';
     var num = form.elements[radioname].length;      var num = form.elements[radioname].length;
     if (num) {      if (num) {
         var setvis = '';          var setvis = '';
         for (var i=0; i<num; i++) {          for (var i=0; i<num; i++) {
             if (form.elements[radioname][i].checked) {              if (form.elements[radioname][i].checked) {
                 if ((form.elements[radioname][i].value == 'zero') || (form.elements[radioname][i].value == 'any')) {                  if (form.elements[radioname][i].value == '1') {
                     if (document.getElementById(divid)) {                      if (document.getElementById(divid)) {
                         document.getElementById(divid).style.display = 'inline-block';                          document.getElementById(divid).style.display = 'inline-block';
                     }                      }
Line 3153  sub saml_javascript { Line 3689  sub saml_javascript {
     return <<"ENDSCRIPT";      return <<"ENDSCRIPT";
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
 function toggleSamlOptions(form,hostid) {  function toggleSamlOptions(form,hostid) { 
     var radioname = 'saml_'+hostid;      var radioname = 'saml_'+hostid;
     var tablecellon = 'samloptionson_'+hostid;      var tablecellon = 'samloptionson_'+hostid;
     var tablecelloff = 'samloptionsoff_'+hostid;      var tablecelloff = 'samloptionsoff_'+hostid;
     var num = form.elements[radioname].length;      var num = form.elements[radioname].length;
     if (num) {      if (num) {
         var setvis = '';          var setvis = ''; 
         for (var i=0; i<num; i++) {          for (var i=0; i<num; i++) {
             if (form.elements[radioname][i].checked) {              if (form.elements[radioname][i].checked) {
                 if (form.elements[radioname][i].value == '1') {                  if (form.elements[radioname][i].value == '1') { 
                     if (document.getElementById(tablecellon)) {                      if (document.getElementById(tablecellon)) {
                         document.getElementById(tablecellon).style.display='';                          document.getElementById(tablecellon).style.display='';
                     }                      }
Line 3262  ENDSCRIPT Line 3798  ENDSCRIPT
 sub print_autoenroll {  sub print_autoenroll {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my $autorun = &Apache::lonnet::auto_run(undef,$dom),      my $autorun = &Apache::lonnet::auto_run(undef,$dom),
     my ($defdom,$runon,$runoff,$coownerson,$coownersoff,      my ($defdom,$runon,$runoff,$coownerson,$coownersoff,$failsafe);
         $failsafe,$autofailsafe,$failsafesty,%failsafechecked);  
     $failsafesty = 'none';  
     %failsafechecked = (  
         off => ' checked="checked"',  
     );  
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (exists($settings->{'run'})) {          if (exists($settings->{'run'})) {
             if ($settings->{'run'} eq '0') {              if ($settings->{'run'} eq '0') {
Line 3301  sub print_autoenroll { Line 3832  sub print_autoenroll {
         if (exists($settings->{'sender_domain'})) {          if (exists($settings->{'sender_domain'})) {
             $defdom = $settings->{'sender_domain'};              $defdom = $settings->{'sender_domain'};
         }          }
         if (exists($settings->{'failsafe'})) {          if (exists($settings->{'autofailsafe'})) {
             $failsafe = $settings->{'failsafe'};              $failsafe = $settings->{'autofailsafe'};
             if ($failsafe eq 'zero') {  
                 $failsafechecked{'zero'} = ' checked="checked"';  
                 $failsafechecked{'off'} = '';  
                 $failsafesty = 'inline-block';  
             } elsif ($failsafe eq 'any') {  
                 $failsafechecked{'any'} = ' checked="checked"';  
                 $failsafechecked{'off'} = '';  
             }  
             $autofailsafe = $settings->{'autofailsafe'};  
         } elsif (exists($settings->{'autofailsafe'})) {  
             $autofailsafe = $settings->{'autofailsafe'};  
             if ($autofailsafe ne '') {  
                 $failsafechecked{'zero'} = ' checked="checked"';  
                 $failsafe = 'zero';  
                 $failsafechecked{'off'} = '';  
             }  
         }          }
     } else {      } else {
         if ($autorun) {          if ($autorun) {
Line 3357  sub print_autoenroll { Line 3872  sub print_autoenroll {
                   $coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.                    $coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.
                   '</tr><tr>'.                    '</tr><tr>'.
                   '<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_left_item"><span class="LC_nobreak">'.                    '<td class="LC_right_item"><span class="LC_nobreak">'.
                   '<span class="LC_nobreak"><label><input type="radio" name="autoenroll_failsafe" value="off" onclick="toggleFailsafe(this.form)"'.$failsafechecked{'off'}.' />'.&mt('Not in use').'</label></span>&nbsp;&nbsp;&nbsp; '.                    '<input type="text" name="autoenroll_failsafe"'.
                   '<span class="LC_nobreak"><label><input type="radio" name="autoenroll_failsafe" value="zero" onclick="toggleFailsafe(this.form)"'.$failsafechecked{'zero'}.' />'.&mt('Retrieved section enrollment is zero').'</label></span><br />'.                    ' value="'.$failsafe.'" size="4" /></span></td></tr>';
                   '<span class="LC_nobreak"><label><input type="radio" name="autoenroll_failsafe" value="any" onclick="toggleFailsafe(this.form)"'.$failsafechecked{'any'}.' />'.&mt('Retrieved section enrollment is zero or greater').'</label></span>'.  
                   '<div class="LC_floatleft" style="display:'.$failsafesty.';" id="autoenroll_failsafe_div">'.  
                   '<span class="LC_nobreak">'.  
                   &mt('Threshold for number of students in section to drop: [_1]',  
                       '<input type="text" name="autoenroll_autofailsafe" value="'.$autofailsafe.'" size="4" />').  
                   '</span></div></td></tr>';  
     $$rowtotal += 4;      $$rowtotal += 4;
     return $datatable;      return $datatable;
 }  }
Line 3389  sub print_autoupdate { Line 3898  sub print_autoupdate {
                 $updateoff = ' ';                  $updateoff = ' ';
             }              }
         }          }
         $enable = '<tr class="LC_odd_row">'.           $enable = '<tr class="LC_odd_row">'.
                   '<td>'.&mt($choices{'run'}).'</td>'.                    '<td>'.$choices{'run'}.'</td>'.
                   '<td class="LC_left_item"><span class="LC_nobreak"><label>'.                    '<td class="LC_left_item"><span class="LC_nobreak"><label>'.
                   '<input type="radio" name="autoupdate_run"'.                    '<input type="radio" name="autoupdate_run"'.
                   $updateoff.'value="0" />'.&mt('No').'</label>&nbsp;'.                    $updateoff.' value="0" />'.&mt('No').'</label>&nbsp;'.
                   '<label><input type="radio" name="autoupdate_run"'.                    '<label><input type="radio" name="autoupdate_run"'.
                   $updateon.'value="1" />'.&mt('Yes').'</label></span></td>'.                    $updateon.'value="1" />'.&mt('Yes').'</label></span></td>'.
                   '</tr>';                    '</tr>';
Line 3930  sub print_contacts { Line 4439  sub print_contacts {
                 map {$excluded{$_} = 1; } @{$lonstatus{'excluded'}};                  map {$excluded{$_} = 1; } @{$lonstatus{'excluded'}};
             }              }
         }          }
         foreach my $item ('errorthreshold','errorsysmail') {          foreach my $item ('errorthreshold','errorsysmail') { 
             $css_class = $rownum%2?' class="LC_odd_row"':'';              $css_class = $rownum%2?' class="LC_odd_row"':'';
             $datatable .= '<tr'.$css_class.'>'.              $datatable .= '<tr'.$css_class.'>'.
                           '<td class="LC_left_item"><span class="LC_nobreak">'.                            '<td class="LC_left_item"><span class="LC_nobreak">'.
Line 4012  sub print_contacts { Line 4521  sub print_contacts {
                             $includeloc{'override_'.$key} = '';                              $includeloc{'override_'.$key} = '';
                             $includestr{'override_'.$key} = '';                              $includestr{'override_'.$key} = '';
                             if ($settings->{'overrides'}{$key}{'include'} ne '') {                              if ($settings->{'overrides'}{$key}{'include'} ne '') {
                                 ($includeloc{'override_'.$key},$includestr{'override_'.$key}) =                                  ($includeloc{'override_'.$key},$includestr{'override_'.$key}) = 
                                     split(/:/,$settings->{'overrides'}{$key}{'include'},2);                                      split(/:/,$settings->{'overrides'}{$key}{'include'},2);
                                 $includestr{'override_'.$key} = &unescape($includestr{'override_'.$key});                                  $includestr{'override_'.$key} = &unescape($includestr{'override_'.$key});
                             }                              }
Line 4024  sub print_contacts { Line 4533  sub print_contacts {
             my $optionsprefix = 'LC_options_helpdesk_';              my $optionsprefix = 'LC_options_helpdesk_';
   
             my $onclicktypes = "toggleHelpdeskRow(this.form,'overrides','$customclass','$optionsprefix');";              my $onclicktypes = "toggleHelpdeskRow(this.form,'overrides','$customclass','$optionsprefix');";
    
             $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,              $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,
                                          $numinrow,$othertitle,'overrides',                                           $numinrow,$othertitle,'overrides',
                                          \$rownum,$onclicktypes,$customclass);                                           \$rownum,$onclicktypes,$customclass);
Line 4091  sub overridden_helpdesk { Line 4600  sub overridden_helpdesk {
             }              }
             my $title;              my $title;
             if (ref($short_titles) eq 'HASH') {              if (ref($short_titles) eq 'HASH') {
                 $title = $short_titles->{$item};                  $title = $short_titles->{$item}; 
             }              }
             $output .= '<label>'.              $output .= '<label>'.
                        '<input type="checkbox" name="override_'.$type.'"'.$check.                         '<input type="checkbox" name="override_'.$type.'"'.$check.
Line 4170  function toggleHelpdeskRow(form,checkbox Line 4679  function toggleHelpdeskRow(form,checkbox
     return;      return;
 }  }
   
   
 // ]]>  // ]]>
 </script>  </script>
   
Line 4241  sub print_helpsettings { Line 4751  sub print_helpsettings {
             push(@jsarray,('notinc','notexc'));              push(@jsarray,('notinc','notexc'));
         }          }
         my $hiddenstr = join("','",@jsarray);          my $hiddenstr = join("','",@jsarray);
         $datatable .= &helpsettings_javascript(\@roles_by_num,$maxnum,$hiddenstr,$formname);  
         my $context = 'domprefs';          my $context = 'domprefs';
         my $crstype = 'Course';          my $crstype = 'Course';
         my $prefix = 'helproles_';          my $prefix = 'helproles_';
Line 4275  sub print_helpsettings { Line 4784  sub print_helpsettings {
             my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);              my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
             $css_class = $itemcount%2?' class="LC_odd_row"':'';              $css_class = $itemcount%2?' class="LC_odd_row"':'';
             my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$num."_pos'".');"';              my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$num."_pos'".');"';
             $datatable .= '<tr '.$css_class.'><td valign="top"><b>'.$role.'</b><br />'.              $datatable .= '<tr '.$css_class.'><td style="vertical-align: top"><b>'.$role.'</b><br />'.
                           '<select name="helproles_'.$num.'_pos"'.$chgstr.'>';                            '<select name="helproles_'.$num.'_pos"'.$chgstr.'>';
             for (my $k=0; $k<=$maxnum; $k++) {              for (my $k=0; $k<=$maxnum; $k++) {
                 my $vpos = $k+1;                  my $vpos = $k+1;
Line 4314  sub print_helpsettings { Line 4823  sub print_helpsettings {
         &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);
         my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$count."_pos'".');"';          my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$count."_pos'".');"';
         $datatable .= '<tr '.$css_class.'><td valign="top"><span class="LC_nobreak"><label>'.          $datatable .= '<tr '.$css_class.'><td style="vertical-align: top"><span class="LC_nobreak"><label>'.
                       '<input type="hidden" name="helproles_maxnum" value="'.$maxnum.'" />'."\n".                        '<input type="hidden" name="helproles_maxnum" value="'.$maxnum.'" />'."\n".
                       '<select name="helproles_'.$count.'_pos"'.$chgstr.'>';                        '<select name="helproles_'.$count.'_pos"'.$chgstr.'>';
         for (my $k=0; $k<$maxnum+1; $k++) {          for (my $k=0; $k<$maxnum+1; $k++) {
Line 4595  sub radiobutton_prefs { Line 5104  sub radiobutton_prefs {
     foreach my $item (@{$toggles}) {      foreach my $item (@{$toggles}) {
         $css_class = $itemcount%2?' class="LC_odd_row"':'';          $css_class = $itemcount%2?' class="LC_odd_row"':'';
         $datatable .=          $datatable .=
             '<tr'.$css_class.'><td valign="top">'.              '<tr'.$css_class.'><td style="vertical-align: top">'.
             '<span class="LC_nobreak">'.$choices->{$item}.              '<span class="LC_nobreak">'.$choices->{$item}.
             '</span></td>';              '</span></td>';
         if ($align eq 'left') {          if ($align eq 'left') {
Line 4612  sub radiobutton_prefs { Line 5121  sub radiobutton_prefs {
                 $checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').'</label>';                  $checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').'</label>';
         } else {          } else {
             $datatable .=              $datatable .=
             '<label><input type="radio" name="'.                  '<label><input type="radio" name="'.
             $item.'" '.$checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').                  $item.'" '.$checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').
             '</label>&nbsp;<label><input type="radio" name="'.$item.'" '.                  '</label>&nbsp;<label><input type="radio" name="'.$item.'" '.
             $checkedoff{$item}.' value="0"'.$onclick.' />'.&mt('No').'</label>';                  $checkedoff{$item}.' value="0"'.$onclick.' />'.&mt('No').'</label>';
         }          }
         $datatable .= '</span>'.$additional.'</td></tr>';          $datatable .= '</span>'.$additional.'</td></tr>';
         $itemcount ++;          $itemcount ++;
Line 4747  sub print_ltitools { Line 5256  sub print_ltitools {
                           '<input type="text" name="ltitools_linktext_'.$i.'" size="25" value="'.$currdisp{'linktext'}.'" /></div>'.                            '<input type="text" name="ltitools_linktext_'.$i.'" size="25" value="'.$currdisp{'linktext'}.'" /></div>'.
                           '<div class="LC_left_float">'.$lt{'explanation'}.'<br />'.                            '<div class="LC_left_float">'.$lt{'explanation'}.'<br />'.
                           '<textarea name="ltitools_explanation_'.$i.'" rows="5" cols="40">'.$currdisp{'explanation'}.                            '<textarea name="ltitools_explanation_'.$i.'" rows="5" cols="40">'.$currdisp{'explanation'}.
                           '</textarea></div><div style=""></div>'.                            '</textarea></div><div style=""></div><br />';
                           '<div style="padding:0;clear:both;margin:0;border:0"></div>';              my %units = (
                             'passback' => 'days',
                             'roster'   => 'seconds',
                           );
               foreach my $extra ('passback','roster') {
                   my $validsty = 'none';
                   my $currvalid;
                   my $checkedon = '';
                   my $checkedoff = ' checked="checked"';
                   if ($settings->{$item}->{$extra}) {
                       $checkedon = $checkedoff;
                       $checkedoff = '';
                       $validsty = 'inline-block';
                       if ($settings->{$item}->{$extra.'valid'} =~ /^\d+\.?\d*$/) {
                           $currvalid = $settings->{$item}->{$extra.'valid'};
                       }
                   }
                   my $onclick = ' onclick="toggleLTITools(this.form,'."'$extra','$i'".');"';
                   $datatable .= '<div class="LC_floatleft"><span class="LC_nobreak">'.$lt{$extra}.'&nbsp;'.
                                 '<label><input type="radio" name="ltitools_'.$extra.'_'.$i.'" value="0"'.$checkedoff.$onclick.' />'.
                                 &mt('No').'</label>'.('&nbsp;'x2).
                                 '<label><input type="radio" name="ltitools_'.$extra.'_'.$i.'" value="1"'.$checkedon.$onclick.' />'.
                                 &mt('Yes').'</label></span></div>'.
                                 '<div class="LC_floatleft" style="display:'.$validsty.';" id="ltitools_'.$extra.'time_'.$i.'">'.
                                 '<span class="LC_nobreak">'.
                                 &mt("at least [_1] $units{$extra} after launch",
                                     '<input type="text" name="ltitools_'.$extra.'valid_'.$i.'" value="'.$currvalid.'" />').
                                 '</span></div><div style="padding:0;clear:both;margin:0;border:0"></div>';
               }
             $datatable .= '<span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;';              $datatable .= '<span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;';
             if ($imgsrc) {              if ($imgsrc) {
                 $datatable .= $imgsrc.                  $datatable .= $imgsrc.
Line 4817  sub print_ltitools { Line 5354  sub print_ltitools {
                 if (!$rolemaps{$role}) {                  if (!$rolemaps{$role}) {
                     $selectnone = ' selected="selected"';                      $selectnone = ' selected="selected"';
                 }                  }
                 $datatable .= '<td align="center">'.                  $datatable .= '<td style="text-align: center">'. 
                               &Apache::lonnet::plaintext($role,'Course').'<br />'.                                &Apache::lonnet::plaintext($role,'Course').'<br />'.
                               '<select name="ltitools_roles_'.$role.'_'.$i.'">'.                                '<select name="ltitools_roles_'.$role.'_'.$i.'">'.
                               '<option value=""'.$selectnone.'>'.&mt('Select').'</option>';                                '<option value=""'.$selectnone.'>'.&mt('Select').'</option>';
Line 4848  sub print_ltitools { Line 5385  sub print_ltitools {
                 }                  }
                 $datatable .= '<label>'.                  $datatable .= '<label>'.
                        '<input type="checkbox" name="ltitools_courseconfig_'.$i.'" value="'.$item.'"'.$checked.' />'.                         '<input type="checkbox" name="ltitools_courseconfig_'.$i.'" value="'.$item.'"'.$checked.' />'.
                        $lt{'crs'.$item}.'</label>'.('&nbsp;' x2)."\n";                         $lt{'crs'.$item}.'</label>&nbsp; '."\n";
             }              }
             $datatable .= '</span></fieldset>'.              $datatable .= '</span></fieldset>'.
                           '<fieldset><legend>'.&mt('Custom items sent on launch').'</legend>'.                            '<fieldset><legend>'.&mt('Custom items sent on launch').'</legend>'.
Line 4929  sub print_ltitools { Line 5466  sub print_ltitools {
                   '<input type="text" name="ltitools_add_linktext" size="5" /></div>'.                    '<input type="text" name="ltitools_add_linktext" size="5" /></div>'.
                   '<div class="LC_left_float">'.$lt{'explanation'}.'<br />'.                    '<div class="LC_left_float">'.$lt{'explanation'}.'<br />'.
                   '<textarea name="ltitools_add_explanation" rows="5" cols="40"></textarea>'.                    '<textarea name="ltitools_add_explanation" rows="5" cols="40"></textarea>'.
                   '</div><div style=""></div>'.                    '</div><div style=""></div><br />';
                   '<div style="padding:0;clear:both;margin:0;border:0"></div>';      my %units = (
                     'passback' => 'days',
                     'roster'   => 'seconds',
                   );
       my %defaulttimes = (
                        'passback' => '7',
                        'roster'   => '300',
                      );
       foreach my $extra ('passback','roster') {
           my $onclick = ' onclick="toggleLTITools(this.form,'."'$extra','add'".');"';
           $datatable .= '<div class="LC_floatleft"><span class="LC_nobreak">'.$lt{$extra}.'&nbsp;'.
                         '<label><input type="radio" name="ltitools_'.$extra.'_add" value="0" checked="checked"'.$onclick.' />'.
                         &mt('No').'</label></span>'.('&nbsp;'x2).'<span class="LC_nobreak">'.
                         '<label><input type="radio" name="ltitools_'.$extra.'_add" value="1"'.$onclick.' />'.
                         &mt('Yes').'</label></span></div>'.
                         '<div class="LC_floatleft" style="display:none;" id="ltitools_'.$extra.'time_add">'.
                         '<span class="LC_nobreak">'.
                         &mt("at least [_1] $units{$extra} after launch",
                             '<input type="text" name="ltitools_'.$extra.'valid_add" value="'.$defaulttimes{$extra}.'" />').
                         '</span></div><div style="padding:0;clear:both;margin:0;border:0"></div>';
       }
     $datatable .= '<span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;'.      $datatable .= '<span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;'.
                   '('.&mt('if larger than 21x21 pixels, image will be scaled').')&nbsp;';                    '('.&mt('if larger than 21x21 pixels, image will be scaled').')&nbsp;';
     if ($switchserver) {      if ($switchserver) {
Line 4964  sub print_ltitools { Line 5521  sub print_ltitools {
     $datatable .= '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';      $datatable .= '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';
     foreach my $role (@courseroles) {      foreach my $role (@courseroles) {
         my ($checked,$checkednone);          my ($checked,$checkednone);
         $datatable .= '<td align="center">'.          $datatable .= '<td style="text-align: center">'.
                       &Apache::lonnet::plaintext($role,'Course').'<br />'.                        &Apache::lonnet::plaintext($role,'Course').'<br />'.
                       '<select name="ltitools_add_roles_'.$role.'">'.                        '<select name="ltitools_add_roles_'.$role.'">'.
                       '<option value="" selected="selected">'.&mt('Select').'</option>';                        '<option value="" selected="selected">'.&mt('Select').'</option>';
Line 5004  sub ltitools_names { Line 5561  sub ltitools_names {
                                           'key'            => 'Key',                                            'key'            => 'Key',
                                           'lifetime'       => 'Nonce lifetime (s)',                                            'lifetime'       => 'Nonce lifetime (s)',
                                           'secret'         => 'Secret',                                            'secret'         => 'Secret',
                                           'icon'           => 'Icon',                                            'icon'           => 'Icon',   
                                           'user'           => 'User',                                            'user'           => 'User',
                                           'fullname'       => 'Full Name',                                            'fullname'       => 'Full Name',
                                           'firstname'      => 'First Name',                                            'firstname'      => 'First Name',
Line 5018  sub ltitools_names { Line 5575  sub ltitools_names {
                                           'width'          => 'Width',                                            'width'          => 'Width',
                                           'linktext'       => 'Default Link Text',                                            'linktext'       => 'Default Link Text',
                                           'explanation'    => 'Default Explanation',                                            'explanation'    => 'Default Explanation',
                                             'passback'       => 'Tool can return grades:',
                                             'roster'         => 'Tool can retrieve roster:',
                                           'crstarget'      => 'Display target',                                            'crstarget'      => 'Display target',
                                           'crslabel'       => 'Course label',                                            'crslabel'       => 'Course label',
                                           'crstitle'       => 'Course title',                                            'crstitle'       => 'Course title', 
                                           'crslinktext'    => 'Link Text',                                            'crslinktext'    => 'Link Text',
                                           'crsexplanation' => 'Explanation',                                            'crsexplanation' => 'Explanation',
                                           'crsappend'      => 'Provider URL',                                            'crsappend'      => 'Provider URL',
                                         );                                          );
       return %lt;
   }
   
   sub print_proctoring {
       my ($dom,$settings,$rowtotal) = @_;
       my $itemcount = 1;
       my (%ordered,%providernames,%current,%currentdef);
       my $confname = $dom.'-domainconfig';
       my $switchserver = &check_switchserver($dom,$confname);
       if (ref($settings) eq 'HASH') {
           foreach my $item (keys(%{$settings})) {
               if (ref($settings->{$item}) eq 'HASH') {
                   my $num = $settings->{$item}{'order'};
                   $ordered{$num} = $item;
               }
           }
       } else {
           %ordered = (
                        1 => 'proctorio',
                        2 => 'examity',
                      );
       }
       %providernames = &proctoring_providernames();
       my $maxnum = scalar(keys(%ordered));
       my (%requserfields,%optuserfields,%defaults,%extended,%crsconf,@courseroles,@ltiroles);
       my ($requref,$opturef,$defref,$extref,$crsref,$rolesref,$ltiref) = &proctoring_data();
       if (ref($requref) eq 'HASH') {
           %requserfields = %{$requref};
       }
       if (ref($opturef) eq 'HASH') {
           %optuserfields = %{$opturef};
       }
       if (ref($defref) eq 'HASH') {
           %defaults = %{$defref};
       }
       if (ref($extref) eq 'HASH') {
           %extended = %{$extref};
       }
       if (ref($crsref) eq 'HASH') {
           %crsconf = %{$crsref};
       }
       if (ref($rolesref) eq 'ARRAY') {
           @courseroles = @{$rolesref};
       }
       if (ref($ltiref) eq 'ARRAY') {
           @ltiroles = @{$ltiref};
       }
       my $datatable;
       my $css_class;
       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 $provider = $ordered{$items[$i]};
               my $optionsty = 'none';
               my ($available,$version,$lifetime,$imgsrc,$userincdom,$showroles,
                   %checkedfields,%rolemaps,%inuse,%crsconfig,%current);
               if (ref($settings) eq 'HASH') {
                   if (ref($settings->{$provider}) eq 'HASH') {
                       %current = %{$settings->{$provider}};
                       if ($current{'available'}) {
                           $optionsty = 'block';
                           $available = 1;
                       }
                       if ($current{'lifetime'} =~ /^\d+$/) {
                           $lifetime = $current{'lifetime'};
                       }
                       if ($current{'version'} =~ /^\d+\.\d+$/) {
                           $version = $current{'version'};
                       }
                       if ($current{'image'} ne '') {
                           $imgsrc = '<img src="'.$current{'image'}.'" alt="'.&mt('Proctoring service icon').'" />';
                       }
                       if (ref($current{'fields'}) eq 'ARRAY') {
                           map { $checkedfields{$_} = 1; } @{$current{'fields'}};
                       }
                       $userincdom = $current{'incdom'};
                       if (ref($current{'roles'}) eq 'HASH') {
                           %rolemaps = %{$current{'roles'}};
                           $checkedfields{'roles'} = 1;
                       }
                       if (ref($current{'defaults'}) eq 'ARRAY') {
                           foreach my $val (@{$current{'defaults'}}) {
                               if (grep(/^\Q$val\E$/,@{$defaults{$provider}})) {
                                   $inuse{$val} = 1;
                               } else {
                                   foreach my $poss (keys(%{$extended{$provider}})) {
                                       if (ref($extended{$provider}{$poss}) eq 'ARRAY') {
                                           if (grep(/^\Q$val\E$/,@{$extended{$provider}{$poss}})) {
                                               $inuse{$poss} = $val;
                                               last;
                                           }
                                       }
                                   }
                               }
                           }
                       } elsif (ref($current{'defaults'}) eq 'HASH') {
                           foreach my $key (keys(%{$current{'defaults'}})) {
                               my $currval = $current{'defaults'}{$key}; 
                               if (grep(/^\Q$key\E$/,@{$defaults{$provider}})) {
                                   $inuse{$key} = 1;
                               } else {
                                   my $match;
                                   foreach my $poss (keys(%{$extended{$provider}})) {
                                       if (ref($extended{$provider}{$poss}) eq 'ARRAY') {
                                           if (grep(/^\Q$key\E$/,@{$extended{$provider}{$poss}})) {
                                               $inuse{$poss} = $key;
                                               last;
                                           }
                                       } elsif (ref($extended{$provider}{$poss}) eq 'HASH') {
                                           foreach my $inner (sort(keys(%{$extended{$provider}{$poss}}))) {
                                               if (ref($extended{$provider}{$poss}{$inner}) eq 'ARRAY') {
                                                   if (grep(/^\Q$currval\E$/,@{$extended{$provider}{$poss}{$inner}})) {
                                                       $currentdef{$inner} = $currval;
                                                       $match = 1;
                                                       last;
                                                   }
                                               } elsif ($inner eq $key) {
                                                   $currentdef{$key} = $currval;
                                                   $match = 1;
                                                   last;
                                               }
                                           }
                                       }
                                       last if ($match);
                                   }
                               }
                           }
                       }
                       if (ref($current{'crsconf'}) eq 'ARRAY') {
                           map { $crsconfig{$_} = 1; } @{$current{'crsconf'}};
                       }
                   }
               }
               my %lt = &proctoring_titles($provider);
               my %fieldtitles = &proctoring_fieldtitles($provider);
               my $onclickavailable = ' onclick="toggleProctoring(this.form,'."'$provider'".');"';
               my %checkedavailable = (
                                      yes => '',
                                      no  => ' checked="checked"',
                                    );
               if ($available) {
                   $checkedavailable{'yes'} = $checkedavailable{'no'};
                   $checkedavailable{'no'} = '';
               }
               my $chgstr = ' onchange="javascript:reorderProctoring(this.form,'."'proctoring_pos_".$provider."'".');"';
               $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
                            .'<select name="proctoring_pos_'.$provider.'"'.$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>';
               }
               if ($version eq '') {
                   if ($provider eq 'proctorio') {
                       $version = '1.0';
                   } elsif ($provider eq 'examity') {
                       $version = '1.1';
                   }
               }
               if ($lifetime eq '') {
                   $lifetime = '300';
               }
               $datatable .=
                   '</select>'.('&nbsp;'x2).'<b>'.$providernames{$provider}.'</b></span><br />'.
                   '<span class="LC_nobreak">'.$lt{'avai'}.'&nbsp;'.
                   '<label><input type="radio" name="proctoring_available_'.$provider.'" value="1"'.$onclickavailable.$checkedavailable{yes}.' />'.&mt('Yes').'</label>&nbsp;'."\n".
                   '<label><input type="radio" name="proctoring_available_'.$provider.'" value="0"'.$onclickavailable.$checkedavailable{no}.' />'.&mt('No').'</label></span>'."\n".
                   '</td>'.
                   '<td colspan="2">'.
                   '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'"><legend>'.$lt{'base'}.'</legend>'.
                   '<span class="LC_nobreak">'.$lt{'version'}.':<select name="proctoring_'.$provider.'_version">'.
                   '<option value="'.$version.'" selected="selected">'.$version.'</option></select></span> '."\n".
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'sigmethod'}.':<select name="proctoring_'.$provider.'_sigmethod">'.
                   '<option value="HMAC-SHA1" selected="selected">HMAC-SHA1</option>'.
                   '<option value="HMAC-SHA256">HMAC-SHA256</option></select></span>'.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'lifetime'}.':<input type="text" size="5" name="proctoring_'.$provider.'_lifetime" value="'.$lifetime.'" /></span> '."\n".
                   '<br />'.
                   '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="40" name="proctoring_'.$provider.'_url" value="'.$current{'url'}.'" /></span> '."\n".
                   '<br />'.
                   '<span class="LC_nobreak">'.$lt{'key'}.':<input type="text" size="25" name="proctoring_'.$provider.'_key" value="'.$current{'key'}.'" /></span> '."\n".
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'secret'}.':<input type="password" size="20" name="proctoring_'.$provider.'_secret" value="'.$current{'secret'}.'" />'.
                   '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.proctoring_'.$provider.'_secret.type='."'text'".' } else { this.form.proctoring_'.$provider.'_secret.type='."'password'".' }" />'.$lt{'visible'}.'</label></span><br />'."\n";
               $datatable .= '<span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;';
               if ($imgsrc) {
                   $datatable .= $imgsrc.
                                 '<label><input type="checkbox" name="proctoring_image_del"'.
                                 ' value="'.$provider.'" />'.&mt('Delete?').'</label></span> '.
                                 '<span class="LC_nobreak">&nbsp;'.&mt('Replace:');
               }
               $datatable .= '&nbsp;';
               if ($switchserver) {
                   $datatable .= &mt('Upload to library server: [_1]',$switchserver);
               } else {
                   $datatable .= '<input type="file" name="proctoring_image_'.$provider.'" value="" />';
               }
               unless ($imgsrc) {
                   $datatable .= '<br />('.&mt('if larger than 21x21 pixels, image will be scaled').')';
               }
               $datatable .= '</fieldset>'."\n";
               if (ref($requserfields{$provider}) eq 'ARRAY') {
                   if (@{$requserfields{$provider}} > 0) {
                       $datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'"><legend>'.$lt{'requ'}.'</legend>';
                       foreach my $field (@{$requserfields{$provider}}) {
                           $datatable .= '<span class="LC_nobreak">'.
                                         '<label><input type="checkbox" name="proctoring_reqd_'.$provider.'" value="'.$field.'" checked="checked" disabled="disabled" />'.
                                         $lt{$field}.'</label>';
                           if ($field eq 'user') {
                               my $seluserdom = '';
                               my $unseluserdom = ' selected="selected"';
                               if ($userincdom) {
                                   $seluserdom = $unseluserdom;
                                   $unseluserdom = '';
                               }
                               $datatable .= ':&nbsp;'.
                                   '<select name="proctoring_userincdom_'.$provider.'">'.
                                   '<option value="0"'.$unseluserdom.'>'.$lt{'username'}.'</option>'.
                                   '<option value="1"'.$seluserdom.'>'.$lt{'uname:dom'}.'</option>'.
                                   '</select>&nbsp;';
                           } else {
                               $datatable .= '&nbsp;';
                               if ($field eq 'roles') {
                                   $showroles = 1; 
                               } 
                           }
                           $datatable .= '</span> ';
                       }
                   }
                   $datatable .= '</fieldset>'."\n";
               }
               if (ref($optuserfields{$provider}) eq 'ARRAY') {
                   if (@{$optuserfields{$provider}} > 0) {
                       $datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'"><legend>'.$lt{'optu'}.'</legend>'; 
                       foreach my $field (@{$optuserfields{$provider}}) {
                           my $checked;
                           if ($checkedfields{$field}) {
                               $checked = ' checked="checked"';
                           }
                           $datatable .= '<span class="LC_nobreak">'.
                                         '<label><input type="checkbox" name="proctoring_optional_'.$provider.'" value="'.$field.'"'.$checked.' />'.$lt{$field}.'</label></span>&nbsp; ';
                       }
                       $datatable .= '</fieldset>'."\n";
                   }
               }
               if (ref($defaults{$provider}) eq 'ARRAY') {
                   if (@{$defaults{$provider}}) {
                       my (%options,@selectboxes);
                       if (ref($extended{$provider}) eq 'HASH') {
                           %options = %{$extended{$provider}};
                       }
                       $datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'"><legend>'.$lt{'defa'}.'</legend>';
                       my ($rem,$numinrow,$dropdowns);
                       if ($provider eq 'proctorio') { 
                           $datatable .= '<table>';
                           $numinrow = 4;
                       }
                       my $i = 0;
                       foreach my $field (@{$defaults{$provider}}) {
                           my $checked;
                           if ($inuse{$field}) {
                               $checked = ' checked="checked"';
                           }
                           if ($provider eq 'examity') {
                               if ($field eq 'display') {
                                   $datatable .= '<span class="LC_nobreak">'.&mt('Display target:');
                                   foreach my $option ('iframe','tab','window') {
                                       my $checkdisp;
                                       if ($currentdef{'target'} eq $option) {
                                           $checkdisp = ' checked="checked"';
                                       }
                                       $datatable .= '<label><input type="radio" name="proctoring_target_'.$provider.'" value="'.$option.'"'.$checkdisp.' />'.
                                       $fieldtitles{$option}.'</label>'.('&nbsp;'x2);
                                   }
                                   $datatable .= ('&nbsp;'x4);
                                   foreach my $dimen ('width','height') {
                                       $datatable .= '<label>'.$fieldtitles{$dimen}.'&nbsp;'.
                                                     '<input type="text" name="proctoring_'.$dimen.'_'.$provider.'" size="5" '.
                                                     'value="'.$currentdef{$dimen}.'" /></label>'.
                                                     ('&nbsp;'x2);
                                   }
                                   $datatable .= '</span><br />'.
                                                 '<div class="LC_left_float">'.$fieldtitles{'linktext'}.'<br />'.
                                                 '<input type="text" name="proctoring_linktext_'.$provider.'" '.
                                                 'size="25" value="'.$currentdef{'linktext'}.'" /></div>'.
                                                 '<div class="LC_left_float">'.$fieldtitles{'explanation'}.'<br />'.
                                                 '<textarea name="proctoring_explanation_'.$provider.'" rows="5" cols="40">'.
                                                 $currentdef{'explanation'}.
                                                 '</textarea></div><div style=""></div><br />';
                               }
                           } else {
                               if ((exists($options{$field})) && (ref($options{$field}) eq 'ARRAY')) {
                                   my ($output,$selnone);
                                   unless ($checked) {
                                       $selnone = ' selected="selected"';
                                   }
                                   $output .= '<span class="LC_nobreak">'.$fieldtitles{$field}.': '.
                                              '<select name="proctoring_defaults_'.$field.'_'.$provider.'">'.
                                              '<option value=""'.$selnone.'>'.&mt('Not in use').'</option>'; 
                                   foreach my $option (@{$options{$field}}) {
                                       my $sel; 
                                       if ($inuse{$field} eq $option) {
                                           $sel = ' selected="selected"';
                                       }
                                       $output .= '<option value="'.$option.'"'.$sel.'>'.$fieldtitles{$option}.'</option>';
                                   }
                                   $output .= '</select></span>';
                                   push(@selectboxes,$output);
                               } else {
                                   $rem = $i%($numinrow);
                                   if ($rem == 0) {
                                       if ($i > 0) {
                                           $datatable .= '</tr>';
                                       }
                                       $datatable .= '<tr>';
                                   }
                                   $datatable .= '<td class="LC_left_item">'.
                                                 '<span class="LC_nobreak">'.
                                                 '<label><input type="checkbox" name="proctoring_defaults_'.$provider.'" value="'.$field.'"'.$checked.' />'.
                                                 $fieldtitles{$field}.'</label></span></td>';
                                   $i++;
                               }
                           }
                       }
                       if ($provider eq 'proctorio') {
                           if ($numinrow) {
                               $rem = $i%$numinrow;
                           }
                           my $colsleft = $numinrow - $rem;
                           if ($colsleft > 1) {
                               $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
                           } else {
                               $datatable .= '<td class="LC_left_item">';
                           }
                           $datatable .= '&nbsp;'.
                                         '</td></tr></table>';
                           if (@selectboxes) {
                               $datatable .= '<hr /><table>';
                               $numinrow = 2;
                               for (my $i=0; $i<@selectboxes; $i++) {
                                   $rem = $i%($numinrow);
                                   if ($rem == 0) {
                                       if ($i > 0) {
                                           $datatable .= '</tr>';
                                       }
                                       $datatable .= '<tr>';
                                   }
                                   $datatable .= '<td class="LC_left_item">'.
                                                 $selectboxes[$i].'</td>';
                               }
                               if ($numinrow) {
                                   $rem = $i%$numinrow;
                               }
                               $colsleft = $numinrow - $rem;
                               if ($colsleft > 1) {
                                   $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
                               } else {
                                   $datatable .= '<td class="LC_left_item">';
                               }
                               $datatable .= '&nbsp;'.
                                             '</td></tr></table>';
                           }
                       }
                       $datatable .= '</fieldset>';
                   }
                   if (ref($crsconf{$provider}) eq 'ARRAY') {
                       $datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'">'.
                                     '<legend>'.&mt('Configurable in course').'</legend>';
                       my ($rem,$numinrow);
                       if ($provider eq 'proctorio') {
                           $datatable .= '<table>';
                           $numinrow = 4;
                       }
                       my $i = 0;
                       foreach my $item (@{$crsconf{$provider}}) {
                           my $name;
                           if ($provider eq 'examity') {
                               $name = $lt{'crs'.$item};
                           } elsif ($provider eq 'proctorio') {
                               $name = $fieldtitles{$item};
                               $rem = $i%($numinrow);
                               if ($rem == 0) {
                                   if ($i > 0) {
                                       $datatable .= '</tr>';
                                   }
                                   $datatable .= '<tr>';
                               }
                               $datatable .= '<td class="LC_left_item>';
                           }
                           my $checked;
                           if ($crsconfig{$item}) {
                               $checked = ' checked="checked"';
                           }
                           $datatable .= '<span class="LC_nobreak"><label>'.
                                         '<input type="checkbox" name="proctoring_crsconf_'.$provider.'" value="'.$item.'"'.$checked.' />'.
                                         $name.'</label></span>';
                           if ($provider eq 'examity') {
                               $datatable .= '&nbsp; ';
                           }
                           $datatable .= "\n";
                           $i++;
                       }
                       if ($provider eq 'proctorio') {
                           if ($numinrow) {
                               $rem = $i%$numinrow;
                           }
                           my $colsleft = $numinrow - $rem;
                           if ($colsleft > 1) {
                               $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
                           } else {
                               $datatable .= '<td class="LC_left_item">';
                           }
                           $datatable .= '&nbsp;'.
                                         '</td></tr></table>';
                       }
                       $datatable .= '</fieldset>';
                   }
                   if ($showroles) {
                       $datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'">'.
                                     '<legend>'.&mt('Role mapping').'</legend><table><tr>';
                       foreach my $role (@courseroles) {
                           my ($selected,$selectnone);
                           if (!$rolemaps{$role}) {
                               $selectnone = ' selected="selected"';
                           }
                           $datatable .= '<td style="text-align: center">'.
                                         &Apache::lonnet::plaintext($role,'Course').'<br />'.
                                         '<select name="proctoring_roles_'.$role.'_'.$provider.'">'.
                                         '<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>'.
                                     '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'">'.
                                     '<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></td><td>lms</td>'.
                                     '<td><input type="text" name="proctoring_customval_lms_'.$provider.'"'.
                                     ' value="Loncapa" disabled="disabled"/></td></tr>';
                       if ((ref($settings) eq 'HASH') && (ref($settings->{$provider}) eq 'HASH') &&
                           (ref($settings->{$provider}->{'custom'}) eq 'HASH')) {
                           my %custom = %{$settings->{$provider}->{'custom'}};
                           if (keys(%custom) > 0) {
                               foreach my $key (sort(keys(%custom))) {
                                   next if ($key eq 'lms');
                                   $datatable .= '<tr><td><span class="LC_nobreak">'.
                                                 '<label><input type="checkbox" name="proctoring_customdel_'.$provider.'" value="'.
                                                 $key.'" />'.&mt('Delete').'</label></span></td><td>'.$key.'</td>'.
                                                 '<td><input type="text" name="proctoring_customval_'.$key.'_'.$provider.'"'.
                                                 ' value="'.$custom{$key}.'" /></td></tr>';
                               }
                           }
                       }
                       $datatable .= '<tr><td><span class="LC_nobreak">'.
                                     '<label><input type="checkbox" name="proctoring_customadd" value="'.$provider.'" />'.
                                     &mt('Add more').'</label></span></td><td><input type="text" name="proctoring_custom_name_'.$provider.'" />'.
                                     '</td><td><input type="text" name="proctoring_custom_value_'.$provider.'" /></td></tr>'.
                                     '</table></fieldset></td></tr>'."\n";
                   }
                   $datatable .= '</td></tr>';
               }
               $itemcount ++;
           }
       }
       return $datatable;
   }
   
   sub proctoring_data {
       my $requserfields = {
                         proctorio => ['user'],
                         examity   => ['roles','user'],
                        };
       my $optuserfields = {
                           proctorio => ['fullname'],
                           examity   => ['fullname','firstname','lastname','email'],
                        };
       my $defaults = {
                     proctorio => ['recordvideo','recordaudio','recordscreen','recordwebtraffic',
                                   'recordroomstart','verifyvideo','verifyaudio','verifydesktop',
                                   'verifyid','verifysignature','fullscreen','clipboard','tabslinks',
                                   'closetabs','onescreen','print','downloads','cache','rightclick',
                                   'reentry','calculator','whiteboard'],
                     examity   => ['display'],
                   };
       my $extended = { 
                     proctorio => {
                                    verifyid => ['verifyidauto','verifyidlive'],
                                    fullscreen => ['fullscreenlenient','fullscreenmoderate','fullscreensever'],
                                    tabslinks => ['notabs','linksonly'],
                                    reentry => ['noreentry','agentreentry'],
                                    calculator => ['calculatorbasic','calculatorsci'],
                                  },
                     examity => {
                                  display => {
                                              target      => ['iframe','tab','window'],
                                              width       => '',
                                              height      => '',
                                              linktext    => '',
                                              explanation => '',
                                             },
                                },
                   };
       my $crsconf = {
                    proctorio => ['recordvideo','recordaudio','recordscreen','recordwebtraffic',
                                  'recordroomstart','verifyvideo','verifyaudio','verifydesktop',
                                  'verifyid','verifysignature','fullscreen','clipboard','tabslinks',
                                  'closetabs','onescreen','print','downloads','cache','rightclick',
                                  'reentry','calculator','whiteboard'],
                    examity => ['label','title','target','linktext','explanation','append'],
                  };
       my $courseroles = ['cc','in','ta','ep','st'];
       my $ltiroles = ['Instructor','ContentDeveloper','TeachingAssistant','Learner'];
       return ($requserfields,$optuserfields,$defaults,$extended,$crsconf,$courseroles,$ltiroles);
   }
   
   sub proctoring_titles {
       my ($item) = @_;
       my (%common_lt,%custom_lt);
       %common_lt = &Apache::lonlocal::texthash (
                        'avai'      => 'Available?',
                        'base'      => 'Basic Settings',
                        'requ'      => 'User data required to be sent on launch',
                        'optu'      => 'User data optionally sent on launch',
                        'udsl'      => 'User data sent on launch',
                        'defa'      => 'Defaults for items configurable in course',
                        'sigmethod' => 'Signature Method',
                        'key'       => 'Key',
                        'lifetime'  => 'Nonce lifetime (s)',
                        'secret'    => 'Secret',
                        'icon'      => 'Icon',
                        'fullname'  => 'Full Name',
                        'visible'   => 'Visible input',
                        'username'  => 'username',
                        'user'      => 'User',
                    );
       if ($item eq 'proctorio') {
           %custom_lt = &Apache::lonlocal::texthash (
                            'version'        => 'OAuth version',
                            'url'            => 'API URL',
                            'uname:dom'      => 'username-domain',
           );
       } elsif ($item eq 'examity') {
           %custom_lt = &Apache::lonlocal::texthash (
                            'version'        => 'LTI Version',
                            'url'            => 'URL',
                            'uname:dom'      => 'username:domain',
                            'msgtype'        => 'Message Type',
                            'firstname'      => 'First Name',
                            'lastname'       => 'Last Name',
                            'email'          => 'E-mail',
                            'roles'          => 'Role',
                            'crstarget'      => 'Display target',
                            'crslabel'       => 'Course label',
                            'crstitle'       => 'Course title', 
                            'crslinktext'    => 'Link Text',
                            'crsexplanation' => 'Explanation',
                            'crsappend'      => 'Provider URL',
           );
       }
       my %lt = (%common_lt,%custom_lt);
       return %lt;
   }
   
   sub proctoring_fieldtitles {
       my ($item) = @_;
       if ($item eq 'proctorio') {
           return &Apache::lonlocal::texthash (
                     'recordvideo' => 'Record video',
                     'recordaudio' => 'Record audio',
                     'recordscreen' => 'Record screen',
                     'recordwebtraffic' => 'Record web traffic',
                     'recordroomstart' => 'Record room scan',
                     'verifyvideo' => 'Verify webcam',
                     'verifyaudio' => 'Verify microphone',
                     'verifydesktop' => 'Verify desktop recording',
                     'verifyid' => 'Photo ID verification',
                     'verifysignature' => 'Require signature',
                     'fullscreen' => 'Fullscreen',
                     'clipboard' => 'Disable copy/paste',
                     'tabslinks' => 'New tabs/windows',
                     'closetabs' => 'Close other tabs',
                     'onescreen' => 'Limit to single screen',
                     'print' => 'Disable Printing',
                     'downloads' => 'Disable Downloads',
                     'cache' => 'Empty cache after exam',
                     'rightclick' => 'Disable right click',
                     'reentry' => 'Re-entry to exam',
                     'calculator' => 'Onscreen calculator',
                     'whiteboard' => 'Onscreen whiteboard',
                     'verifyidauto' => 'Automated verification',
                     'verifyidlive' => 'Live agent verification',
                     'fullscreenlenient' => 'Forced, but can navigate away for up to 30s',
                     'fullscreenmoderate' => 'Forced, but can navigate away for up to 15s',
                     'fullscreensever' => 'Forced, navigation away ends exam',
                     'notabs' => 'Disaallowed',
                     'linksonly' => 'Allowed from links in exam',
                     'noreentry' => 'Disallowed',
                     'agentreentry' => 'Agent required for re-entry',
                     'calculatorbasic' => 'Basic',
                     'calculatorsci' => 'Scientific',
           );
       } elsif ($item eq 'examity') {
           return &Apache::lonlocal::texthash (
                   'target'         => 'Display target',   
                   'window'         => 'Window',
                   'tab'            => 'Tab',
                   'iframe'         => 'iFrame',
                   'height'         => 'Height (pixels)',
                   'width'          => 'Width (pixels)',
                   'linktext'       => 'Default Link Text',
                   'explanation'    => 'Default Explanation',
                   'append'         => 'Provider URL',
           );
       }
   }
   
   sub proctoring_providernames {
       return (
                proctorio => 'Proctorio',
                examity   => 'Examity',
              );
   }
   
   sub print_lti {
       my ($dom,$settings,$rowtotal) = @_;
       my $itemcount = 1;
       my $maxnum = 0;
       my $css_class;
       my %ordered;
       if (ref($settings) eq 'HASH') {
           foreach my $item (keys(%{$settings})) {
               if (ref($settings->{$item}) eq 'HASH') {
                   my $num = $settings->{$item}{'order'};
                   if ($num eq '') {
                       $num = scalar(keys(%{$settings}));
                   }
                   $ordered{$num} = $item;
               }
           }
       }
       my $maxnum = scalar(keys(%ordered));
       my $datatable;
       my %lt = &lti_names();
       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 ($key,$secret,$lifetime,$consumer,$requser,$crsinc,$current);
               if (ref($settings->{$item}) eq 'HASH') {
                   $key = $settings->{$item}->{'key'};
                   $secret = $settings->{$item}->{'secret'};
                   $lifetime = $settings->{$item}->{'lifetime'};
                   $consumer = $settings->{$item}->{'consumer'};
                   $requser = $settings->{$item}->{'requser'};
                   $crsinc = $settings->{$item}->{'crsinc'};
                   $current = $settings->{$item};
               }
               my $onclickrequser = ' onclick="toggleLTI(this.form,'."'requser','$i'".');"';
               my %checkedrequser = (
                                      yes => ' checked="checked"',
                                      no  => '',
                                    );
               if (!$requser) {
                   $checkedrequser{'no'} = $checkedrequser{'yes'};
                   $checkedrequser{'yes'} = '';
               }
               my $onclickcrsinc = ' onclick="toggleLTI(this.form,'."'crsinc','$i'".');"';
               my %checkedcrsinc = (
                                         yes => ' checked="checked"',
                                         no  => '',
                                      );
               if (!$crsinc) {
                   $checkedcrsinc{'no'} = $checkedcrsinc{'yes'};
                   $checkedcrsinc{'yes'} = '';
               }
               my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'lti_pos_".$item."'".');"';
               $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
                            .'<select name="lti_pos_'.$item.'"'.$chgstr.'>';
               for (my $k=0; $k<=$maxnum; $k++) {
                   my $vpos = $k+1;
                   my $selstr;
                   if ($k == $i) {
                       $selstr = ' selected="selected" ';
                   }
                   $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
               }
               $datatable .= '</select>'.('&nbsp;'x2).
                   '<label><input type="checkbox" name="lti_del" value="'.$item.'" />'.
                   &mt('Delete?').'</label></span></td>'.
                   '<td colspan="2">'.
                   '<fieldset><legend>'.&mt('Required settings').'</legend>'.
                   '<span class="LC_nobreak">'.$lt{'consumer'}.
                   ':<input type="text" size="15" name="lti_consumer_'.$i.'" value="'.$consumer.'" /></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'version'}.':<select name="lti_version_'.$i.'">'.
                   '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'lifetime'}.':<input type="text" name="lti_lifetime_'.$i.'"'.
                   'value="'.$lifetime.'" size="3" /></span>'.
                   ('&nbsp;'x2).
                    '<span class="LC_nobreak">'.$lt{'requser'}.':'.
                    '<label><input type="radio" name="lti_requser_'.$i.'" value="1"'.$onclickrequser.$checkedrequser{yes}.' />'.&mt('Yes').'</label>&nbsp;'."\n".
                    '<label><input type="radio" name="lti_requser_'.$i.'" value="0"'.$onclickrequser.$checkedrequser{no}.' />'.&mt('No').'</label></span>'."\n".
                   '<br /><br />'.
                   '<span class="LC_nobreak">'.$lt{'crsinc'}.':'.
                   '<label><input type="radio" name="lti_crsinc_'.$i.'" value="1"'.$onclickcrsinc.$checkedcrsinc{yes}.' />'.&mt('Yes').'</label>&nbsp;'."\n".
                   '<label><input type="radio" name="lti_crsinc_'.$i.'" value="0"'.$onclickcrsinc.$checkedcrsinc{no}.' />'.&mt('No').'</label></span>'."\n".
                   ('&nbsp;'x4).
                   '<span class="LC_nobreak">'.$lt{'key'}.
                   ':<input type="text" size="25" name="lti_key_'.$i.'" value="'.$key.'" /></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'secret'}.':'.
                   '<input type="password" size="20" name="lti_secret_'.$i.'" value="'.$secret.'" />'.
                   '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.lti_secret_'.$i.'.type='."'text'".' } else { this.form.lti_secret_'.$i.'.type='."'password'".' }" />'.&mt('Visible input').'</label>'.
                   '<input type="hidden" name="lti_id_'.$i.'" value="'.$item.'" /></span>'.
                   '</fieldset>'.&lti_options($i,$current,$itemcount,%lt).'</td></tr>';
               $itemcount ++;
           }
       }
       $css_class = $itemcount%2?' class="LC_odd_row"':'';
       my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'lti_pos_add'".');"';
       $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
                     '<input type="hidden" name="lti_maxnum" value="'.$maxnum.'" />'."\n".
                     '<select name="lti_pos_add"'.$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="lti_add" value="1" />'.&mt('Add').'</span></td>'."\n".
                     '<td colspan="2">'.
                     '<fieldset><legend>'.&mt('Required settings').'</legend>'.
                     '<span class="LC_nobreak">'.$lt{'consumer'}.
                     ':<input type="text" size="15" name="lti_consumer_add" value="" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'version'}.':<select name="lti_version_add">'.
                     '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'lifetime'}.':<input type="text" size="3" name="lti_lifetime_add" value="300" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'requser'}.':'.
                     '<label><input type="radio" name="lti_requser_add" value="1" onclick="toggleLTI(this.form,'."'requser','add'".');" checked="checked" />'.&mt('Yes').'</label>&nbsp;'."\n".
                     '<label><input type="radio" name="lti_requser_add" value="0" onclick="toggleLTI(this.form,'."'requser','add'".');" />'.&mt('No').'</label></span>'."\n".
                     '<br /><br />'.
                     '<span class="LC_nobreak">'.$lt{'crsinc'}.':'.
                     '<label><input type="radio" name="lti_crsinc_add" value="1" onclick="toggleLTI(this.form,'."'crsinc','add'".');" checked="checked" />'.&mt('Yes').'</label>&nbsp;'."\n".
                     '<label><input type="radio" name="lti_crsinc_add" value="0" onclick="toggleLTI(this.form,'."'crsinc','add'".');" />'.&mt('No').'</label></span>'."\n".
                     ('&nbsp;'x4).
                     '<span class="LC_nobreak">'.$lt{'key'}.':<input type="text" size="25" name="lti_key_add" value="" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'secret'}.':<input type="password" size="20" name="lti_secret_add" value="" />'.
                     '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.lti_secret_add.type='."'text'".' } else { this.form.lti_secret_add.type='."'password'".' }" />'.&mt('Visible input').'</label></span> '."\n".
                     '</fieldset>'.&lti_options('add',undef,$itemcount,%lt).
                     '</td>'."\n".
                     '</tr>'."\n";
       $$rowtotal ++;
       return $datatable;;
   }
   
   sub lti_names {
       my %lt = &Apache::lonlocal::texthash(
                                             'version'   => 'LTI Version',
                                             'url'       => 'URL',
                                             'key'       => 'Key',
                                             'lifetime'  => 'Nonce lifetime (s)',
                                             'consumer'  => 'Consumer',
                                             'secret'    => 'Secret',
                                             'requser'   => "User's identity sent",
                                             'crsinc'    => "Course's identity sent",
                                             'email'     => 'Email address',
                                             'sourcedid' => 'User ID',
                                             'other'     => 'Other',
                                             'passback'  => 'Can return grades to Consumer:',
                                             'roster'    => 'Can retrieve roster from Consumer:',
                                             'topmenu'   => 'Display LON-CAPA page header',
                                             'inlinemenu'=> 'Display LON-CAPA inline menu',
                                           );
     return %lt;      return %lt;
 }  }
   
   sub lti_options {
       my ($num,$current,$itemcount,%lt) = @_;
       my (%checked,%rolemaps,$crssecsrc,$userfield,$cidfield,$callback);
       $checked{'mapuser'}{'sourcedid'} = ' checked="checked"';
       $checked{'mapcrs'}{'course_offering_sourcedid'} = ' checked="checked"';
       $checked{'storecrs'}{'Y'} = ' checked="checked"';
       $checked{'makecrs'}{'N'} = ' checked="checked"';
       $checked{'mapcrstype'} = {};
       $checked{'makeuser'} = {};
       $checked{'selfenroll'} = {};
       $checked{'crssec'} = {};
       $checked{'crssecsrc'} = {};
       $checked{'lcauth'} = {};
       $checked{'menuitem'} = {};
       if ($num eq 'add') {
           $checked{'lcauth'}{'lti'} = ' checked="checked"';
       }
       my $userfieldsty = 'none';
       my $crsfieldsty = 'none';
       my $crssecfieldsty = 'none';
       my $secsrcfieldsty = 'none';
       my $callbacksty = 'none';
       my $passbacksty = 'none';
       my $optionsty = 'block';
       my $crssty = 'block';
       my $lcauthparm;
       my $lcauthparmstyle = 'display:none';
       my $lcauthparmtext;
       my $menusty;
       my $numinrow = 4;
       my %menutitles = &ltimenu_titles();
   
       if (ref($current) eq 'HASH') {
           if (!$current->{'requser'}) {
               $optionsty = 'none';
               $crssty = 'none';
           } elsif (!$current->{'crsinc'}) {
               $crssty = 'none';
           }
           if (($current->{'mapuser'} ne '') && ($current->{'mapuser'} ne 'lis_person_sourcedid')) {
               $checked{'mapuser'}{'sourcedid'} = '';
               if ($current->{'mapuser'} eq 'lis_person_contact_email_primary') {
                   $checked{'mapuser'}{'email'} = ' checked="checked"'; 
               } else {
                   $checked{'mapuser'}{'other'} = ' checked="checked"';
                   $userfield = $current->{'mapuser'};
                   $userfieldsty = 'inline-block';
               }
           }
           if (($current->{'mapcrs'} ne '') && ($current->{'mapcrs'} ne 'course_offering_sourcedid')) {
               $checked{'mapcrs'}{'course_offering_sourcedid'} = '';
               if ($current->{'mapcrs'} eq 'context_id') {
                   $checked{'mapcrs'}{'context_id'} = ' checked="checked"'; 
               } else {
                   $checked{'mapcrs'}{'other'} = ' checked="checked"';
                   $cidfield = $current->{'mapcrs'};
                   $crsfieldsty = 'inline-block';
               }
           }
           if (ref($current->{'mapcrstype'}) eq 'ARRAY') {
               foreach my $type (@{$current->{'mapcrstype'}}) {
                   $checked{'mapcrstype'}{$type} = ' checked="checked"';
               }
           }
           if (!$current->{'storecrs'}) {
               $checked{'storecrs'}{'N'} = $checked{'storecrs'}{'Y'};
               $checked{'storecrs'}{'Y'} = '';
           }
           if ($current->{'makecrs'}) {
               $checked{'makecrs'}{'Y'} = '  checked="checked"';
           }
           if (ref($current->{'makeuser'}) eq 'ARRAY') {
               foreach my $role (@{$current->{'makeuser'}}) {
                   $checked{'makeuser'}{$role} = ' checked="checked"';
               }
           }
           if ($current->{'lcauth'} =~ /^(internal|localauth|krb4|krb5|lti)$/) {
               $checked{'lcauth'}{$1} = ' checked="checked"';
               unless (($current->{'lcauth'} eq 'lti') || ($current->{'lcauth'} eq 'internal')) {
                   $lcauthparm = $current->{'lcauthparm'};
                   $lcauthparmstyle = 'display:table-row'; 
                   if ($current->{'lcauth'} eq 'localauth') {
                       $lcauthparmtext = &mt('Local auth argument');
                   } else {
                       $lcauthparmtext = &mt('Kerberos domain');
                   }
               }
           }
           if (ref($current->{'selfenroll'}) eq 'ARRAY') {
               foreach my $role (@{$current->{'selfenroll'}}) {
                   $checked{'selfenroll'}{$role} = ' checked="checked"';
               }
           }
           if (ref($current->{'maproles'}) eq 'HASH') {
               %rolemaps = %{$current->{'maproles'}};
           }
           if ($current->{'section'} ne '') {
               $checked{'crssec'}{'Y'} = '  checked="checked"'; 
               $crssecfieldsty = 'inline-block';
               if ($current->{'section'} eq 'course_section_sourcedid') {
                   $checked{'crssecsrc'}{'sourcedid'} = ' checked="checked"';
               } else {
                   $checked{'crssecsrc'}{'other'} = ' checked="checked"';
                   $crssecsrc = $current->{'section'};
                   $secsrcfieldsty = 'inline-block';
               }
           } else {
               $checked{'crssec'}{'N'} = ' checked="checked"';
           }
           if ($current->{'callback'} ne '') {
               $callback = $current->{'callback'};
               $checked{'callback'}{'Y'} = ' checked="checked"';
               $callbacksty = 'inline-block';
           } else {
               $checked{'callback'}{'N'} = ' checked="checked"';
           }
           if ($current->{'topmenu'}) {
               $checked{'topmenu'}{'Y'} = ' checked="checked"';
           } else {
               $checked{'topmenu'}{'N'} = ' checked="checked"';
           }
           if ($current->{'inlinemenu'}) {
               $checked{'inlinemenu'}{'Y'} = ' checked="checked"';
           } else {
               $checked{'inlinemenu'}{'N'} = ' checked="checked"';
           }
           if (($current->{'topmenu'}) || ($current->{'inlinemenu'})) {
               $menusty = 'inline-block';
               if (ref($current->{'lcmenu'}) eq 'ARRAY') {
                   foreach my $item (@{$current->{'lcmenu'}}) {
                       if (exists($menutitles{$item})) {
                           $checked{'menuitem'}{$item} = ' checked="checked"';
                       }
                   }
               }
           } else {
               $menusty = 'none';
           }
       } else {
           $checked{'makecrs'}{'N'} = ' checked="checked"';
           $checked{'crssec'}{'N'} = ' checked="checked"';
           $checked{'callback'}{'N'} = ' checked="checked"';
           $checked{'topmenu'}{'N'} = ' checked="checked"';
           $checked{'inlinemenu'}{'Y'} = ' checked="checked"'; 
           $checked{'menuitem'}{'grades'} = ' checked="checked"';
           $menusty = 'inline-block'; 
       }
       my @coursetypes = ('official','unofficial','community','textbook','placement','lti');
       my %coursetypetitles = &Apache::lonlocal::texthash (
                                  official   => 'Official',
                                  unofficial => 'Unofficial',
                                  community  => 'Community',
                                  textbook   => 'Textbook',
                                  placement  => 'Placement Test',
                                  lti        => 'LTI Provider',
       );
       my @authtypes = ('internal','krb4','krb5','localauth');
       my %shortauth = (
                        internal => 'int',
                        krb4 => 'krb4',
                        krb5 => 'krb5',
                        localauth  => 'loc'
                       );
       my %authnames = &authtype_names();
       my @ltiroles = qw(Learner Instructor ContentDeveloper TeachingAssistant Mentor Member Manager Administrator);
       my @lticourseroles = qw(Learner Instructor TeachingAssistant Mentor);
       my @courseroles = ('cc','in','ta','ep','st');
       my $onclickuser = ' onclick="toggleLTI(this.form,'."'user','$num'".');"';
       my $onclickcrs = ' onclick="toggleLTI(this.form,'."'crs','$num'".');"';
       my $onclicksec = ' onclick="toggleLTI(this.form,'."'sec','$num'".');"';
       my $onclickcallback = ' onclick="toggleLTI(this.form,'."'callback','$num'".');"';
       my $onclicksecsrc = ' onclick="toggleLTI(this.form,'."'secsrc','$num'".')"';
       my $onclicklcauth = ' onclick="toggleLTI(this.form,'."'lcauth','$num'".')"';
       my $onclickmenu = ' onclick="toggleLTI(this.form,'."'lcmenu','$num'".');"';
       my $output = '<fieldset class="ltioption_usr_'.$num.'" style="display:'.$optionsty.'"><legend>'.&mt('Logout options').'</legend>'.
                    '<div class="LC_floatleft"><span class="LC_nobreak">'.&mt('Callback to logout LON-CAPA on log out from Consumer').':&nbsp;'.
                    '<label><input type="radio" name="lti_callback_'.$num.'" value="0"'.
                    $checked{'callback'}{'N'}.$onclickcallback.' />'.&mt('No').'</label>'.('&nbsp;'x2).
                    '<label><input type="radio" name="lti_callback_'.$num.'" value="1"'.
                    $checked{'callback'}{'Y'}.$onclickcallback.' />'.&mt('Yes').'</label></span></div>'.
                    '<div class="LC_floatleft" style="display:'.$callbacksty.';" id="lti_callbackfield_'.$num.'">'.
                    '<span class="LC_nobreak">'.&mt('Parameter').': '.
                    '<input type="text" name="lti_callbackparam_'.$num.'" value="'.$callback.'" /></span>'.
                    '</div><div style="padding:0;clear:both;margin:0;border:0"></div></fieldset>'.
                    '<fieldset class="ltioption_usr_'.$num.'" style="display:'.$optionsty.'"><legend>'.&mt('Mapping users').'</legend>'.
                    '<div class="LC_floatleft"><span class="LC_nobreak">'.&mt('LON-CAPA username').':&nbsp;';
       foreach my $option ('sourcedid','email','other') {
           $output .= '<label><input type="radio" name="lti_mapuser_'.$num.'" value="'.$option.'"'.
                      $checked{'mapuser'}{$option}.$onclickuser.' />'.$lt{$option}.'</label>'.
                      ($option eq 'other' ? '' : ('&nbsp;'x2) );
       }
       $output .= '</span></div>'.
                  '<div class="LC_floatleft" style="display:'.$userfieldsty.';" id="lti_userfield_'.$num.'">'.
                  '<input type="text" name="lti_customuser_'.$num.'" '.
                  'value="'.$userfield.'" /></div></fieldset>'.
                  '<fieldset class="ltioption_usr_'.$num.'" style="display:'.$optionsty.'"><legend>'.&mt('Roles which may create user accounts').'</legend>';
       foreach my $ltirole (@ltiroles) {
           $output .= '<span class="LC_nobreak"><label><input type="checkbox" name="lti_makeuser_'.$num.'" value="'.$ltirole.'"'.
                      $checked{'makeuser'}{$ltirole}.' />'.$ltirole.'</label>&nbsp;</span> ';     
       }
       $output .= '</fieldset>'.
                  '<fieldset class="ltioption_usr_'.$num.'" style="display:'.$optionsty.'"><legend>'.&mt('New user accounts created for LTI users').'</legend>'.
                  '<table>'.
                  &modifiable_userdata_row('lti','instdata_'.$num,$current,$numinrow,$itemcount).
                  '</table>'.
                  '<table class="LC_nested"><tr><td class="LC_left_item">LON-CAPA Authentication</td>'.
                  '<td class="LC_left_item">';
       foreach my $auth ('lti',@authtypes) {
           my $authtext;
           if ($auth eq 'lti') {
               $authtext = &mt('None');
           } else {
               $authtext = $authnames{$shortauth{$auth}};
           }
           $output .= '<span class="LC_nobreak"><label><input type="radio" name="lti_lcauth_'.$num.
                      '" value="'.$auth.'"'.$checked{'lcauth'}{$auth}.$onclicklcauth.' />'.
                      $authtext.'</label></span> &nbsp;';
       }
       $output .= '</td></tr>'.
                  '<tr id="lti_lcauth_parmrow_'.$num.'" style="'.$lcauthparmstyle.'">'.
                  '<td class="LC_right_item" colspan="2"><span class="LC_nobreak">'.
                  '<span id="lti_lcauth_parmtext_'.$num.'">'.$lcauthparmtext.'</span>'.
                  '<input type="text" name="lti_lcauthparm_'.$num.'" value="" /></span></td></tr>'.
                  '</table></fieldset>'.
                  '<fieldset class="ltioption_usr_'.$num.'" style="display:'.$optionsty.'"><legend>'.
                  &mt('LON-CAPA menu items (Course Coordinator can override)').'</legend>'.
                  '<div class="LC_floatleft"><span class="LC_nobreak">'.$lt{'topmenu'}.':&nbsp;'.
                  '<label><input type="radio" name="lti_topmenu_'.$num.'" value="0"'.
                  $checked{'topmenu'}{'N'}.$onclickmenu.' />'.&mt('No').'</label>'.('&nbsp;'x2).
                  '<label><input type="radio" name="lti_topmenu_'.$num.'" value="1"'.
                  $checked{'topmenu'}{'Y'}.$onclickmenu.' />'.&mt('Yes').'</label></span></div>'.
                  '<div style="padding:0;clear:both;margin:0;border:0"></div>'.
                  '<div class="LC_floatleft"><span class="LC_nobreak">'.$lt{'inlinemenu'}.':&nbsp;'.
                  '<label><input type="radio" name="lti_inlinemenu_'.$num.'" value="0"'.
                  $checked{'inlinemenu'}{'N'}.$onclickmenu.' />'.&mt('No').'</label>'.('&nbsp;'x2).
                  '<label><input type="radio" name="lti_inlinemenu_'.$num.'" value="1"'.
                  $checked{'inlinemenu'}{'Y'}.$onclickmenu.' />'.&mt('Yes').'</label></span></div>';
        $output .='<div style="padding:0;clear:both;margin:0;border:0"></div>'.
                  '<div class="LC_floatleft" style="display:'.$menusty.';" id="lti_menufield_'.$num.'">'.
                  '<span class="LC_nobreak">'.&mt('Menu items').':&nbsp;';
       foreach my $type ('fullname','coursetitle','role','logout','grades') {
           $output .= '<label><input type="checkbox" name="lti_menuitem_'.$num.'" value="'.$type.'"'.
                      $checked{'menuitem'}{$type}.' />'.$menutitles{$type}.'</label>'.
                      ('&nbsp;'x2);
       }
       $output .= '</span></div></fieldset>'.
                  '<fieldset class="ltioption_crs_'.$num.'" style="display:'.$crssty.'"><legend>'.&mt('Mapping courses').'</legend>'.
                  '<div class="LC_floatleft"><span class="LC_nobreak">'.
                  &mt('Unique course identifier').':&nbsp;';
       foreach my $option ('course_offering_sourcedid','context_id','other') {
           $output .= '<label><input type="radio" name="lti_mapcrs_'.$num.'" value="'.$option.'"'.
                      $checked{'mapcrs'}{$option}.$onclickcrs.' />'.$option.'</label>'.
                      ($option eq 'other' ? '' : ('&nbsp;'x2) );
       }
       $output .= '</span></div><div class="LC_floatleft" style="display:'.$crsfieldsty.';" id="lti_crsfield_'.$num.'">'.
                  '<input type="text" name="lti_mapcrsfield_'.$num.'" value="'.$cidfield.'" />'.
                  '</div><div style="padding:0;clear:both;margin:0;border:0"></div>'.
                  '<span class="LC_nobreak">'.&mt('LON-CAPA course type(s)').':&nbsp;';
       foreach my $type (@coursetypes) {
           $output .= '<label><input type="checkbox" name="lti_mapcrstype_'.$num.'" value="'.$type.'"'.
                      $checked{'mapcrstype'}{$type}.' />'.$coursetypetitles{$type}.'</label>'.
                      ('&nbsp;'x2);
       }
       $output .= '</span><br /><br />'.
                  '<span class="LC_nobreak">'.&mt('Store mapping of course identifier to LON-CAPA CourseID').':&nbsp;'.
                  '<label><input type="radio" name="lti_storecrs_'.$num.'" value="0"'.
                  $checked{'storecrs'}{'N'}.' />'.&mt('No').'</label>'.('&nbsp;'x2).
                  '<label><input type="radio" name="lti_storecrs_'.$num.'" value="1"'.
                  $checked{'storecrs'}{'Y'}.' />'.&mt('Yes').'</label></span>'.
                  '</fieldset>'.
                  '<fieldset class="ltioption_crs_'.$num.'" style="display:'.$crssty.'"><legend>'.&mt('Mapping course roles').'</legend><table><tr>';
       foreach my $ltirole (@lticourseroles) {
           my ($selected,$selectnone);
           if ($rolemaps{$ltirole} eq '') {
               $selectnone = ' selected="selected"';
           }
           $output .= '<td style="text-align: center">'.$ltirole.'<br />'.
                      '<select name="lti_maprole_'.$ltirole.'_'.$num.'">'.
                      '<option value=""'.$selectnone.'>'.&mt('Select').'</option>';
           foreach my $role (@courseroles) {
               unless ($selectnone) {
                   if ($rolemaps{$ltirole} eq $role) {
                       $selected = ' selected="selected"';
                   } else {
                       $selected = '';
                   }
               }
               $output .= '<option value="'.$role.'"'.$selected.'>'.
                          &Apache::lonnet::plaintext($role,'Course').
                          '</option>';
           }
           $output .= '</select></td>';
       }
       $output .= '</tr></table></fieldset>'.
                  '<fieldset class="ltioption_crs_'.$num.'" style="display:'.$crssty.'"><legend>'.&mt('Creating courses').'</legend>'.
                  '<span class="LC_nobreak">'.&mt('Course created (if absent) on Instructor access').':&nbsp;'.
                  '<label><input type="radio" name="lti_makecrs_'.$num.'" value="0"'.
                  $checked{'makecrs'}{'N'}.' />'.&mt('No').'</label>'.('&nbsp;'x2).
                  '<label><input type="radio" name="lti_makecrs_'.$num.'" value="1"'.
                  $checked{'makecrs'}{'Y'}.' />'.&mt('Yes').'</label></span>'.
                  '</fieldset>'.
                  '<fieldset class="ltioption_crs_'.$num.'" style="display:'.$crssty.'"><legend>'.&mt('Roles which may self-enroll').'</legend>';
       foreach my $lticrsrole (@lticourseroles) {
           $output .= '<span class="LC_nobreak"><label><input type="checkbox" name="lti_selfenroll_'.$num.'" value="'.$lticrsrole.'"'.
                      $checked{'selfenroll'}{$lticrsrole}.' />'.$lticrsrole.'</label>&nbsp;</span> ';
       }
       $output .= '</fieldset>'.
                  '<fieldset class="ltioption_crs_'.$num.'" style="display:'.$crssty.'"><legend>'.&mt('Course options').'</legend>'.
                  '<div class="LC_floatleft"><span class="LC_nobreak">'.&mt('Assign users to sections').':&nbsp;'.
                  '<label><input type="radio" name="lti_crssec_'.$num.'" value="0"'.
                  $checked{'crssec'}{'N'}.$onclicksec.' />'.&mt('No').'</label>'.('&nbsp;'x2).
                  '<label><input type="radio" name="lti_crssec_'.$num.'" value="1"'.
                  $checked{'crssec'}{'Y'}.$onclicksec.' />'.&mt('Yes').'</label></span></div>'.
                  '<div class="LC_floatleft" style="display:'.$crssecfieldsty.';" id="lti_crssecfield_'.$num.'">'.
                  '<span class="LC_nobreak">'.&mt('From').':<label>'.
                  '<input type="radio" name="lti_crssecsrc_'.$num.'" value="course_section_sourcedid"'.
                  $checked{'crssecsrc'}{'sourcedid'}.$onclicksecsrc.' />'.
                  &mt('Standard field').'</label>'.('&nbsp;'x2).
                  '<label><input type="radio" name="lti_crssecsrc_'.$num.'" value="other"'.
                  $checked{'crssecsrc'}{'other'}.$onclicksecsrc.' />'.&mt('Other').
                  '</label></span></div><div class="LC_floatleft" style="display:'.$secsrcfieldsty.';" id="lti_secsrcfield_'.$num.'">'.
                  '<input type="text" name="lti_customsection_'.$num.'" value="'.$crssecsrc.'" />'.
                  '</div><div style="padding:0;clear:both;margin:0;border:0"></div>';
       my ($pb1p1chk,$pb1p0chk,$onclickpb);
       foreach my $extra ('roster','passback') {
           my $checkedon = '';
           my $checkedoff = ' checked="checked"';
           if ($extra eq 'passback') {
               $pb1p1chk = ' checked="checked"';
               $pb1p0chk = '';
               $onclickpb = ' onclick="toggleLTI(this.form,'."'passback','$num'".');"'; 
           } else {
               $onclickpb = ''; 
           }
           if (ref($current) eq 'HASH') {
               if (($current->{$extra})) {
                   $checkedon = $checkedoff;
                   $checkedoff = '';
                   if ($extra eq 'passback') {
                       $passbacksty = 'inline-block';
                   }
                   if ($current->{'passbackformat'} eq '1.0') {
                       $pb1p0chk =  ' checked="checked"';
                       $pb1p1chk = '';
                   }
               }
           }
           $output .= $lt{$extra}.'&nbsp;'.
                      '<label><input type="radio" name="lti_'.$extra.'_'.$num.'" value="0"'.$checkedoff.$onclickpb.' />'.
                      &mt('No').'</label>'.('&nbsp;'x2).
                      '<label><input type="radio" name="lti_'.$extra.'_'.$num.'" value="1"'.$checkedon.$onclickpb.' />'.
                      &mt('Yes').'</label><br />';
       }
       $output .= '<div class="LC_floatleft" style="display:'.$passbacksty.';" id="lti_passback_'.$num.'">'.
                  '<span class="LC_nobreak">'.&mt('Grade format').
                  '<label><input type="radio" name="lti_passbackformat_'.$num.'" value="1.1"'.$pb1p1chk.' />'.
                  &mt('Outcomes Service (1.1)').'</label>'.('&nbsp;'x2).
                  '<label><input type="radio" name="lti_passbackformat_'.$num.'" value="1.0"'.$pb1p0chk.'/>'.
                  &mt('Outcomes Extension (1.0)').'</label></span></div>'.
                  '<div style="padding:0;clear:both;margin:0;border:0"></div></fieldset>';
       $output .= '</span></div></fieldset>';
   #        '<fieldset><legend>'.&mt('Assigning author roles').'</legend>';
   #
   #    $output .= '</fieldset>'.
   #        '<fieldset><legend>'.&mt('Assigning domain roles').'</legend>';
       return $output;
   }
   
   sub ltimenu_titles {
       return &Apache::lonlocal::texthash(
                                           fullname    => 'Full name',
                                           coursetitle => 'Course title',
                                           role        => 'Role',
                                           logout      => 'Logout',
                                           grades      => 'Grades',
       );
   }
   
 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)',
         inline_chem          => 'Use inline previewer for chemical reaction response in place of pop-up',  
         texengine            => 'Default method to display mathematics',          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)",
Line 5053  sub print_coursedefaults { Line 6785  sub print_coursedefaults {
                          );                           );
     if ($position eq 'top') {      if ($position eq 'top') {
         %defaultchecked = (          %defaultchecked = (
                               'canuse_pdfforms' => 'off',
                             'uselcmath'       => 'on',                              'uselcmath'       => 'on',
                             'usejsme'         => 'on',                              'usejsme'         => 'on',
                             'inline_chem'     => 'on',  
                             'canclone'        => 'none',                              'canclone'        => 'none',
                           );                            );
         @toggles = ('uselcmath','usejsme','inline_chem');          @toggles = ('canuse_pdfforms','uselcmath','usejsme');
         my $deftex = $Apache::lonnet::deftex;          my $deftex = $Apache::lonnet::deftex;
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if ($settings->{'texengine'}) {              if ($settings->{'texengine'}) {
Line 5091  sub print_coursedefaults { Line 6823  sub print_coursedefaults {
         $datatable = $mathdisp.$datatable;          $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 style="vertical-align: top">'.
             '<span class="LC_nobreak">'.$choices{'canclone'}.              '<span class="LC_nobreak">'.$choices{'canclone'}.
             '</span></td><td class="LC_left_item">';              '</span></td><td class="LC_left_item">';
         my $currcanclone = 'none';          my $currcanclone = 'none';
Line 5135  sub print_coursedefaults { Line 6867  sub print_coursedefaults {
                     if ($checked) {                      if ($checked) {
                         $show = 'block';                          $show = 'block';
                     }                      }
                     $additional = '<div id="cloneinstcode" style="display:'.$show.'" />'.                      $additional = '<div id="cloneinstcode" style="display:'.$show.';" />'.
                                   &mt('Institutional codes for new and cloned course have identical:').                                    &mt('Institutional codes for new and cloned course have identical:').
                                   '<br />';                                    '<br />';
                     foreach my $item (@code_order) {                      foreach my $item (@code_order) {
Line 5165  sub print_coursedefaults { Line 6897  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 5243  sub print_coursedefaults { Line 6975  sub print_coursedefaults {
         $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.          $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
                       $choices{'uploadquota'}.                        $choices{'uploadquota'}.
                       '</span></td>'.                        '</span></td>'.
                       '<td align="right" class="LC_right_item">'.                        '<td style="text-align: right" class="LC_right_item">'.
                       '<table><tr>';                        '<table><tr>';
         foreach my $type (@types) {          foreach my $type (@types) {
             $datatable .= '<td align="center">'.&mt($type).'<br />'.              $datatable .= '<td style="text-align: center">'.&mt($type).'<br />'.
                            '<input type="text" name="uploadquota_'.$type.'"'.                             '<input type="text" name="uploadquota_'.$type.'"'.
                            ' value="'.$curruploadquota{$type}.'" size="5" /></td>';                             ' value="'.$curruploadquota{$type}.'" size="5" /></td>';
         }          }
Line 5261  sub print_coursedefaults { Line 6993  sub print_coursedefaults {
                          '<i>'.&mt('Default credits').'</i><br /><table><tr>';                           '<i>'.&mt('Default credits').'</i><br /><table><tr>';
         foreach my $type (@types) {          foreach my $type (@types) {
             next if ($type eq 'community');              next if ($type eq 'community');
             $additional .= '<td align="center">'.&mt($type).'<br />'.              $additional .= '<td style="text-align: center">'.&mt($type).'<br />'.
                            '<input type="text" name="'.$type.'_credits"'.                             '<input type="text" name="'.$type.'_credits"'.
                            ' value="'.$defcredits{$type}.'" size="3" /></td>';                             ' value="'.$defcredits{$type}.'" size="3" /></td>';
         }          }
Line 5285  sub print_coursedefaults { Line 7017  sub print_coursedefaults {
                       '<i>'.&mt('Enter 0 to remain disabled until page reload.').'</i><br />'.                        '<i>'.&mt('Enter 0 to remain disabled until page reload.').'</i><br />'.
                       '<table><tr>';                        '<table><tr>';
         foreach my $type (@types) {          foreach my $type (@types) {
             $additional .= '<td align="center">'.&mt($type).'<br />'.              $additional .= '<td style="text-align: center">'.&mt($type).'<br />'.
                            '<input type="text" name="'.$type.'_timeout" value="'.                             '<input type="text" name="'.$type.'_timeout" value="'.
                            $deftimeout{$type}.'" size="5" /></td>';                             $deftimeout{$type}.'" size="5" /></td>';
         }          }
Line 5303  sub print_coursedefaults { Line 7035  sub print_coursedefaults {
         $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.          $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
                       $choices{'mysqltables'}.                        $choices{'mysqltables'}.
                       '</span></td>'.                        '</span></td>'.
                       '<td align="right" class="LC_right_item">'.                        '<td style="text-align: right" class="LC_right_item">'.
                       '<table><tr>';                        '<table><tr>';
         foreach my $type (@types) {          foreach my $type (@types) {
             $datatable .= '<td align="center">'.&mt($type).'<br />'.              $datatable .= '<td style="text-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="8" /></td>';
         }          }
Line 5322  sub print_selfenrollment { Line 7054  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 5543  sub print_validation_rows { Line 7275  sub print_validation_rows {
     return $datatable;      return $datatable;
 }  }
   
   sub print_privacy {
       my ($position,$dom,$settings,$rowtotal) = @_;
       my ($datatable,$css_class,$numinrow,@items,%names,$othertitle,$usertypes,$types);
       my $itemcount = 0;
       unless ($position eq 'top') {
           @items = ('domain','author','course','community');
           %names = &Apache::lonlocal::texthash (
                        domain => 'Assigned domain role(s)',
                        author => 'Assigned co-author role(s)',
                        course => 'Assigned course role(s)',
                        community => 'Assigned community role',
                    );
           $numinrow = 4;
           ($othertitle,$usertypes,$types) =
               &Apache::loncommon::sorted_inst_types($dom);
       }
       if (($position eq 'top') || ($position eq 'middle')) {
           my (%by_ip,%by_location,@intdoms,@instdoms);
           &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
           if ($position eq 'top') {
               my %curr;
               my @options = ('none','user','domain','auto');
               my %titles = &Apache::lonlocal::texthash (
                   none   => 'Not allowed',
                   user   => 'User authorizes',
                   domain => 'DC authorizes',
                   auto   => 'Unrestricted',
                   instdom => 'Other domain shares institution/provider',
                   extdom => 'Other domain has different institution/provider',
               );
               my %names = &Apache::lonlocal::texthash (
                   domain => 'Domain role',
                   author => 'Co-author role',
                   course => 'Course role',
                   community => 'Community role',
               );
               my $primary_id = &Apache::lonnet::domain($dom,'primary');
               my $intdom = &Apache::lonnet::internet_dom($primary_id);
               foreach my $domtype ('instdom','extdom') {
                   my (%checked,$skip);
                   $css_class = $itemcount%2?' class="LC_odd_row"':'';
                   $datatable .= '<tr'.$css_class.'><td>'.$titles{$domtype}.'</td>'.
                                 '<td class="LC_left_item">';
                   if ($domtype eq 'instdom') {
                       unless (@instdoms > 1) {
                           $datatable .= &mt('Nothing to set, as no domains besides [_1] are hosted by [_2]',$dom,$intdom);
                           $skip = 1;
                       }
                   } elsif ($domtype eq 'extdom') {
                       if (keys(%by_location) == 0) {
                           $datatable .= &mt('Nothing to set, as no other hosts besides [_1]',$intdom);
                           $skip = 1;
                       }
                   }
                   unless ($skip) {
                       foreach my $roletype ('domain','author','course','community') {
                           $checked{'auto'} = ' checked="checked"';
                           if (ref($settings) eq 'HASH') {
                               if (ref($settings->{approval}) eq 'HASH') {
                                   if (ref($settings->{approval}->{$domtype}) eq 'HASH') {
                                       if ($settings->{approval}->{$domtype}->{$roletype}=~ /^(none|user|domain)$/) {
                                           $checked{$1} = ' checked="checked"';
                                           $checked{'auto'} = '';
                                       }
                                   }
                               }
                           }
                           $datatable .= '<fieldset><legend>'.$names{$roletype}.'</legend>';
                           foreach my $option (@options) {
                               $datatable .= '<span class="LC_nobreak"><label>'.
                                             '<input type="radio" name="privacy_approval_'.$domtype.'_'.$roletype.'" '.
                                             'value="'.$option.'"'.$checked{$option}.' />'.$titles{$option}.
                                             '</label></span>&nbsp; ';
                           }
                           $datatable .= '</fieldset>';
                       }
                   }
                   $datatable .= '</td></tr>';
                   $itemcount ++;
               }
           } elsif ($position eq 'middle') {
               if ((@instdoms > 1) || (keys(%by_location) > 0)) {
                   if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
                       foreach my $item (@{$types}) {
                           $datatable .= &modifiable_userdata_row('privacy','othdom_'.$item,$settings,
                                                                  $numinrow,$itemcount,'','','','','',
                                                                  '',$usertypes->{$item});
                           $itemcount ++;
                       }
                   }
                   $datatable .= &modifiable_userdata_row('privacy','othdom_default',$settings,
                                                          $numinrow,$itemcount,'','','','','',
                                                          '',$othertitle);
                   $itemcount ++;
               } else {
                   my (@insttypes,%insttitles);
                   if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
                       @insttypes = @{$types};
                       %insttitles = %{$usertypes};
                   }
                   foreach my $item (@insttypes,'default') {
                       my $title;
                       if ($item eq 'default') {
                           $title = $othertitle;
                       } else {
                           $title = $insttitles{$item};
                       }
                       $css_class = $itemcount%2?' class="LC_odd_row"':'';
                       $datatable .= '<tr'.$css_class.'>'.
                                     '<td class="LC_left_item">'.$title.'</td>'.
                                     '<td class="LC_left_item">'.
                                     &mt('Nothing to set here, as there are no other domains').
                                     '</td></tr>';
                       $itemcount ++;
                   }
               }
           }
       } else {
           my $prefix;
           if ($position eq 'lower') {
               $prefix = 'priv';
           } else {
               $prefix = 'unpriv';
           }
           foreach my $item (@items) {
               $datatable .= &modifiable_userdata_row('privacy',$prefix.'_'.$item,$settings,
                                                      $numinrow,$itemcount,'','','','','',
                                                      '',$names{$item});
               $itemcount ++;
           }
       }
       if (ref($rowtotal)) {
           $$rowtotal += $itemcount;
       }
       return $datatable;
   }
   
 sub print_passwords {  sub print_passwords {
     my ($position,$dom,$confname,$settings,$rowtotal) = @_;      my ($position,$dom,$confname,$settings,$rowtotal) = @_;
     my ($datatable,$css_class);      my ($datatable,$css_class);
Line 5564  sub print_passwords { Line 7433  sub print_passwords {
         min            => 'Minimum password length',          min            => 'Minimum password length',
         max            => 'Maximum password length',          max            => 'Maximum password length',
         chars          => 'Required characters',          chars          => 'Required characters',
           expire         => 'Password expiration (days)',
         numsaved       => 'Number of previous passwords to save and disallow reuse',          numsaved       => 'Number of previous passwords to save and disallow reuse',
     );      );
     if ($position eq 'top') {      if ($position eq 'top') {
Line 5828  sub print_passwords { Line 7698  sub print_passwords {
             $itemcount ++;              $itemcount ++;
         }          }
     } elsif ($position eq 'lower') {      } elsif ($position eq 'lower') {
         my ($min,$max,%chars,$numsaved);          my ($min,$max,%chars,$expire,$numsaved);
         $min = $Apache::lonnet::passwdmin;          $min = $Apache::lonnet::passwdmin;
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if ($settings->{min}) {              if ($settings->{min}) {
Line 5840  sub print_passwords { Line 7710  sub print_passwords {
             if (ref($settings->{chars}) eq 'ARRAY') {              if (ref($settings->{chars}) eq 'ARRAY') {
                 map { $chars{$_} = 1; } (@{$settings->{chars}});                  map { $chars{$_} = 1; } (@{$settings->{chars}});
             }              }
               if ($settings->{expire}) {
                   $expire = $settings->{expire};
               }
             if ($settings->{numsaved}) {              if ($settings->{numsaved}) {
                 $numsaved = $settings->{numsaved};                  $numsaved = $settings->{numsaved};
             }              }
Line 5900  sub print_passwords { Line 7773  sub print_passwords {
         $datatable .='</table></td></tr>';          $datatable .='</table></td></tr>';
         $itemcount ++;          $itemcount ++;
         $css_class = $itemcount%2?' class="LC_odd_row"':'';          $css_class = $itemcount%2?' class="LC_odd_row"':'';
           $datatable .= '<tr'.$css_class.'><td>'.$titles{'expire'}.'</td>'.
                         '<td class="LC_left_item"><span class="LC_nobreak">'.
                         '<input type="text" name="passwords_expire" value="'.$expire.'" size="4" '.
                         'onblur="javascript:warnIntPass(this);" />'.
                         '<span class="LC_fontsize_small"> '.&mt('(Leave blank for no expiration)').'</span>'.
                         '</span></td></tr>';
           $itemcount ++;
           $css_class = $itemcount%2?' class="LC_odd_row"':'';
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'numsaved'}.'</td>'.          $datatable .= '<tr'.$css_class.'><td>'.$titles{'numsaved'}.'</td>'.
                       '<td class="LC_left_item"><span class="LC_nobreak">'.                        '<td class="LC_left_item"><span class="LC_nobreak">'.
                       '<input type="text" name="passwords_numsaved" value="'.$numsaved.'" size="3" '.                        '<input type="text" name="passwords_numsaved" value="'.$numsaved.'" size="3" '.
                       'onblur="javascript:warnIntPass(this);" />'.                        'onblur="javascript:warnIntPass(this);" />'. 
                       '<span class="LC_fontsize_small"> '.&mt('(Leave blank to not save previous passwords)').'</span>'.                        '<span class="LC_fontsize_small"> '.&mt('(Leave blank to not save previous passwords)').'</span>'.
                       '</span></td></tr>';                        '</span></td></tr>';
     } else {      } else {
Line 5930  sub print_passwords { Line 7811  sub print_passwords {
         $datatable .= '<tr '.$css_class.'>'.          $datatable .= '<tr '.$css_class.'>'.
                       '<td>'.                        '<td>'.
                       &mt('Requirements').'<ul>'.                        &mt('Requirements').'<ul>'.
                       '<li>'.&mt("Course 'type' is not a Community").'</li>'.                        '<li>'.&mt("Course 'type' is not a Community or Placement Test").'</li>'.
                       '<li>'.&mt('User is Course Coordinator and also course owner').'</li>'.                        '<li>'.&mt('User is Course Coordinator and also course owner').'</li>'.
                       '<li>'.&mt("Student's only active roles are student role(s) in course(s) owned by this user").'</li>'.                        '<li>'.&mt("Student's only active roles are student role(s) in course(s) owned by this user").'</li>'.
                       '<li>'.&mt('User, course, and student share same domain').'</li>'.                        '<li>'.&mt('User, course, and student share same domain').'</li>'.
Line 6018  sub print_wafproxy { Line 7899  sub print_wafproxy {
             my %config = &Apache::lonnet::get_dom('configuration',['wafproxy'],$domain);              my %config = &Apache::lonnet::get_dom('configuration',['wafproxy'],$domain);
             if (ref($config{'wafproxy'}) eq 'HASH') {              if (ref($config{'wafproxy'}) eq 'HASH') {
                 $aliases{$domain} = $config{'wafproxy'}{'alias'};                  $aliases{$domain} = $config{'wafproxy'}{'alias'};
                 if (exists($config{'wafproxy'}{'saml'})) {                  if (exists($config{'wafproxy'}{'saml'})) { 
                     $saml{$domain} = $config{'wafproxy'}{'saml'};                      $saml{$domain} = $config{'wafproxy'}{'saml'};
                 }                  }
                 foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {                  foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {
Line 6083  sub print_wafproxy { Line 7964  sub print_wafproxy {
                               ('&nbsp;'x2).'<span class="LC_nobreak">'.                                ('&nbsp;'x2).'<span class="LC_nobreak">'.
                               &mt('Alias used for SSO Auth').':&nbsp;<label>'.                                &mt('Alias used for SSO Auth').':&nbsp;<label>'.
                               '<input type="radio" value="0"'.$samloff.' name="wafproxy_alias_saml_'.$server.'" />'.                                '<input type="radio" value="0"'.$samloff.' name="wafproxy_alias_saml_'.$server.'" />'.
                               &mt('No').'</label>&nbsp;<label>'.                                &mt('No').'</label>&nbsp;<label>'. 
                               '<input type="radio" value="1"'.$samlon.' name="wafproxy_alias_saml_'.$server.'" />'.                                '<input type="radio" value="1"'.$samlon.' name="wafproxy_alias_saml_'.$server.'" />'.
                               &mt('Yes').'</label></span>'.                                &mt('Yes').'</label></span>'.
                               '</td>';                                '</td>'; 
             }              }
             $aliasrows .= '</tr>';              $aliasrows .= '</tr>';
             $aliasinfo{$dom_in_effect} .= $aliasrows;              $aliasinfo{$dom_in_effect} .= $aliasrows;
Line 6274  sub remoteip_methods { Line 8155  sub remoteip_methods {
   
 sub print_usersessions {  sub print_usersessions {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable,%checked,%choices);      my ($css_class,$datatable,$itemcount,%checked,%choices);
     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 @alldoms = &Apache::lonnet::all_domains();      my @alldoms = &Apache::lonnet::all_domains();
     my %serverhomes = %Apache::lonnet::serverhomeIDs;      my %serverhomes = %Apache::lonnet::serverhomeIDs;
     my %servers = &Apache::lonnet::internet_dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
     my %altids = &id_for_thisdom(%servers);      my %altids = &id_for_thisdom(%servers);
     my $itemcount = 1;  
     if ($position eq 'top') {      if ($position eq 'top') {
         if (keys(%serverhomes) > 1) {          if (keys(%serverhomes) > 1) {
             my %spareid = &current_offloads_to($dom,$settings,\%servers);              my %spareid = &current_offloads_to($dom,$settings,\%servers);
Line 6300  sub print_usersessions { Line 8180  sub print_usersessions {
                                       $other_insts,$curroffloadnow,$curroffloadoth,$rowtotal);                                        $other_insts,$curroffloadnow,$curroffloadoth,$rowtotal);
         } else {          } else {
             $datatable .= '<tr'.$css_class.'><td colspan="2">'.              $datatable .= '<tr'.$css_class.'><td colspan="2">'.
                           &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.');                            &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.').
                             '</td></tr>';
         }          }
     } else {      } else {
         if (keys(%by_location) == 0) {          my %titles = &usersession_titles();
             $datatable .= '<tr'.$css_class.'><td colspan="2">'.          my ($prefix,@types);
                           &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.');          if ($position eq 'bottom') {
               $prefix = 'remote';
               @types = ('version','excludedomain','includedomain');
         } else {          } else {
             my %lt = &usersession_titles();              $prefix = 'hosted';
             my $numinrow = 5;              @types = ('excludedomain','includedomain');
             my $prefix;          }
             my @types;          ($datatable,$itemcount) = &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
             if ($position eq 'bottom') {      }
                 $prefix = 'remote';      $$rowtotal += $itemcount;
                 @types = ('version','excludedomain','includedomain');      return $datatable;
             } else {  }
                 $prefix = 'hosted';  
                 @types = ('excludedomain','includedomain');  sub rules_by_location {
             }      my ($settings,$prefix,$by_location,$by_ip,$types,$titles) = @_; 
             my (%current,%checkedon,%checkedoff);      my ($datatable,$itemcount,$css_class);
             my @lcversions = &Apache::lonnet::all_loncaparevs();      if (keys(%{$by_location}) == 0) {
             my @locations = sort(keys(%by_location));          $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
             foreach my $type (@types) {          $datatable = '<tr'.$css_class.'><td colspan="2">'.
                 $checkedon{$type} = '';                       &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.').
                 $checkedoff{$type} = ' checked="checked"';                       '</td></tr>';
             }          $itemcount = 1;
             if (ref($settings) eq 'HASH') {      } else {
                 if (ref($settings->{$prefix}) eq 'HASH') {          $itemcount = 0;
                     foreach my $key (keys(%{$settings->{$prefix}})) {          my $numinrow = 5;
                         $current{$key} = $settings->{$prefix}{$key};          my (%current,%checkedon,%checkedoff);
                         if ($key eq 'version') {          my @locations = sort(keys(%{$by_location}));
                             if ($current{$key} ne '') {          foreach my $type (@{$types}) {
                                 $checkedon{$key} = ' checked="checked"';              $checkedon{$type} = '';
                                 $checkedoff{$key} = '';              $checkedoff{$type} = ' checked="checked"';
                             }          }
                         } elsif (ref($current{$key}) eq 'ARRAY') {          if (ref($settings) eq 'HASH') {
               if (ref($settings->{$prefix}) eq 'HASH') {
                   foreach my $key (keys(%{$settings->{$prefix}})) {
                       $current{$key} = $settings->{$prefix}{$key};
                       if ($key eq 'version') {
                           if ($current{$key} ne '') {
                             $checkedon{$key} = ' checked="checked"';                              $checkedon{$key} = ' checked="checked"';
                             $checkedoff{$key} = '';                              $checkedoff{$key} = '';
                         }                          }
                       } elsif (ref($current{$key}) eq 'ARRAY') {
                           $checkedon{$key} = ' checked="checked"';
                           $checkedoff{$key} = '';
                     }                      }
                 }                  }
             }              }
             foreach my $type (@types) {          }
                 next if ($type ne 'version' && !@locations);          foreach my $type (@{$types}) {
                 $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';              next if ($type ne 'version' && !@locations);
                 $datatable .= '<tr'.$css_class.'>              $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
                                <td><span class="LC_nobreak">'.$lt{$type}.'</span><br />              $datatable .= '<tr'.$css_class.'>
                                <span class="LC_nobreak">&nbsp;                             <td><span class="LC_nobreak">'.$titles->{$type}.'</span><br />
                                <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>&nbsp;                             <span class="LC_nobreak">&nbsp;
                                <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';                             <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>&nbsp;
                 if ($type eq 'version') {                             <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';
                     my $selector = '<select name="'.$prefix.'_version">';              if ($type eq 'version') {
                     foreach my $version (@lcversions) {                  my @lcversions = &Apache::lonnet::all_loncaparevs();
                         my $selected = '';                  my $selector = '<select name="'.$prefix.'_version">';
                         if ($current{'version'} eq $version) {                  foreach my $version (@lcversions) {
                             $selected = ' selected="selected"';                      my $selected = '';
                         }                      if ($current{'version'} eq $version) {
                         $selector .= ' <option value="'.$version.'"'.                          $selected = ' selected="selected"';
                                      $selected.'>'.$version.'</option>';  
                     }                      }
                     $selector .= '</select> ';                      $selector .= ' <option value="'.$version.'"'.
                     $datatable .= &mt('remote server must be version: [_1] or later',$selector);                                   $selected.'>'.$version.'</option>';
                 } else {                  }
                     $datatable.= '<div><input type="button" value="'.&mt('check all').'" '.                  $selector .= '</select> ';
                                  'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.                  $datatable .= &mt('remote server must be version: [_1] or later',$selector);
                                  ' />'.('&nbsp;'x2).              } else {
                                  '<input type="button" value="'.&mt('uncheck all').'" '.                  $datatable.= '<div><input type="button" value="'.&mt('check all').'" '.
                                  'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.                               'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.
                                  "\n".                               ' />'.('&nbsp;'x2).
                                  '</div><div><table>';                               '<input type="button" value="'.&mt('uncheck all').'" '.
                     my $rem;                               'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.
                     for (my $i=0; $i<@locations; $i++) {                               "\n".
                         my ($showloc,$value,$checkedtype);                               '</div><div><table>';
                         if (ref($by_location{$locations[$i]}) eq 'ARRAY') {                  my $rem;
                             my $ip = $by_location{$locations[$i]}->[0];                  for (my $i=0; $i<@locations; $i++) {
                             if (ref($by_ip{$ip}) eq 'ARRAY') {                      my ($showloc,$value,$checkedtype);
                                  $value = join(':',@{$by_ip{$ip}});                      if (ref($by_location->{$locations[$i]}) eq 'ARRAY') {
                                 $showloc = join(', ',@{$by_ip{$ip}});                          my $ip = $by_location->{$locations[$i]}->[0];
                                 if (ref($current{$type}) eq 'ARRAY') {                          if (ref($by_ip->{$ip}) eq 'ARRAY') {
                                     foreach my $loc (@{$by_ip{$ip}}) {                                $value = join(':',@{$by_ip->{$ip}});
                                         if (grep(/^\Q$loc\E$/,@{$current{$type}})) {                              $showloc = join(', ',@{$by_ip->{$ip}});
                                             $checkedtype = ' checked="checked"';                              if (ref($current{$type}) eq 'ARRAY') {
                                             last;                                  foreach my $loc (@{$by_ip->{$ip}}) {
                                         }                                      if (grep(/^\Q$loc\E$/,@{$current{$type}})) {
                                           $checkedtype = ' checked="checked"';
                                           last;
                                     }                                      }
                                 }                                  }
                             }                              }
                         }                          }
                         $rem = $i%($numinrow);  
                         if ($rem == 0) {  
                             if ($i > 0) {  
                                 $datatable .= '</tr>';  
                             }  
                             $datatable .= '<tr>';  
                         }  
                         $datatable .= '<td class="LC_left_item">'.  
                                       '<span class="LC_nobreak"><label>'.  
                                       '<input type="checkbox" name="'.$prefix.'_'.$type.  
                                       '" value="'.$value.'"'.$checkedtype.' />'.$showloc.  
                                       '</label></span></td>';  
                     }                      }
                     $rem = @locations%($numinrow);                      $rem = $i%($numinrow);
                     my $colsleft = $numinrow - $rem;                      if ($rem == 0) {
                     if ($colsleft > 1 ) {                          if ($i > 0) {
                         $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.                              $datatable .= '</tr>';
                                       '&nbsp;</td>';                          }
                     } elsif ($colsleft == 1) {                          $datatable .= '<tr>';
                         $datatable .= '<td class="LC_left_item">&nbsp;</td>';                      }
                       $datatable .= '<td class="LC_left_item">'.
                                     '<span class="LC_nobreak"><label>'.
                                     '<input type="checkbox" name="'.$prefix.'_'.$type.
                                     '" value="'.$value.'"'.$checkedtype.' />'.$showloc.
                                     '</label></span></td>';
                   }
                   $rem = @locations%($numinrow);
                   my $colsleft = $numinrow - $rem;
                   if ($colsleft > 1 ) {
                       $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                                     '&nbsp;</td>';
                   } elsif ($colsleft == 1) {
                       $datatable .= '<td class="LC_left_item">&nbsp;</td>';
                   }
                   $datatable .= '</tr></table>';
               }
               $datatable .= '</td></tr>';
               $itemcount ++;
           }
       }
       return ($datatable,$itemcount);
   }
   
   sub print_ssl {
       my ($position,$dom,$settings,$rowtotal) = @_;
       my ($css_class,$datatable);
       my $itemcount = 1;
       if ($position eq 'top') {
           my $primary_id = &Apache::lonnet::domain($dom,'primary');
           my $intdom = &Apache::lonnet::internet_dom($primary_id);
           my $same_institution;
           if ($intdom ne '') {
               my $internet_names = &Apache::lonnet::get_internet_names($Apache::lonnet::perlvar{'lonHostID'});
               if (ref($internet_names) eq 'ARRAY') {
                   if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
                       $same_institution = 1;
                   }
               }
           }
           $css_class = $itemcount%2?' class="LC_odd_row"':'';
           $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 {
               $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.");
           }
           $datatable .= '</td></tr>';
           $itemcount ++;
       } else {
           my %titles = &ssl_titles();
           my (%by_ip,%by_location,@intdoms,@instdoms);
           &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
           my @alldoms = &Apache::lonnet::all_domains();
           my %serverhomes = %Apache::lonnet::serverhomeIDs;
           my @domservers = &Apache::lonnet::get_servers($dom);
           my %servers = &Apache::lonnet::internet_dom_servers($dom);
           my %altids = &id_for_thisdom(%servers);
           if (($position eq 'connto') || ($position eq 'connfrom')) {
               my $legacy;
               unless (ref($settings) eq 'HASH') {
                   my $name;
                   if ($position eq 'connto') {
                       $name = 'loncAllowInsecure';
                   } else {
                       $name = 'londAllowInsecure';
                   }
                   my $primarylibserv = &Apache::lonnet::domain($dom,'primary');
                   my @ids=&Apache::lonnet::current_machine_ids();
                   if (($primarylibserv ne '') && (!grep(/^\Q$primarylibserv\E$/,@ids))) {
                       my %what = (
                                      $name => 1,
                                  );
                       my ($result,$returnhash) =
                           &Apache::lonnet::get_remote_globals($primarylibserv,\%what);
                       if ($result eq 'ok') {
                           if (ref($returnhash) eq 'HASH') {
                               $legacy = $returnhash->{$name};
                           }
                       }
                   } else {
                       $legacy = $Apache::lonnet::perlvar{$name};
                   }
               }
               foreach my $type ('dom','intdom','other') {
                   my %checked;
                   $css_class = $itemcount%2?' class="LC_odd_row"':'';
                   $datatable .= '<tr'.$css_class.'><td>'.$titles{$type}.'</td>'.
                                 '<td class="LC_right_item">';
                   my $skip; 
                   if ($type eq 'dom') {
                       unless (keys(%servers) > 1) {
                           $datatable .= &mt('Nothing to set here, as there are no other servers/VMs');    
                           $skip = 1;
                       }
                   }
                   if ($type eq 'intdom') {
                       unless (@instdoms > 1) {
                           $datatable .= &mt('Nothing to set here, as there are no other domains for this institution');
                           $skip = 1;
                       } 
                   } elsif ($type eq 'other') {
                       if (keys(%by_location) == 0) {
                           $datatable .= &mt('Nothing to set here, as there are no other institutions');
                           $skip = 1;
                       }
                   }
                   unless ($skip) {
                       $checked{'yes'} = ' checked="checked"'; 
                       if (ref($settings) eq 'HASH') {
                           if (ref($settings->{$position}) eq 'HASH') {
                               if ($settings->{$position}->{$type} =~ /^(no|req)$/) {
                                   $checked{$1} = $checked{'yes'};
                                   delete($checked{'yes'}); 
                               }
                           }
                       } else {
                           if ($legacy == 0) {
                               $checked{'req'} = $checked{'yes'};
                               delete($checked{'yes'});    
                           }
                       }
                       foreach my $option ('no','yes','req') {
                           $datatable .= '<span class="LC_nobreak"><label>'.
                                         '<input type="radio" name="'.$position.'_'.$type.'" '.
                                         'value="'.$option.'"'.$checked{$option}.' />'.$titles{$option}.
                                         '</label></span>'.('&nbsp;'x2);
                     }                      }
                     $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 6419  sub print_usersessions { Line 8437  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 6439  sub build_location_hashes { Line 8507  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 6759  sub print_loadbalancing { Line 8833  sub print_loadbalancing {
         my $disabled_div_style = 'display: block';          my $disabled_div_style = 'display: block';
         my $homedom_div_style = 'display: none';          my $homedom_div_style = 'display: none';
         $datatable .= '<tr class="'.$css_class[$cssidx].'">'.          $datatable .= '<tr class="'.$css_class[$cssidx].'">'.
                       '<td rowspan="'.$rownum.'" valign="top">'.                        '<td rowspan="'.$rownum.'" style="vertical-align: top">'.
                       '<p>';                        '<p>';
         if ($lonhost eq '') {          if ($lonhost eq '') {
             $datatable .= '<span class="LC_nobreak">';              $datatable .= '<span class="LC_nobreak">';
Line 6792  sub print_loadbalancing { Line 8866  sub print_loadbalancing {
                 $homedom_div_style = 'display: block';                  $homedom_div_style = 'display: block';
             }              }
         }          }
         $datatable .= '</p></td><td rowspan="'.$rownum.'" valign="top">'.          $datatable .= '</p></td><td rowspan="'.$rownum.'" style="vertical-align: top">'.
                   '<div id="loadbalancing_disabled_'.$balnum.'" style="'.                    '<div id="loadbalancing_disabled_'.$balnum.'" style="'.
                   $disabled_div_style.'">'.$disabledtext.'</div>'."\n".                    $disabled_div_style.'">'.$disabledtext.'</div>'."\n".
                   '<div id="loadbalancing_targets_'.$balnum.'" style="'.$targets_div_style.'">'.&mt('Offloads to:').'<br />';                    '<div id="loadbalancing_targets_'.$balnum.'" style="'.$targets_div_style.'">'.&mt('Offloads to:').'<br />';
Line 6803  sub print_loadbalancing { Line 8877  sub print_loadbalancing {
                                   no => ' checked="checked"',                                    no => ' checked="checked"',
                               );                                );
         my %balcookiechecked = (          my %balcookiechecked = (
                                   no => ' checked="checked"',                                    no => ' checked="checked"', 
                                );                                 );
         foreach my $sparetype (@sparestypes) {          foreach my $sparetype (@sparestypes) {
             my $targettable;              my $targettable;
Line 7021  sub loadbalance_rule_row { Line 9095  sub loadbalance_rule_row {
     }      }
     my $space;      my $space;
     if ($islast && $num == 1) {      if ($islast && $num == 1) {
         $space = '<div display="inline-block">&nbsp;</div>';          $space = '<div style="display:inline-block;">&nbsp;</div>';
     }      }
     my $output =      my $output =
         '<tr class="'.$css_class.'" id="balanceruletr_'.$balnum.'_'.$num.'"><td valign="top">'.$space.          '<tr class="'.$css_class.'" id="balanceruletr_'.$balnum.'_'.$num.'"><td style="vertical-align: top">'.$space.
         '<div id="balanceruletitle_'.$balnum.'_'.$type.'" style="'.$style.'">'.$title.'</div></td>'."\n".          '<div id="balanceruletitle_'.$balnum.'_'.$type.'" style="'.$style.'">'.$title.'</div></td>'."\n".
         '<td valaign="top">'.$space.          '<td valaign="top">'.$space.
         '<div id="balancerule_'.$balnum.'_'.$type.'" style="'.$style.'">'."\n";          '<div id="balancerule_'.$balnum.'_'.$type.'" style="'.$style.'">'."\n";
Line 7164  sub tool_titles { Line 9238  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 7174  sub courserequest_titles { Line 9249  sub courserequest_titles {
                                    unofficial => 'Unofficial',                                     unofficial => 'Unofficial',
                                    community  => 'Communities',                                     community  => 'Communities',
                                    textbook   => 'Textbook',                                     textbook   => 'Textbook',
                                      placement  => 'Placement tests',
                                      lti        => 'LTI Provider',
                                    norequest  => 'Not allowed',                                     norequest  => 'Not allowed',
                                    approval   => 'Approval by Dom. Coord.',                                     approval   => 'Approval by DC',
                                    validate   => 'With validation',                                     validate   => 'With validation',
                                    autolimit  => 'Numerical limit',                                     autolimit  => 'Numerical limit',
                                    unlimited  => '(blank for unlimited)',                                     unlimited  => '(blank for unlimited)',
Line 7264  sub print_usercreation { Line 9341  sub print_usercreation {
             }              }
             $datatable .= '<tr'.$css_class.'>'.              $datatable .= '<tr'.$css_class.'>'.
                          '<td><span class="LC_nobreak">'.$lt{$item}.                           '<td><span class="LC_nobreak">'.$lt{$item}.
                          '</span></td><td align="right">';                           '</span></td><td style="text-align: right">';
             my @options = ('any');              my @options = ('any');
             if (ref($rules) eq 'HASH') {              if (ref($rules) eq 'HASH') {
                 if (keys(%{$rules}) > 0) {                  if (keys(%{$rules}) > 0) {
Line 7287  sub print_usercreation { Line 9364  sub print_usercreation {
         }          }
     } else {      } else {
         my @contexts = ('author','course','domain');          my @contexts = ('author','course','domain');
         my @authtypes = ('int','krb4','krb5','loc');          my @authtypes = ('int','krb4','krb5','loc','lti');
         my %checked;          my %checked;
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if (ref($settings->{'authtypes'}) eq 'HASH') {              if (ref($settings->{'authtypes'}) eq 'HASH') {
Line 7386  sub print_selfcreation { Line 9463  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;
           
         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,
Line 7523  sub print_selfcreation { Line 9600  sub print_selfcreation {
                 my $currstyle = 'display:none';                  my $currstyle = 'display:none';
                 if (grep(/^\Q$status\E$/,@ordered)) {                  if (grep(/^\Q$status\E$/,@ordered)) {
                     $currstyle = $rowstyle;                      $currstyle = $rowstyle;
                     $hidden = 0;                      $hidden = 0; 
                 }                  }
                 $datatable .= &noninst_users($processing,$emailverified,$emailoptions,$emaildomain,                  $datatable .= &noninst_users($processing,$emailverified,$emailoptions,$emaildomain,
                                              $emailrules,$emailruleorder,$settings,$status,$rowid,                                               $emailrules,$emailruleorder,$settings,$status,$rowid,
Line 7550  sub print_selfcreation { Line 9627  sub print_selfcreation {
             foreach my $status (@posstypes) {              foreach my $status (@posstypes) {
                 my $rowid = $classprefix.$status;                  my $rowid = $classprefix.$status;
                 my $datarowstyle = 'display:none';                  my $datarowstyle = 'display:none';
                 if (grep(/^\Q$status\E$/,@ordered)) {                  if (grep(/^\Q$status\E$/,@ordered)) { 
                     $datarowstyle = $rowstyle;                      $datarowstyle = $rowstyle; 
                 }                  }
                 $datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,                  $datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,
                                                        $numinrow,$$rowtotal,\%usertypeshash,$infofields,                                                         $numinrow,$$rowtotal,\%usertypeshash,$infofields,
Line 7653  function toggleEmailOptions(form,radio,p Line 9730  function toggleEmailOptions(form,radio,p
                     document.getElementById(altprefix+'_inst_'+status).style.display = 'none';                      document.getElementById(altprefix+'_inst_'+status).style.display = 'none';
                     document.getElementById(altprefix+'_noninst_'+status).style.display = 'none';                      document.getElementById(altprefix+'_noninst_'+status).style.display = 'none';
                     if (curr == 'custom') {                      if (curr == 'custom') {
                         if (prefix) {                          if (prefix) { 
                             document.getElementById(prefix+'_'+status).style.display = 'inline';                              document.getElementById(prefix+'_'+status).style.display = 'inline';
                         }                          }
                     } else if (curr == 'inst') {                      } else if (curr == 'inst') {
Line 7676  ENDSCRIPT Line 9753  ENDSCRIPT
   
 sub noninst_users {  sub noninst_users {
     my ($processing,$emailverified,$emailoptions,$emaildomain,$emailrules,      my ($processing,$emailverified,$emailoptions,$emaildomain,$emailrules,
         $emailruleorder,$settings,$type,$rowid,$typetitle,$css_class,$rowstyle,$intdom) = @_;          $emailruleorder,$settings,$type,$rowid,$typetitle,$css_class,$rowstyle,$intdom) = @_; 
     my $class = 'LC_left_item';      my $class = 'LC_left_item';
     if ($css_class) {      if ($css_class) {
         $css_class = ' class="'.$css_class.'"';          $css_class = ' class="'.$css_class.'"'; 
     }      }
     if ($rowid) {      if ($rowid) {
         $rowid = ' id="'.$rowid.'"';          $rowid = ' id="'.$rowid.'"';
Line 7694  sub noninst_users { Line 9771  sub noninst_users {
         $description = &mt('Requests for: [_1] (status self-reported)',$typetitle);          $description = &mt('Requests for: [_1] (status self-reported)',$typetitle);
     }      }
     $output = '<tr'.$css_class.$rowid.$rowstyle.'>'.      $output = '<tr'.$css_class.$rowid.$rowstyle.'>'.
               "<td>$description</td>\n".                "<td>$description</td>\n".           
               '<td class="'.$class.'" colspan="2">'.                '<td class="'.$class.'" colspan="2">'.
               '<table><tr>';                '<table><tr>';
     my %headers = &Apache::lonlocal::texthash(      my %headers = &Apache::lonlocal::texthash( 
               approve  => 'Processing',                approve  => 'Processing',
               email    => 'E-mail',                email    => 'E-mail',
               username => 'Username',                username => 'Username',
Line 7707  sub noninst_users { Line 9784  sub noninst_users {
     }      }
     $output .= '</tr><tr>';      $output .= '</tr><tr>';
     foreach my $item ('approve','email','username') {      foreach my $item ('approve','email','username') {
         $output .= '<td valign="top">';          $output .= '<td style="vertical-align: top">';
         my (%choices,@options,$hashref,$defoption,$name,$onclick,$hascustom);          my (%choices,@options,$hashref,$defoption,$name,$onclick,$hascustom);
         if ($item eq 'approve') {          if ($item eq 'approve') {
             %choices = &Apache::lonlocal::texthash (              %choices = &Apache::lonlocal::texthash (
Line 7822  sub noninst_users { Line 9899  sub noninst_users {
                     my $value;                      my $value;
                     if (ref($emaildomain) eq 'HASH') {                      if (ref($emaildomain) eq 'HASH') {
                         if (ref($emaildomain->{$type}) eq 'HASH') {                          if (ref($emaildomain->{$type}) eq 'HASH') {
                             $value = $emaildomain->{$type}->{$option};                              $value = $emaildomain->{$type}->{$option}; 
                         }                          }
                     }                      }
                     if ($value eq '') {                      if ($value eq '') {
Line 7849  sub noninst_users { Line 9926  sub noninst_users {
 sub captcha_choice {  sub captcha_choice {
     my ($context,$settings,$itemcount,$customcss,$rowstyle) = @_;      my ($context,$settings,$itemcount,$customcss,$rowstyle) = @_;
     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;      my $colspan=2;
Line 8031  sub authtype_names { Line 10108  sub authtype_names {
                       krb4   => 'Kerberos 4',                        krb4   => 'Kerberos 4',
                       krb5   => 'Kerberos 5',                        krb5   => 'Kerberos 5',
                       loc    => 'Local',                        loc    => 'Local',
                         lti    => 'LTI',
                   );                    );
     return %lt;      return %lt;
 }  }
Line 8099  sub print_defaults { Line 10177  sub print_defaults {
                           '<td><span class="LC_nobreak">'.$titles->{$item}.                            '<td><span class="LC_nobreak">'.$titles->{$item}.
                           '</span></td><td class="LC_right_item" colspan="3">';                            '</span></td><td class="LC_right_item" colspan="3">';
             if ($item eq 'auth_def') {              if ($item eq 'auth_def') {
                 my @authtypes = ('internal','krb4','krb5','localauth');                  my @authtypes = ('internal','krb4','krb5','localauth','lti');
                 my %shortauth = (                  my %shortauth = (
                                  internal => 'int',                                   internal => 'int',
                                  krb4 => 'krb4',                                   krb4 => 'krb4',
                                  krb5 => 'krb5',                                   krb5 => 'krb5',
                                  localauth  => 'loc'                                   localauth  => 'loc',
                                    lti => 'lti',
                                 );                                  );
                 my %authnames = &authtype_names();                  my %authnames = &authtype_names();
                 foreach my $auth (@authtypes) {                  foreach my $auth (@authtypes) {
Line 8160  sub print_defaults { Line 10239  sub print_defaults {
                     $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" colspan="2"><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></tr>';
                 }                  }
Line 8179  sub print_defaults { Line 10258  sub print_defaults {
                 $datatable .= '</select>&nbsp;'.&mt('Internal ID:').                  $datatable .= '</select>&nbsp;'.&mt('Internal ID:').
                               '<input type="text" size="10" name="addinststatus" value="" />'.                                '<input type="text" size="10" name="addinststatus" value="" />'.
                               '&nbsp;'.&mt('(new)').                                '&nbsp;'.&mt('(new)').
                               '</span></td><td class="LC_left_item"><span class="LC_nobreak">'.                                '</span></td><td class="LC_left_item" colspan="2"><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>'.
                               '</tr>'."\n";                                '</tr>'."\n";
Line 8396  sub print_scantronformat { Line 10475  sub print_scantronformat {
         }          }
         $datatable .= '</span></td>';          $datatable .= '</span></td>';
         if (keys(%error) == 0) {           if (keys(%error) == 0) { 
             $datatable .= '<td valign="bottom">';              $datatable .= '<td style="vertical-align: bottom">';
             if (!$switchserver) {              if (!$switchserver) {
                 $datatable .= &mt('Upload:').'<br />';                  $datatable .= &mt('Upload:').'<br />';
             }              }
Line 8631  sub print_coursecategories { Line 10710  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 8649  sub print_coursecategories { Line 10732  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 8689  sub print_coursecategories { Line 10783  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 class="LC_odd_row">'.
                     '<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 8715  sub print_coursecategories { Line 10823  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 8741  sub print_coursecategories { Line 10852  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 8764  sub print_coursecategories { Line 10875  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 8796  sub print_coursecategories { Line 10907  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 8885  sub print_serverstatuses { Line 10996  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 {
Line 8951  $jstext Line 11062  $jstext
   
 ENDSCRIPT  ENDSCRIPT
     }      }
       return;
 }  }
   
 sub passwords_javascript {  sub passwords_javascript {
Line 9009  function warnIntPass(field) { Line 11121  function warnIntPass(field) {
         }          }
         if (field.value != '') {          if (field.value != '') {
             if (field.name == 'passwords_expire') {              if (field.name == 'passwords_expire') {
                 var regexpposnum=/^\\d+(|\\.\\d*)\$/;                  var regexpposnum=/^\\d+(|\\.\\d*)\$/; 
                 if (!regexpposnum.test(field.value)) {                  if (!regexpposnum.test(field.value)) {
                     alert('$intalert{passexp}');                      alert('$intalert{passexp}');
                     field.value = '';                      field.value = '';
Line 9065  sub coursecategories_javascript { Line 11177  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 9137  function categoryCheck(form) { Line 11251  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 9153  sub initialize_categories { Line 11271  sub initialize_categories {
     my %default_names = &Apache::lonlocal::texthash (      my %default_names = &Apache::lonlocal::texthash (
                       instcode    => 'Official courses (with institutional codes)',                        instcode    => 'Official courses (with institutional codes)',
                       communities => 'Communities',                        communities => 'Communities',
                         placement   => 'Placement Tests',
                         );                          );
     my $select0 = ' selected="selected"';      my %selnum = (
     my $select1 = '';                     instcode    => '0',
     foreach my $default ('instcode','communities') {                     communities => '1',
                      placement   => '2',
                    );
       my %selected;
       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') {          map { $selected{$selnum{$_}} = '' } keys(%selnum);
             $select1 = $select0;          $selected{$selnum{$default}} = ' selected="selected"';
             $select0 = '';  
         }  
         $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'          $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
                      .'<select name="'.$default.'_pos">'                       .'<select name="'.$default.'_pos"'.$chgstr.'>'
                      .'<option value="0"'.$select0.'>1</option>'                       .'<option value="0"'.$selected{'0'}.'>1</option>'
                      .'<option value="1"'.$select1.'>2</option>'                       .'<option value="1"'.$selected{'1'}.'>2</option>'
                      .'<option value="2">3</option></select>&nbsp;'                       .'<option value="2"'.$selected{'2'}.'>3</option>'
                        .'<option value="3">4</option></select>&nbsp;'
                      .$default_names{$default}                       .$default_names{$default}
                      .'</span></td><td><span class="LC_nobreak">'                       .'</span></td><td><span class="LC_nobreak">'
                      .'<label><input type="radio" name="'.$default.'" value="1" checked="checked" />'                       .'<label><input type="radio" name="'.$default.'" value="1" checked="checked" />'
Line 9182  sub initialize_categories { Line 11304  sub initialize_categories {
                   .'<select name="addcategory_pos"'.$chgstr.'>'                    .'<select name="addcategory_pos"'.$chgstr.'>'
                   .'<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">3</option>'
                     .'<option value="3" selected="selected">4</option></select>&nbsp;'
                   .&mt('Add category').'</span></td><td><span class="LC_nobreak">'.&mt('Name:')                    .&mt('Add category').'</span></td><td><span class="LC_nobreak">'.&mt('Name:')
                   .'&nbsp;<input type="text" size="20" name="addcategory_name" value="" /></span>'                    .'&nbsp;<input type="text" size="20" name="addcategory_name" value="" /></span>'
                   .'</td></tr>';                    .'</td></tr>';
Line 9273  sub build_category_rows { Line 11396  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) = @_;          $rowid,$customcss,$rowstyle,$itemdesc) = @_;
     my ($role,$rolename,$statustype);      my ($role,$rolename,$statustype);
     $role = $item;      $role = $item;
     if ($context eq 'cancreate') {      if ($context eq 'cancreate') {
Line 9294  sub modifiable_userdata_row { Line 11417  sub modifiable_userdata_row {
         } else {          } else {
             $rolename = $role;              $rolename = $role;
         }          }
       } elsif ($context eq 'lti') {
           $rolename = &mt('Institutional data used (if available)');
       } elsif ($context eq 'privacy') {
           $rolename = $itemdesc;
     } else {      } else {
         if ($role eq 'cr') {          if ($role eq 'cr') {
             $rolename = &mt('Custom role');              $rolename = &mt('Custom role');
Line 9331  sub modifiable_userdata_row { Line 11458  sub modifiable_userdata_row {
     if ($rowid) {      if ($rowid) {
         $rowid = ' id="'.$rowid.'"';          $rowid = ' id="'.$rowid.'"';
     }      }
   
     $output = '<tr '.$css_class.$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;
     my %checks;      my %checks;
       my %current;
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{$context}) eq 'HASH') {          my $hashref;
           if ($context eq 'lti') {
               if (ref($settings) eq 'HASH') {
                   $hashref = $settings->{'instdata'};
               }
           } elsif ($context eq 'privacy') {
               my ($key,$inner) = split(/_/,$role);
               if (ref($settings) eq 'HASH') {
                   if (ref($settings->{$key}) eq 'HASH') {
                       $hashref = $settings->{$key}->{$inner};
                   }
               }
           } elsif (ref($settings->{$context}) eq 'HASH') {
             if (ref($settings->{$context}->{$role}) eq 'HASH') {              if (ref($settings->{$context}->{$role}) eq 'HASH') {
                 my $hashref = $settings->{$context}->{$role};                  $hashref = $settings->{'lti_instdata'};
                 if ($role eq 'emailusername') {              }
                     if ($statustype) {              if ($role eq 'emailusername') {
                         if (ref($settings->{$context}->{$role}->{$statustype}) eq 'HASH') {                  if ($statustype) {
                             $hashref = $settings->{$context}->{$role}->{$statustype};                      if (ref($settings->{$context}->{$role}->{$statustype}) eq 'HASH') {
                             if (ref($hashref) eq 'HASH') {                           $hashref = $settings->{$context}->{$role}->{$statustype};
                                 foreach my $field (@fields) {  
                                     if ($hashref->{$field}) {  
                                         $checks{$field} = $hashref->{$field};  
                                     }  
                                 }  
                             }  
                         }  
                     }                      }
                 } else {                  }
                     if (ref($hashref) eq 'HASH') {              }
                         foreach my $field (@fields) {          }
                             if ($hashref->{$field}) {          if (ref($hashref) eq 'HASH') { 
                                 $checks{$field} = ' checked="checked" ';              foreach my $field (@fields) {
                             }                  if ($hashref->{$field}) {
                         }                      if ($role eq 'emailusername') {
                           $checks{$field} = $hashref->{$field};
                       } else {
                           $checks{$field} = ' checked="checked" ';
                     }                      }
                 }                  }
             }              }
         }          }
     }      }
    
     my $total = scalar(@fields);      my $total = scalar(@fields);
     for (my $i=0; $i<$total; $i++) {      for (my $i=0; $i<$total; $i++) {
         $rem = $i%($numinrow);          $rem = $i%($numinrow);
Line 9380  sub modifiable_userdata_row { Line 11515  sub modifiable_userdata_row {
         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 {              } elsif ($context eq 'privacy') {
                   if ($role =~ /^priv_(domain|course)$/) {
                       if (ref($settings) ne 'HASH') {
                           $check = ' checked="checked" ';
                       }
                   } elsif ($role =~ /^priv_(author|community)$/) {
                       if (ref($settings) ne 'HASH') {
                           unless ($fields[$i] eq 'id') {
                               $check = ' checked="checked" ';
                           }
                       }
                   } elsif ($role =~ /^(unpriv|othdom)_/) {
                       if (ref($settings) ne 'HASH') {
                           if (($fields[$i] eq 'lastname') || ($fields[$i] eq 'firstname')) {
                               $check = ' checked="checked" ';
                           }
                       }
                   }
               } elsif ($context ne 'lti') {
                 if ($role eq 'st') {                  if ($role eq 'st') {
                     if (ref($settings) ne 'HASH') {                      if (ref($settings) ne 'HASH') {
                         $check = ' checked="checked" ';                           $check = ' checked="checked" '; 
Line 9390  sub modifiable_userdata_row { Line 11543  sub modifiable_userdata_row {
         }          }
         $output .= '<td class="LC_left_item">'.          $output .= '<td class="LC_left_item">'.
                    '<span class="LC_nobreak">';                     '<span class="LC_nobreak">';
           my $prefix = 'canmodify';
         if ($role eq 'emailusername') {          if ($role eq 'emailusername') {
             unless ($checks{$fields[$i]} =~ /^(required|optional)$/) {              unless ($checks{$fields[$i]} =~ /^(required|optional)$/) {
                 $checks{$fields[$i]} = 'omit';                  $checks{$fields[$i]} = 'omit';
Line 9400  sub modifiable_userdata_row { Line 11554  sub modifiable_userdata_row {
                     $checked='checked="checked" ';                      $checked='checked="checked" ';
                 }                  }
                 $output .= '<label>'.                  $output .= '<label>'.
                            '<input type="radio" name="canmodify_'.$item.'_'.$fields[$i].'" value="'.$option.'" '.$checked.'/>'.                             '<input type="radio" name="'.$prefix.'_'.$item.'_'.$fields[$i].'" value="'.$option.'" '.$checked.'/>'.
                            &mt($option).'</label>'.('&nbsp;' x2);                             &mt($option).'</label>'.('&nbsp;' x2);
             }              }
             $output .= '<i>'.$fieldtitles{$fields[$i]}.'</i>';              $output .= '<i>'.$fieldtitles{$fields[$i]}.'</i>';
         } else {          } else {
               if ($context eq 'lti') {
                   $prefix = 'lti';
               } elsif ($context eq 'privacy') {
                   $prefix = 'privacy';
               }
             $output .= '<label>'.              $output .= '<label>'.
                        '<input type="checkbox" name="canmodify_'.$role.'" '.                         '<input type="checkbox" name="'.$prefix.'_'.$role.'" '.
                        'value="'.$fields[$i].'"'.$check.'/>'.$fieldtitles{$fields[$i]}.                         'value="'.$fields[$i].'"'.$check.'/>'.$fieldtitles{$fields[$i]}.
                        '</label>';                         '</label>';
         }          }
Line 9493  sub insttypes_row { Line 11652  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.$onclick.' />'.
                            $usertypes->{$types->[$i]}.'</label></span></td>';                             $usertypes->{$types->[$i]}.'</label></span></td>';
             }              }
         }          }
Line 9506  sub insttypes_row { Line 11665  sub insttypes_row {
         } else {          } else {
             $output .= '<td class="LC_left_item">';              $output .= '<td class="LC_left_item">';
         }          }
         $output .= '&nbsp;';          $output .= '&nbsp;';  
     } else {      } else {
         if ($rem == 0) {          if ($rem == 0) {
             $output .= '<tr>';              $output .= '<tr>';
Line 9921  sub modify_login { Line 12080  sub modify_login {
                 $currsaml{$lonhost}{$item} = $env{'form.saml_'.$item.'_'.$lonhost};                  $currsaml{$lonhost}{$item} = $env{'form.saml_'.$item.'_'.$lonhost};
             }              }
         } else {          } else {
             if ($saml{$lonhost}) {              if ($saml{$lonhost}) {  
                 $changes{'saml'}{$lonhost} = 1;                  $changes{'saml'}{$lonhost} = 1;
                 delete($currsaml{$lonhost});                  delete($currsaml{$lonhost});
             }              }
         }          }
     }      }
     foreach my $posshost (keys(%currsaml)) {      foreach my $posshost (keys(%currsaml)) {
         unless (exists($domservers{$posshost})) {          unless (exists($domservers{$posshost})) { 
             delete($currsaml{$posshost});              delete($currsaml{$posshost}); 
         }          }
     }      }
     %{$loginhash{'login'}{'saml'}} = %currsaml;      %{$loginhash{'login'}{'saml'}} = %currsaml;
Line 10306  sub modify_ipaccess { Line 12465  sub modify_ipaccess {
             $possrange =~ s/,+/,/g;              $possrange =~ s/,+/,/g;
             if ($possrange ne '') {              if ($possrange ne '') {
                 my (@ok,$count);                  my (@ok,$count);
                 $count = 0;                  $count = 0; 
                 foreach my $poss (split(/\,/,$possrange)) {                  foreach my $poss (split(/\,/,$possrange)) {
                     $count ++;                      $count ++;
                     $poss = &validate_ip_pattern($poss);                      $poss = &validate_ip_pattern($poss);
Line 10339  sub modify_ipaccess { Line 12498  sub modify_ipaccess {
             }              }
         }          }
         $confhash{$itemid}{'commblocks'} = {};          $confhash{$itemid}{'commblocks'} = {};
            
         my %commblocks;          my %commblocks;
         map { $commblocks{$_} = 1; } &Apache::loncommon::get_env_multiple('form.ipaccess_block_'.$idx);          map { $commblocks{$_} = 1; } &Apache::loncommon::get_env_multiple('form.ipaccess_block_'.$idx);  
         foreach my $type (@{$typeorder}) {          foreach my $type (@{$typeorder}) {
             if ($commblocks{$type}) {              if ($commblocks{$type}) {
                 $confhash{$itemid}{'commblocks'}{$type} = 'on';                  $confhash{$itemid}{'commblocks'}{$type} = 'on';
Line 10373  sub modify_ipaccess { Line 12532  sub modify_ipaccess {
         }          }
         $env{'form.ipaccess_cnum_'.$idx} =~ s/^\s+|\s+$//g;          $env{'form.ipaccess_cnum_'.$idx} =~ s/^\s+|\s+$//g;
         $env{'form.ipaccess_cdom_'.$idx} =~ s/^\s+|\s+$//g;          $env{'form.ipaccess_cdom_'.$idx} =~ s/^\s+|\s+$//g;
         if (($env{'form.ipaccess_cnum_'.$idx} =~ /^$match_courseid$/) &&          if (($env{'form.ipaccess_cnum_'.$idx} =~ /^$match_courseid$/) && 
             ($env{'form.ipaccess_cdom_'.$idx} =~ /^$match_domain$/)) {              ($env{'form.ipaccess_cdom_'.$idx} =~ /^$match_domain$/)) {
             if (&Apache::lonnet::homeserver($env{'form.ipaccess_cnum_'.$idx},              if (&Apache::lonnet::homeserver($env{'form.ipaccess_cnum_'.$idx},
                                             $env{'form.ipaccess_cdom_'.$idx}) eq 'no_host') {                                              $env{'form.ipaccess_cdom_'.$idx}) eq 'no_host') {
Line 10453  sub modify_ipaccess { Line 12612  sub modify_ipaccess {
                     if (keys(%{$confhash{$itemid}{'courses'}})) {                      if (keys(%{$confhash{$itemid}{'courses'}})) {
                         my @courses;                          my @courses;
                         foreach my $cid (sort(keys(%{$confhash{$itemid}{'courses'}}))) {                          foreach my $cid (sort(keys(%{$confhash{$itemid}{'courses'}}))) {
                             my %courseinfo = &Apache::lonnet::coursedescription($cid,{'one_time' => 1});                              my %courseinfo = &Apache::lonnet::coursedescription($cid,{'one_time' => 1}); 
                             push(@courses,$courseinfo{'description'}.' ('.$cid.')');                              push(@courses,$courseinfo{'description'}.' ('.$cid.')');
                         }                          }
                         $resulttext .= '<li>'.&mt('Courses/Communities allowed').':<ul><li>'.                          $resulttext .= '<li>'.&mt('Courses/Communities allowed').':<ul><li>'.
Line 10871  sub display_colorchgs { Line 13030  sub display_colorchgs {
                         } else {                          } else {
                             my $newitem = $confhash->{$role}{$item};                              my $newitem = $confhash->{$role}{$item};
                             if ($key eq 'images') {                              if ($key eq 'images') {
                                 $newitem = '<img src="'.$confhash->{$role}{$item}.'" alt="'.$choices{$item}.'" valign="bottom" />';                                  $newitem = '<img src="'.$confhash->{$role}{$item}.'" alt="'.$choices{$item}.'" style="vertical-align: bottom" />';
                             }                              }
                             $resulttext .= '<li>'.&mt("$choices{$item} set to [_1]",$newitem).'</li>';                              $resulttext .= '<li>'.&mt("$choices{$item} set to [_1]",$newitem).'</li>';
                         }                          }
Line 10953  sub check_authorstatus { Line 13112  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 11082  $env{'user.name'}.':'.$env{'user.domain' Line 13241  $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 11094  $env{'user.name'}.':'.$env{'user.domain' Line 13254  $env{'user.name'}.':'.$env{'user.domain'
             $output = $versionresult;              $output = $versionresult;
         }          }
     }      }
     return ($output,$logourl);      return ($output,$logourl,$madethumb);
 }  }
   
 sub logo_versioning {  sub logo_versioning {
Line 11248  sub modify_quotas { Line 13408  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','lti');
         @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 11297  sub modify_quotas { Line 13457  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','lti');
         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 11419  sub modify_quotas { Line 13579  sub modify_quotas {
                                             &Apache::lonnet::logthis($error);                                              &Apache::lonnet::logthis($error);
                                             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';                                              $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'} = 
                                         $domconfig{$action}{$type}{$key}{'image'};                                          $domconfig{$action}{$type}{$key}{'image'};
Line 11984  sub modify_ltitools { Line 14144  sub modify_ltitools {
     map { $posslti{$_} = 1; } @ltiroles;      map { $posslti{$_} = 1; } @ltiroles;
     my @allfields = ('fullname','firstname','lastname','email','user','roles');      my @allfields = ('fullname','firstname','lastname','email','user','roles');
     map { $possfield{$_} = 1; } @allfields;      map { $possfield{$_} = 1; } @allfields;
     my %lt = &ltitools_names();      my %lt = &ltitools_names(); 
     if ($env{'form.ltitools_add'}) {      if ($env{'form.ltitools_add'}) {
         my $title = $env{'form.ltitools_add_title'};          my $title = $env{'form.ltitools_add_title'};
         $title =~ s/(`)/'/g;          $title =~ s/(`)/'/g;
Line 12029  sub modify_ltitools { Line 14189  sub modify_ltitools {
                     }                      }
                 } else {                  } else {
                     if ($env{'form.ltitools_add_'.$item} ne '') {                      if ($env{'form.ltitools_add_'.$item} ne '') {
                         $confhash{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item};                          $confhash{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item}; 
                     }                      }
                 }                  }
             }              }
Line 12040  sub modify_ltitools { Line 14200  sub modify_ltitools {
             } else {              } else {
                 $confhash{$newid}{'display'}{'target'} = 'iframe';                  $confhash{$newid}{'display'}{'target'} = 'iframe';
             }              }
               foreach my $item ('passback','roster') {
                   if ($env{'form.ltitools_'.$item.'_add'}) {
                       $confhash{$newid}{$item} = 1;
                       if ($env{'form.ltitools_'.$item.'valid_add'} ne '') {
                           my $lifetime = $env{'form.ltitools_'.$item.'valid_add'};
                           $lifetime =~ s/^\s+|\s+$//g;
                           if ($lifetime =~ /^\d+\.?\d*$/) {
                               $confhash{$newid}{$item.'valid'} = $lifetime;
                           }
                       }
                   }
               }
             if ($env{'form.ltitools_add_image.filename'} ne '') {              if ($env{'form.ltitools_add_image.filename'} ne '') {
                 my ($imageurl,$error) =                  my ($imageurl,$error) =
                     &process_ltitools_image($r,$dom,$confname,'ltitools_add_image',$newid,                      &process_ltitools_image($r,$dom,$confname,'ltitools_add_image',$newid,
Line 12061  sub modify_ltitools { Line 14233  sub modify_ltitools {
                             if (($choice ne '') && ($posslti{$choice})) {                              if (($choice ne '') && ($posslti{$choice})) {
                                 $confhash{$newid}{'roles'}{$role} = $choice;                                  $confhash{$newid}{'roles'}{$role} = $choice;
                                 if ($role eq 'cc') {                                  if ($role eq 'cc') {
                                     $confhash{$newid}{'roles'}{'co'} = $choice;                                      $confhash{$newid}{'roles'}{'co'} = $choice; 
                                 }                                  }
                             }                              }
                         }                          }
Line 12089  sub modify_ltitools { Line 14261  sub modify_ltitools {
                 $confhash{$newid}{'custom'}{$name} = $value;                  $confhash{$newid}{'custom'}{$name} = $value;
             }              }
         } else {          } else {
             my $error = &mt('Failed to acquire unique ID for new external tool');              my $error = &mt('Failed to acquire unique ID for new external tool');   
             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';              $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
         }          }
     }      }
Line 12103  sub modify_ltitools { Line 14275  sub modify_ltitools {
         my @newcustom = &Apache::loncommon::get_env_multiple('form.ltitools_customadd');          my @newcustom = &Apache::loncommon::get_env_multiple('form.ltitools_customadd');
         if (@newcustom) {          if (@newcustom) {
             map { $customadds{$_} = 1; } @newcustom;              map { $customadds{$_} = 1; } @newcustom;
         }          } 
         my %imgdeletions;          my %imgdeletions;
         my @todeleteimages = &Apache::loncommon::get_env_multiple('form.ltitools_image_del');          my @todeleteimages = &Apache::loncommon::get_env_multiple('form.ltitools_image_del');
         if (@todeleteimages) {          if (@todeleteimages) {
Line 12144  sub modify_ltitools { Line 14316  sub modify_ltitools {
                     if ($env{'form.ltitools_sigmethod_'.$i} eq 'HMAC-SHA256') {                      if ($env{'form.ltitools_sigmethod_'.$i} eq 'HMAC-SHA256') {
                         $confhash{$itemid}{'sigmethod'} = $env{'form.ltitools_sigmethod_'.$i};                          $confhash{$itemid}{'sigmethod'} = $env{'form.ltitools_sigmethod_'.$i};
                     } else {                      } else {
                         $confhash{$itemid}{'sigmethod'} = 'HMAC-SHA1';                          $confhash{$itemid}{'sigmethod'} = 'HMAC-SHA1'; 
                     }                      }
                     if ($domconfig{$action}{$itemid}{'sigmethod'} eq '') {                      if ($domconfig{$action}{$itemid}{'sigmethod'} eq '') {
                         if ($confhash{$itemid}{'sigmethod'} ne 'HMAC-SHA1') {                          if ($confhash{$itemid}{'sigmethod'} ne 'HMAC-SHA1') {
Line 12203  sub modify_ltitools { Line 14375  sub modify_ltitools {
                     } else {                      } else {
                         $changes{$itemid} = 1;                          $changes{$itemid} = 1;
                     }                      }
                       foreach my $extra ('passback','roster') {
                           if ($env{'form.ltitools_'.$extra.'_'.$i}) {
                               $confhash{$itemid}{$extra} = 1;
                               if ($env{'form.ltitools_'.$extra.'valid_'.$i} ne '') {
                                   my $lifetime = $env{'form.ltitools_'.$extra.'valid_'.$i};
                                   $lifetime =~ s/^\s+|\s+$//g;
                                   if ($lifetime =~ /^\d+\.?\d*$/) {
                                       $confhash{$itemid}{$extra.'valid'} = $lifetime;
                                   }
                               }
                           }
                           if ($domconfig{$action}{$itemid}{$extra} ne $confhash{$itemid}{$extra}) {
                               $changes{$itemid} = 1;
                           }
                           if ($domconfig{$action}{$itemid}{$extra.'valid'} ne $confhash{$itemid}{$extra.'valid'}) {
                               $changes{$itemid} = 1;
                           }
                       }
                     my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig_'.$i);                      my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig_'.$i);
                     foreach my $item ('label','title','target','linktext','explanation','append') {                      foreach my $item ('label','title','target','linktext','explanation','append') {
                         if (grep(/^\Q$item\E$/,@courseconfig)) {                          if (grep(/^\Q$item\E$/,@courseconfig)) {
Line 12294  sub modify_ltitools { Line 14484  sub modify_ltitools {
                     }                      }
                 }                  }
                 my %customdels;                  my %customdels;
                 my @customdeletions = &Apache::loncommon::get_env_multiple('form.ltitools_customdel_'.$i);                  my @customdeletions = &Apache::loncommon::get_env_multiple('form.ltitools_customdel_'.$i); 
                 if (@customdeletions) {                  if (@customdeletions) {
                     $changes{$itemid} = 1;                      $changes{$itemid} = 1;
                 }                  }
Line 12303  sub modify_ltitools { Line 14493  sub modify_ltitools {
                     foreach my $key (keys(%{$domconfig{$action}{$itemid}{'custom'}})) {                      foreach my $key (keys(%{$domconfig{$action}{$itemid}{'custom'}})) {
                         unless ($customdels{$key}) {                          unless ($customdels{$key}) {
                             if ($env{'form.ltitools_customval_'.$key.'_'.$i} ne '') {                              if ($env{'form.ltitools_customval_'.$key.'_'.$i} ne '') {
                                 $confhash{$itemid}{'custom'}{$key} = $env{'form.ltitools_customval_'.$key.'_'.$i};                                  $confhash{$itemid}{'custom'}{$key} = $env{'form.ltitools_customval_'.$key.'_'.$i}; 
                             }                              }
                             if ($domconfig{$action}{$itemid}{'custom'}{$key} ne $env{'form.ltitools_customval_'.$key.'_'.$i}) {                              if ($domconfig{$action}{$itemid}{'custom'}{$key} ne $env{'form.ltitools_customval_'.$key.'_'.$i}) {
                                 $changes{$itemid} = 1;                                  $changes{$itemid} = 1;
Line 12378  sub modify_ltitools { Line 14568  sub modify_ltitools {
                 $bynum{$position} = $itemid;                  $bynum{$position} = $itemid;
             }              }
             foreach my $pos (sort { $a <=> $b } keys(%bynum)) {              foreach my $pos (sort { $a <=> $b } keys(%bynum)) {
                 my $itemid = $bynum{$pos};                  my $itemid = $bynum{$pos}; 
                 if (ref($confhash{$itemid}) ne 'HASH') {                  if (ref($confhash{$itemid}) ne 'HASH') {
                     $resulttext .= '<li>'.&mt('Deleted: [_1]',$changes{$itemid}).'</li>';                      $resulttext .= '<li>'.&mt('Deleted: [_1]',$changes{$itemid}).'</li>';
                 } else {                  } else {
Line 12406  sub modify_ltitools { Line 14596  sub modify_ltitools {
                     }                      }
                     $resulttext .= '<li>'.&mt('Configurable in course:');                      $resulttext .= '<li>'.&mt('Configurable in course:');
                     my @possconfig = ('label','title','target','linktext','explanation','append');                      my @possconfig = ('label','title','target','linktext','explanation','append');
                     my $numconfig = 0;                      my $numconfig = 0; 
                     if (ref($confhash{$itemid}{'crsconf'}) eq 'HASH') {                      if (ref($confhash{$itemid}{'crsconf'}) eq 'HASH') { 
                         foreach my $item (@possconfig) {                          foreach my $item (@possconfig) {
                             if ($confhash{$itemid}{'crsconf'}{$item}) {                              if ($confhash{$itemid}{'crsconf'}{$item}) {
                                 $numconfig ++;                                  $numconfig ++;
Line 12416  sub modify_ltitools { Line 14606  sub modify_ltitools {
                         }                          }
                     }                      }
                     if (!$numconfig) {                      if (!$numconfig) {
                         $resulttext .= &mt('None');                          $resulttext .= '&nbsp;'.&mt('None');
                     }                      }
                     $resulttext .= '</li>';                      $resulttext .= '</li>';
                       foreach my $item ('passback','roster') {
                           $resulttext .= '<li>'.$lt{$item}.'&nbsp;';
                           if ($confhash{$itemid}{$item}) {
                               $resulttext .= &mt('Yes');
                               if ($confhash{$itemid}{$item.'valid'}) {
                                   if ($item eq 'passback') {
                                       $resulttext .= ' '.&mt('valid for at least [quant,_1,day] after launch',
                                                              $confhash{$itemid}{$item.'valid'});
                                   } else {
                                       $resulttext .= ' '.&mt('valid for at least [quant,_1,second] after launch',
                                                              $confhash{$itemid}{$item.'valid'});
                                   }
                               }
                           } else {
                               $resulttext .= &mt('No');
                           }
                           $resulttext .= '</li>';
                       }
                     if (ref($confhash{$itemid}{'display'}) eq 'HASH') {                      if (ref($confhash{$itemid}{'display'}) eq 'HASH') {
                         my $displaylist;                          my $displaylist;
                         if ($confhash{$itemid}{'display'}{'target'}) {                          if ($confhash{$itemid}{'display'}{'target'}) {
                             $displaylist = &mt('Display target').':&nbsp;'.                              $displaylist = &mt('Display target').':&nbsp;'.
                                            $confhash{$itemid}{'display'}{'target'}.',';                                             $confhash{$itemid}{'display'}{'target'}.',';
                         }                          }
                         foreach my $size ('width','height') {                          foreach my $size ('width','height') { 
                             if ($confhash{$itemid}{'display'}{$size}) {                              if ($confhash{$itemid}{'display'}{$size}) {
                                 $displaylist .= ('&nbsp;'x2).$lt{$size}.':&nbsp;'.                                  $displaylist .= ('&nbsp;'x2).$lt{$size}.':&nbsp;'.
                                                 $confhash{$itemid}{'display'}{$size}.',';                                                  $confhash{$itemid}{'display'}{$size}.',';
Line 12469  sub modify_ltitools { Line 14677  sub modify_ltitools {
                             }                              }
                         }                          }
                         if ($rolemaps) {                          if ($rolemaps) {
                             $rolemaps =~ s/,$//;                              $rolemaps =~ s/,$//; 
                             $resulttext .= '<li>'.&mt('Role mapping:').$rolemaps.'</li>';                              $resulttext .= '<li>'.&mt('Role mapping:').$rolemaps.'</li>';
                         }                          }
                     }                      }
Line 12478  sub modify_ltitools { Line 14686  sub modify_ltitools {
                         if (keys(%{$confhash{$itemid}{'custom'}})) {                          if (keys(%{$confhash{$itemid}{'custom'}})) {
                             foreach my $key (sort(keys(%{$confhash{$itemid}{'custom'}}))) {                              foreach my $key (sort(keys(%{$confhash{$itemid}{'custom'}}))) {
                                 $customlist .= $key.':'.$confhash{$itemid}{'custom'}{$key}.('&nbsp;'x2);                                  $customlist .= $key.':'.$confhash{$itemid}{'custom'}{$key}.('&nbsp;'x2);
                             }                              } 
                         }                          }
                         if ($customlist) {                          if ($customlist) {
                             $resulttext .= '<li>'.&mt('Custom items').': '.$customlist.'</li>';                              $resulttext .= '<li>'.&mt('Custom items').': '.$customlist.'</li>';
                         }                          }
                     }                      } 
                     $resulttext .= '</ul></li>';                      $resulttext .= '</ul></li>';
                 }                  }
             }              }
Line 12544  sub get_ltitools_id { Line 14752  sub get_ltitools_id {
     my $tries = 0;      my $tries = 0;
     my $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);      my $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
     my ($id,$error);      my ($id,$error);
    
     while (($gotlock ne 'ok') && ($tries<10)) {      while (($gotlock ne 'ok') && ($tries<10)) {
         $tries ++;          $tries ++;
         sleep (0.1);          sleep (0.1);
Line 12577  sub get_ltitools_id { Line 14785  sub get_ltitools_id {
     return ($id,$error);      return ($id,$error);
 }  }
   
   sub modify_proctoring {
       my ($r,$dom,$action,$lastactref,%domconfig) = @_;
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
       my (@allpos,%changes,%confhash,%encconfhash,$errors,$resulttext,%imgdeletions);
       my $confname = $dom.'-domainconfig';
       my $servadm = $r->dir_config('lonAdmEMail');
       my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
       my %providernames = &proctoring_providernames();
       my $maxnum = scalar(keys(%providernames));
   
       my (%requserfields,%optuserfields,%defaults,%extended,%crsconf,@courseroles,@ltiroles);
       my ($requref,$opturef,$defref,$extref,$crsref,$rolesref,$ltiref) = &proctoring_data();
       if (ref($requref) eq 'HASH') {
           %requserfields = %{$requref};
       }
       if (ref($opturef) eq 'HASH') {
           %optuserfields = %{$opturef};
       }
       if (ref($defref) eq 'HASH') {
           %defaults = %{$defref};
       }
       if (ref($extref) eq 'HASH') {
           %extended = %{$extref};
       }
       if (ref($crsref) eq 'HASH') {
           %crsconf = %{$crsref};
       }
       if (ref($rolesref) eq 'ARRAY') {
           @courseroles = @{$rolesref};
       }
       if (ref($ltiref) eq 'ARRAY') {
           @ltiroles = @{$ltiref};
       }
   
       if (ref($domconfig{$action}) eq 'HASH') {
           my @todeleteimages = &Apache::loncommon::get_env_multiple('form.proctoring_image_del');
           if (@todeleteimages) {
               map { $imgdeletions{$_} = 1; } @todeleteimages;
           }
       }
       my %customadds;
       my @newcustom = &Apache::loncommon::get_env_multiple('form.proctoring_customadd');
       if (@newcustom) {
           map { $customadds{$_} = 1; } @newcustom;
       }
       foreach my $provider (sort(keys(%providernames))) {
           $confhash{$provider} = {};
           my $pos = $env{'form.proctoring_pos_'.$provider};
           $pos =~ s/\D+//g;
           $allpos[$pos] = $provider;
           my (%current,%currentenc);
           my $showroles = 0;
           if (ref($domconfig{$action}) eq 'HASH') {
               if (ref($domconfig{$action}{$provider}) eq 'HASH') {
                   %current = %{$domconfig{$action}{$provider}};
                   foreach my $item ('key','secret') { 
                       $currentenc{$item} = $current{$item};
                       delete($current{$item});
                   }
               }
           }
           if ($env{'form.proctoring_available_'.$provider}) {
               $confhash{$provider}{'available'} = 1;
               unless ($current{'available'}) {
                   $changes{$provider} = 1;
               }
           } else {
               %{$confhash{$provider}} = %current;
               %{$encconfhash{$provider}} = %currentenc;
               $confhash{$provider}{'available'} = 0;
               if ($current{'available'}) {
                   $changes{$provider} = 1;
               }
           }
           if ($confhash{$provider}{'available'}) {
               foreach my $field ('lifetime','version','sigmethod','url','key','secret') {
                   my $possval = $env{'form.proctoring_'.$provider.'_'.$field};
                   if ($field eq 'lifetime') {
                       if ($possval =~ /^\d+$/) {
                           $confhash{$provider}{$field} = $possval;
                       }
                   } elsif ($field eq 'version') {
                       if ($possval =~ /^\d+\.\d+$/) {
                           $confhash{$provider}{$field} = $possval;
                       }
                   } elsif ($field eq 'sigmethod') {
                       if ($possval =~ /^\QHMAC-SHA\E(1|256)$/) {
                           $confhash{$provider}{$field} = $possval;
                       }
                   } elsif ($field eq 'url') {
                       $confhash{$provider}{$field} = $possval;
                   } elsif (($field eq 'key') || ($field eq 'secret')) {
                       $encconfhash{$provider}{$field} = $possval;
                       unless ($currentenc{$field} eq $possval) {
                           $changes{$provider} = 1;
                       }
                   }
                   unless (($field eq 'key') || ($field eq 'secret')) {
                       unless ($current{$field} eq $confhash{$provider}{$field}) {
                           $changes{$provider} = 1;
                       }
                   }
               }
               if ($imgdeletions{$provider}) {
                   $changes{$provider} = 1;
               } elsif ($env{'form.proctoring_image_'.$provider.'.filename'} ne '') {
                   my ($imageurl,$error) =
                       &process_proctoring_image($r,$dom,$confname,'proctoring_image_'.$provider,$provider,
                                                 $configuserok,$switchserver,$author_ok);
                   if ($imageurl) {
                       $confhash{$provider}{'image'} = $imageurl;
                       $changes{$provider} = 1; 
                   }
                   if ($error) {
                       &Apache::lonnet::logthis($error);
                       $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                   }
               } elsif (exists($current{'image'})) {
                   $confhash{$provider}{'image'} = $current{'image'};
               }
               if (ref($requserfields{$provider}) eq 'ARRAY') {
                   if (@{$requserfields{$provider}} > 0) {
                       if (grep(/^user$/,@{$requserfields{$provider}})) {
                           if ($env{'form.proctoring_userincdom_'.$provider}) {
                               $confhash{$provider}{'incdom'} = 1;
                           }
                           unless ($current{'incdom'} eq $confhash{$provider}{'incdom'}) {
                               $changes{$provider} = 1;
                           }
                       }
                       if (grep(/^roles$/,@{$requserfields{$provider}})) {
                           $showroles = 1;
                       }
                   }
               }
               $confhash{$provider}{'fields'} = [];
               if (ref($optuserfields{$provider}) eq 'ARRAY') {
                   if (@{$optuserfields{$provider}} > 0) {
                       my @optfields = &Apache::loncommon::get_env_multiple('form.proctoring_optional_'.$provider);
                       foreach my $field (@{$optuserfields{$provider}}) {
                           if (grep(/^\Q$field\E$/,@optfields)) {
                               push(@{$confhash{$provider}{'fields'}},$field);
                           }
                       }
                   }
                   if (ref($current{'fields'}) eq 'ARRAY') {
                       unless ($changes{$provider}) {
                           my @new = sort(@{$confhash{$provider}{'fields'}});
                           my @old = sort(@{$current{'fields'}}); 
                           my @diffs = &Apache::loncommon::compare_arrays(\@new,\@old);
                           if (@diffs) {
                               $changes{$provider} = 1;
                           }
                       }
                   } elsif (@{$confhash{$provider}{'fields'}}) {
                       $changes{$provider} = 1;
                   }
               }
               if (ref($defaults{$provider}) eq 'ARRAY') {  
                   if (@{$defaults{$provider}} > 0) {
                       my %options;
                       if (ref($extended{$provider}) eq 'HASH') {
                           %options = %{$extended{$provider}};
                       }
                       my @checked = &Apache::loncommon::get_env_multiple('form.proctoring_defaults_'.$provider);
                       foreach my $field (@{$defaults{$provider}}) {
                           if ((exists($options{$field})) && (ref($options{$field}) eq 'ARRAY')) {
                               my $poss = $env{'form.proctoring_defaults_'.$field.'_'.$provider};
                               if (grep(/^\Q$poss\E$/,@{$options{$field}})) {
                                   push(@{$confhash{$provider}{'defaults'}},$poss); 
                               }
                           } elsif ((exists($options{$field})) && (ref($options{$field}) eq 'HASH')) {
                               foreach my $inner (keys(%{$options{$field}})) {
                                   if (ref($options{$field}{$inner}) eq 'ARRAY') {
                                       my $poss = $env{'form.proctoring_'.$inner.'_'.$provider};
                                       if (grep(/^\Q$poss\E$/,@{$options{$field}{$inner}})) {
                                           $confhash{$provider}{'defaults'}{$inner} = $poss;
                                       }
                                   } else {
                                       $confhash{$provider}{'defaults'}{$inner} = $env{'form.proctoring_'.$inner.'_'.$provider};
                                   }
                               }
                           } else {
                               if (grep(/^\Q$field\E$/,@checked)) {
                                   push(@{$confhash{$provider}{'defaults'}},$field);
                               }
                           }
                       }
                       if (ref($confhash{$provider}{'defaults'}) eq 'ARRAY') {
                           if (ref($current{'defaults'}) eq 'ARRAY') {
                               unless ($changes{$provider}) {
                                   my @new = sort(@{$confhash{$provider}{'defaults'}});
                                   my @old = sort(@{$current{'defaults'}});
                                   my @diffs = &Apache::loncommon::compare_arrays(\@new,\@old);
                                   if (@diffs) {
                                       $changes{$provider} = 1; 
                                   }
                               }
                           } elsif (ref($current{'defaults'}) eq 'ARRAY') {
                               if (@{$current{'defaults'}}) {
                                   $changes{$provider} = 1;
                               }
                           }
                       } elsif (ref($confhash{$provider}{'defaults'}) eq 'HASH') {
                           if (ref($current{'defaults'}) eq 'HASH') {
                               unless ($changes{$provider}) {
                                   foreach my $key (keys(%{$confhash{$provider}{'defaults'}})) {
                                       unless ($confhash{$provider}{'defaults'}{$key} eq $current{'defaults'}{$key}) {
                                           $changes{$provider} = 1;
                                           last;
                                       }
                                   }
                               }
                               unless ($changes{$provider}) {
                                   foreach my $key (keys(%{$current{'defaults'}})) {
                                       unless ($current{'defaults'}{$key} eq $confhash{$provider}{'defaults'}{$key}) {
                                           $changes{$provider} = 1;
                                           last;
                                       }
                                   }
                               }
                           } elsif (keys(%{$confhash{$provider}{'defaults'}})) {
                               $changes{$provider} = 1;
                           }
                       }
                   }
               }
               if (ref($crsconf{$provider}) eq 'ARRAY') {
                   if (@{$crsconf{$provider}} > 0) {
                       $confhash{$provider}{'crsconf'} = [];
                       my @checked = &Apache::loncommon::get_env_multiple('form.proctoring_crsconf_'.$provider);
                       foreach my $crsfield (@{$crsconf{$provider}}) {
                           if (grep(/^\Q$crsfield\E$/,@checked)) {
                               push(@{$confhash{$provider}{'crsconf'}},$crsfield);
                           }
                       }
                       if (ref($current{'crsconf'}) eq 'ARRAY') {
                           unless ($changes{$provider}) {  
                               my @new = sort(@{$confhash{$provider}{'crsconf'}});
                               my @old = sort(@{$current{'crsconf'}});
                               my @diffs = &Apache::loncommon::compare_arrays(\@new,\@old);
                               if (@diffs) {
                                   $changes{$provider} = 1;
                               }
                           }
                       } elsif (@{$confhash{$provider}{'crsconf'}}) {
                           $changes{$provider} = 1;
                       }
                   }
               }
               if ($showroles) {
                   $confhash{$provider}{'roles'} = {};
                   foreach my $role (@courseroles) {
                       my $poss = $env{'form.proctoring_roles_'.$role.'_'.$provider};
                       if (grep(/^\Q$poss\E$/,@ltiroles)) {
                           $confhash{$provider}{'roles'}{$role} = $poss;
                       }
                   }
                   unless ($changes{$provider}) {
                       if (ref($current{'roles'}) eq 'HASH') {
                           foreach my $role (keys(%{$current{'roles'}})) {
                               unless ($current{'roles'}{$role} eq $confhash{$provider}{'roles'}{$role}) {
                                   $changes{$provider} = 1;
                                   last
                               }
                           }
                           unless ($changes{$provider}) {
                               foreach my $role (keys(%{$confhash{$provider}{'roles'}})) {
                                   unless ($confhash{$provider}{'roles'}{$role} eq $current{'roles'}{$role}) {
                                       $changes{$provider} = 1;
                                       last;
                                   }
                               }
                           }
                       } elsif (keys(%{$confhash{$provider}{'roles'}})) {
                           $changes{$provider} = 1;
                       }
                   }
               }
               if (ref($current{'custom'}) eq 'HASH') {
                   my @customdels = &Apache::loncommon::get_env_multiple('form.proctoring_customdel_'.$provider);
                   foreach my $key (keys(%{$current{'custom'}})) {
                       if (grep(/^\Q$key\E$/,@customdels)) {
                           $changes{$provider} = 1;
                       } else {
                           $confhash{$provider}{'custom'}{$key} = $env{'form.proctoring_customval_'.$key.'_'.$provider};
                           if ($confhash{$provider}{'custom'}{$key} ne $current{'custom'}{$key}) {
                               $changes{$provider} = 1;
                           }
                       }
                   }
               }
               if ($customadds{$provider}) {
                   my $name = $env{'form.proctoring_custom_name_'.$provider};
                   $name =~ s/(`)/'/g;
                   $name =~ s/^\s+//;
                   $name =~ s/\s+$//;
                   my $value = $env{'form.proctoring_custom_value_'.$provider};
                   $value =~ s/(`)/'/g;
                   $value =~ s/^\s+//;
                   $value =~ s/\s+$//;
                   if ($name ne '') {
                       $confhash{$provider}{'custom'}{$name} = $value;
                       $changes{$provider} = 1;
                   }
               }
           }
       }
       if (@allpos > 0) {
           my $idx = 0;
           foreach my $provider (@allpos) {
               if ($provider ne '') {
                   $confhash{$provider}{'order'} = $idx;
                   unless ($changes{$provider}) {
                       if (ref($domconfig{$action}) eq 'HASH') {
                           if (ref($domconfig{$action}{$provider}) eq 'HASH') {
                               if ($domconfig{$action}{$provider}{'order'} ne $idx) {
                                   $changes{$provider} = 1;
                               }
                           }
                       }
                   }
                   $idx ++;
               }
           }
       }
       my %proc_hash = (
                             $action => { %confhash }
                          );
       my $putresult = &Apache::lonnet::put_dom('configuration',\%proc_hash,
                                                $dom);
       if ($putresult eq 'ok') {
           my %proc_enchash = (
                                $action => { %encconfhash }
                            );
           &Apache::lonnet::put_dom('encconfig',\%proc_enchash,$dom,undef,1);
           if (keys(%changes) > 0) {
               my $cachetime = 24*60*60;
               my %procall = %confhash;
               foreach my $provider (keys(%procall)) {
                   if (ref($encconfhash{$provider}) eq 'HASH') {
                       foreach my $key ('key','secret') {
                           $procall{$provider}{$key} = $encconfhash{$provider}{$key};
                       }
                   }
               }
               &Apache::lonnet::do_cache_new('proctoring',$dom,\%procall,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'proctoring'} = 1;
               }
               $resulttext = &mt('Configuration for Provider(s) with changes:').'<ul>';
               my %bynum;
               foreach my $provider (sort(keys(%changes))) {
                   my $position = $confhash{$provider}{'order'};
                   $bynum{$position} = $provider;
               }
               foreach my $pos (sort { $a <=> $b } keys(%bynum)) {
                   my $provider = $bynum{$pos};
                   my %lt = &proctoring_titles($provider);
                   my %fieldtitles = &proctoring_fieldtitles($provider);
                   if (!$confhash{$provider}{'available'}) {
                       $resulttext .= '<li>'.&mt('Proctoring integration unavailable for: [_1]','<b>'.$providernames{$provider}.'</b>').'</li>';
                   } else {
                       $resulttext .= '<li>'.&mt('Proctoring integration available for: [_1]','<b>'.$providernames{$provider}.'</b>');
                       if ($confhash{$provider}{'image'}) {
                           $resulttext .= '&nbsp;'.
                                          '<img src="'.$confhash{$provider}{'image'}.'"'.
                                          ' alt="'.&mt('Proctoring icon').'" />';
                       }
                       $resulttext .= '<ul>';
                       my $position = $pos + 1;
                       $resulttext .= '<li>'.&mt('Order: [_1]',$position).'</li>';
                       foreach my $key ('version','sigmethod','url','lifetime') {
                           if ($confhash{$provider}{$key} ne '') {
                               $resulttext .= '<li>'.$lt{$key}.':&nbsp;'.$confhash{$provider}{$key}.'</li>';
                           }
                       }
                       if ($encconfhash{$provider}{'key'} ne '') {
                           $resulttext .= '<li>'.$lt{'key'}.':&nbsp;'.$encconfhash{$provider}{'key'}.'</li>';
                       }
                       if ($encconfhash{$provider}{'secret'} ne '') {
                           $resulttext .= '<li>'.$lt{'secret'}.':&nbsp;';
                           my $num = length($encconfhash{$provider}{'secret'});
                           $resulttext .= ('*'x$num).'</li>';
                       }
                       my (@fields,$showroles);
                       if (ref($requserfields{$provider}) eq 'ARRAY') {
                           push(@fields,@{$requserfields{$provider}});
                       }
                       if (ref($confhash{$provider}{'fields'}) eq 'ARRAY') {
                           push(@fields,@{$confhash{$provider}{'fields'}});
                       } elsif (ref($confhash{$provider}{'fields'}) eq 'HASH') {
                           push(@fields,(keys(%{$confhash{$provider}{'fields'}})));
                       }
                       if (@fields) {
                           if (grep(/^roles$/,@fields)) {
                               $showroles = 1;
                           }
                           $resulttext .= '<li>'.$lt{'udsl'}.':&nbsp;"'.
                                          join('", "', map { $lt{$_}; } @fields).'"</li>';
                       }
                       if (ref($requserfields{$provider}) eq 'ARRAY') {
                           if (grep(/^user$/,@{$requserfields{$provider}})) {
                               if ($confhash{$provider}{'incdom'}) {
                                   $resulttext .= '<li>'.&mt('[_1] sent as [_2]',$lt{'user'},$lt{'uname:dom'}).'</li>';
                               } else { 
                                   $resulttext .= '<li>'.&mt('[_1] sent as [_2]',$lt{'user'},$lt{'username'}).'</li>';
                               }
                           }
                       }
                       if (ref($confhash{$provider}{'defaults'}) eq 'ARRAY') {
                           if (@{$confhash{$provider}{'defaults'}} > 0) {
                               $resulttext .= '<li>'.$lt{'defa'};
                               foreach my $field (@{$confhash{$provider}{'defaults'}}) {
                                   $resulttext .= ' "'.$fieldtitles{$field}.'",';
                               }
                               $resulttext =~ s/,$//;
                               $resulttext .= '</li>';
                           }
                       } elsif (ref($confhash{$provider}{'defaults'}) eq 'HASH') {
                           if (keys(%{$confhash{$provider}{'defaults'}})) {
                               $resulttext .= '<li>'.$lt{'defa'}.':&nbsp;<ul>';
                               foreach my $key (sort(keys(%{$confhash{$provider}{'defaults'}}))) {
                                   if ($confhash{$provider}{'defaults'}{$key} ne '') {
                                       $resulttext .= '<li>'.$fieldtitles{$key}.' = '.$confhash{$provider}{'defaults'}{$key}.'</li>';
                                   }
                               }
                               $resulttext .= '</ul></li>';
                           }
                       }
                       if (ref($crsconf{$provider}) eq 'ARRAY') {
                           if (@{$crsconf{$provider}} > 0) {
                               $resulttext .= '<li>'.&mt('Configurable in course:');
                               my $numconfig = 0;
                               if (ref($confhash{$provider}{'crsconf'}) eq 'ARRAY') {
                                   if (@{$confhash{$provider}{'crsconf'}} > 0) {
                                       foreach my $field (@{$confhash{$provider}{'crsconf'}}) {
                                           $numconfig ++;
                                           if ($provider eq 'examity') {
                                               $resulttext .= ' "'.$lt{'crs'.$field}.'",';
                                           } else {
                                               $resulttext .= ' "'.$fieldtitles{$field}.'",';
                                           }
                                       }
                                       $resulttext =~ s/,$//;
                                   }
                               }
                               if (!$numconfig) {
                                   $resulttext .= '&nbsp;'.&mt('None');
                               }
                               $resulttext .= '</li>';
                           }
                       }
                       if ($showroles) {
                           if (ref($confhash{$provider}{'roles'}) eq 'HASH') {
                               my $rolemaps;
                               foreach my $role (@courseroles) {
                                   if ($confhash{$provider}{'roles'}{$role}) {
                                       $rolemaps .= ('&nbsp;'x2).&Apache::lonnet::plaintext($role,'Course').'='.
                                                    $confhash{$provider}{'roles'}{$role}.',';
                                   }
                               }
                               if ($rolemaps) {
                                   $rolemaps =~ s/,$//;
                                   $resulttext .= '<li>'.&mt('Role mapping:').$rolemaps.'</li>';
                               }
                           }
                       }
                       if (ref($confhash{$provider}{'custom'}) eq 'HASH') {
                           my $customlist;
                           if (keys(%{$confhash{$provider}{'custom'}})) {
                               foreach my $key (sort(keys(%{$confhash{$provider}{'custom'}}))) {
                                   $customlist .= $key.'='.$confhash{$provider}{'custom'}{$key}.', ';
                               }
                               $customlist =~ s/,$//;
                           }
                           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_proctoring_image {
       my ($r,$dom,$confname,$caller,$provider,$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 Remote Proctoring Provider icon is not permitted to this server: [_1]',
                            $switchserver);
           } elsif ($author_ok eq 'ok') {
               my ($result,$imageurl,$madethumb) =
                   &publishlogo($r,'upload',$caller,$dom,$confname,
                                "proctoring/$provider/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 modify_lti {
       my ($r,$dom,$action,$lastactref,%domconfig) = @_;
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
       my ($newid,@allpos,%changes,%confhash,%encconfig,$errors,$resulttext);
       my (%posslti,%posslticrs,%posscrstype);
       my @courseroles = ('cc','in','ta','ep','st');
       my @ltiroles = qw(Learner Instructor ContentDeveloper TeachingAssistant Mentor Member Manager Administrator);
       my @lticourseroles = qw(Instructor TeachingAssistant Mentor Learner);
       my @coursetypes = ('official','unofficial','community','textbook','placement','lti');
       my %coursetypetitles = &Apache::lonlocal::texthash (
                                  official   => 'Official',
                                  unofficial => 'Unofficial',
                                  community  => 'Community',
                                  textbook   => 'Textbook',
                                  placement  => 'Placement Test',
                                  lti        => 'LTI Provider',
       );
       my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
       my %lt = &lti_names();
       map { $posslti{$_} = 1; } @ltiroles;
       map { $posslticrs{$_} = 1; } @lticourseroles;
       map { $posscrstype{$_} = 1; } @coursetypes;
   
       my %menutitles = &ltimenu_titles();
   
       my (@items,%deletions,%itemids);
       if ($env{'form.lti_add'}) {
           my $consumer = $env{'form.lti_consumer_add'};
           $consumer =~ s/(`)/'/g;
           ($newid,my $error) = &get_lti_id($dom,$consumer);
           if ($newid) {
               $itemids{'add'} = $newid;
               push(@items,'add');
               $changes{$newid} = 1;
           } else {
               my $error = &mt('Failed to acquire unique ID for new LTI configuration');
               $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
           }
       }
       if (ref($domconfig{$action}) eq 'HASH') {
           my @todelete = &Apache::loncommon::get_env_multiple('form.lti_del');
           if (@todelete) {
               map { $deletions{$_} = 1; } @todelete;
           }
           my $maxnum = $env{'form.lti_maxnum'};
           for (my $i=0; $i<$maxnum; $i++) {
               my $itemid = $env{'form.lti_id_'.$i};
               $itemid =~ s/\D+//g;
               if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
                   if ($deletions{$itemid}) {
                       $changes{$itemid} = $domconfig{$action}{$itemid}{'consumer'};
                   } else {
                       push(@items,$i);
                       $itemids{$i} = $itemid;
                   }
               }
           }
       }
       foreach my $idx (@items) {
           my $itemid = $itemids{$idx};
           next unless ($itemid);
           my $position = $env{'form.lti_pos_'.$itemid};
           $position =~ s/\D+//g;
           if ($position ne '') {
               $allpos[$position] = $itemid;
           }
           foreach my $item ('consumer','key','secret','lifetime','requser','crsinc') {
               my $formitem = 'form.lti_'.$item.'_'.$idx;
               $env{$formitem} =~ s/(`)/'/g;
               if ($item eq 'lifetime') {
                   $env{$formitem} =~ s/[^\d.]//g;
               }
               if ($env{$formitem} ne '') {
                   if (($item eq 'key') || ($item eq 'secret')) {
                       $encconfig{$itemid}{$item} = $env{$formitem};
                   } else {
                       $confhash{$itemid}{$item} = $env{$formitem};
                       unless (($idx eq 'add') || ($changes{$itemid})) {
                           if ($domconfig{$action}{$itemid}{$item} ne $confhash{$itemid}{$item}) {
                               $changes{$itemid} = 1;
                           }
                       }
                   }
               }
           }
           if ($env{'form.lti_version_'.$idx} eq 'LTI-1p0') {
               $confhash{$itemid}{'version'} = $env{'form.lti_version_'.$idx};
           }
           if ($confhash{$itemid}{'requser'}) {
               if ($env{'form.lti_mapuser_'.$idx} eq 'sourcedid') {
                   $confhash{$itemid}{'mapuser'} = 'lis_person_sourcedid'; 
               } elsif ($env{'form.lti_mapuser_'.$idx} eq 'email') {
                   $confhash{$itemid}{'mapuser'} = 'lis_person_contact_email_primary';
               } elsif ($env{'form.lti_mapuser_'.$idx} eq 'other') {
                   my $mapuser = $env{'form.lti_customuser_'.$idx};
                   $mapuser =~ s/(`)/'/g;
                   $mapuser =~ s/^\s+|\s+$//g; 
                   $confhash{$itemid}{'mapuser'} = $mapuser; 
               }
               my @possmakeuser = &Apache::loncommon::get_env_multiple('form.lti_makeuser_'.$idx);
               my @makeuser;
               foreach my $ltirole (sort(@possmakeuser)) {
                   if ($posslti{$ltirole}) {
                       push(@makeuser,$ltirole);
                   }
               }
               $confhash{$itemid}{'makeuser'} = \@makeuser;
               if (@makeuser) {
                   my $lcauth = $env{'form.lti_lcauth_'.$idx};
                   if ($lcauth =~ /^(internal|krb4|krb5|localauth)$/) {
                       $confhash{$itemid}{'lcauth'} = $lcauth;
                       if ($lcauth ne 'internal') {
                           my $lcauthparm = $env{'form.lti_lcauthparm_'.$idx};
                           $lcauthparm =~ s/^(\s+|\s+)$//g;
                           $lcauthparm =~ s/`//g;
                           if ($lcauthparm ne '') {
                               $confhash{$itemid}{'lcauthparm'} = $lcauthparm;
                           }
                       }
                   } else {
                       $confhash{$itemid}{'lcauth'} = 'lti';
                   }
               }
               my @possinstdata =  &Apache::loncommon::get_env_multiple('form.lti_instdata_'.$idx);
               if (@possinstdata) {
                   foreach my $field (@possinstdata) {
                       if (exists($fieldtitles{$field})) {
                           push(@{$confhash{$itemid}{'instdata'}});
                       }
                   }
               }
               if ($env{'form.lti_callback_'.$idx}) {
                   if ($env{'form.lti_callbackparam_'.$idx}) {
                       my $callback = $env{'form.lti_callbackparam_'.$idx};
                       $callback =~ s/^\s+|\s+$//g;
                       $confhash{$itemid}{'callback'} = $callback;
                   }
               }
               foreach my $field ('topmenu','inlinemenu') {
                   if ($env{'form.lti_'.$field.'_'.$idx}) {
                       $confhash{$itemid}{$field} = 1;
                   }
               }
               if ($env{'form.lti_topmenu_'.$idx} || $env{'form.lti_inlinemenu_'.$idx}) {
                   $confhash{$itemid}{lcmenu} = [];
                   my @possmenu = &Apache::loncommon::get_env_multiple('form.lti_menuitem_'.$idx);
                   foreach my $field (@possmenu) {
                       if (exists($menutitles{$field})) {
                           if ($field eq 'grades') {
                               next unless ($env{'form.lti_inlinemenu_'.$idx});
                           }
                           push(@{$confhash{$itemid}{lcmenu}},$field);
                       }
                   }
               }
               if ($confhash{$itemid}{'crsinc'}) {
                   if (($env{'form.lti_mapcrs_'.$idx} eq 'course_offering_sourcedid') ||
                       ($env{'form.lti_mapcrs_'.$idx} eq 'context_id'))  {
                       $confhash{$itemid}{'mapcrs'} = $env{'form.lti_mapcrs_'.$idx};
                   } elsif ($env{'form.lti_mapcrs_'.$idx} eq 'other') {
                       my $mapcrs = $env{'form.lti_mapcrsfield_'.$idx}; 
                       $mapcrs =~ s/(`)/'/g;
                       $mapcrs =~ s/^\s+|\s+$//g;
                       $confhash{$itemid}{'mapcrs'} = $mapcrs;
                   }
                   my @posstypes = &Apache::loncommon::get_env_multiple('form.lti_mapcrstype_'.$idx);
                   my @crstypes;
                   foreach my $type (sort(@posstypes)) {
                       if ($posscrstype{$type}) {
                           push(@crstypes,$type);
                       }
                   }
                   $confhash{$itemid}{'mapcrstype'} = \@crstypes;
                   if ($env{'form.lti_storecrs_'.$idx}) {
                       $confhash{$itemid}{'storecrs'} = 1;
                   }       
                   if ($env{'form.lti_makecrs_'.$idx}) {
                       $confhash{$itemid}{'makecrs'} = 1;
                   }
                   foreach my $ltirole (@lticourseroles) {
                       my $possrole = $env{'form.lti_maprole_'.$ltirole.'_'.$idx};
                       if (grep(/^\Q$possrole\E$/,@courseroles)) {
                           $confhash{$itemid}{'maproles'}{$ltirole} = $possrole;
                       }
                   }
                   my @possenroll = &Apache::loncommon::get_env_multiple('form.lti_selfenroll_'.$idx);
                   my @selfenroll;
                   foreach my $type (sort(@possenroll)) {
                       if ($posslticrs{$type}) {
                           push(@selfenroll,$type);
                       }
                   }
                   $confhash{$itemid}{'selfenroll'} = \@selfenroll;
                   if ($env{'form.lti_crssec_'.$idx}) {
                       if ($env{'form.lti_crssecsrc_'.$idx} eq 'course_section_sourcedid') {
                           $confhash{$itemid}{'section'} = $env{'form.lti_crssecsrc_'.$idx};
                       } elsif ($env{'form.lti_crssecsrc_'.$idx} eq 'other') {
                           my $section = $env{'form.lti_customsection_'.$idx};
                           $section =~ s/(`)/'/g;
                           $section =~ s/^\s+|\s+$//g;
                           if ($section ne '') {
                               $confhash{$itemid}{'section'} = $section;
                           }
                       }
                   }
                   foreach my $field ('passback','roster') {
                       if ($env{'form.lti_'.$field.'_'.$idx}) {
                           $confhash{$itemid}{$field} = 1;
                       }
                   }
                   if ($env{'form.lti_passback_'.$idx}) {
                       if ($env{'form.lti_passbackformat_'.$idx} eq '1.0') {
                           $confhash{$itemid}{'passbackformat'} = '1.0';
                       } else {
                           $confhash{$itemid}{'passbackformat'} = '1.1';
                       }
                   }
               }
               unless (($idx eq 'add') || ($changes{$itemid})) {
                   if ($confhash{$itemid}{'crsinc'}) {
                       foreach my $field ('mapcrs','storecrs','makecrs','section','passback','roster') {
                           if ($domconfig{$action}{$itemid}{$field} ne $confhash{$itemid}{$field}) {
                               $changes{$itemid} = 1;
                           }
                       }
                       unless ($changes{$itemid}) {
                           if ($domconfig{$action}{$itemid}{'passback'} eq $confhash{$itemid}{'passback'}) {
                               if ($domconfig{$action}{$itemid}{'passbackformat'} ne $confhash{$itemid}{'passbackformat'}) {
                                   $changes{$itemid} = 1;
                               }
                           }
                       }
                       foreach my $field ('mapcrstype','selfenroll') {
                           unless ($changes{$itemid}) {
                               if (ref($domconfig{$action}{$itemid}{$field}) eq 'ARRAY') {
                                   if (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
                                       my @diffs = &Apache::loncommon::compare_arrays($domconfig{$action}{$itemid}{$field},
                                                                                      $confhash{$itemid}{$field});
                                       if (@diffs) {
                                           $changes{$itemid} = 1;
                                       }
                                   } elsif (@{$domconfig{$action}{$itemid}{$field}} > 0) {
                                       $changes{$itemid} = 1;
                                   }
                               } elsif (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
                                   if (@{$confhash{$itemid}{$field}} > 0) {
                                       $changes{$itemid} = 1;
                                   }
                               }
                           }
                       }
                       unless ($changes{$itemid}) {
                           if (ref($domconfig{$action}{$itemid}{'maproles'}) eq 'HASH') {
                               if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
                                   foreach my $ltirole (keys(%{$domconfig{$action}{$itemid}{'maproles'}})) {
                                       if ($domconfig{$action}{$itemid}{'maproles'}{$ltirole} ne 
                                           $confhash{$itemid}{'maproles'}{$ltirole}) {
                                           $changes{$itemid} = 1;
                                           last;
                                       }
                                   }
                                   unless ($changes{$itemid}) {
                                       foreach my $ltirole (keys(%{$confhash{$itemid}{'maproles'}})) {
                                           if ($confhash{$itemid}{'maproles'}{$ltirole} ne 
                                               $domconfig{$action}{$itemid}{'maproles'}{$ltirole}) {
                                               $changes{$itemid} = 1;
                                               last;
                                           }
                                       }
                                   }
                               } elsif (keys(%{$domconfig{$action}{$itemid}{'maproles'}}) > 0) {
                                   $changes{$itemid} = 1;
                               }
                           } elsif (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
                               unless ($changes{$itemid}) {
                                   if (keys(%{$confhash{$itemid}{'maproles'}}) > 0) {
                                       $changes{$itemid} = 1;
                                   }
                               }
                           }
                       }
                   }
                   unless ($changes{$itemid}) {
                       foreach my $field ('mapuser','lcauth','lcauthparm','topmenu','inlinemenu','callback') {
                           if ($domconfig{$action}{$itemid}{$field} ne $confhash{$itemid}{$field}) {
                               $changes{$itemid} = 1;
                           }
                       }
                       unless ($changes{$itemid}) {
                           foreach my $field ('makeuser','lcmenu') {
                               if (ref($domconfig{$action}{$itemid}{$field}) eq 'ARRAY') {
                                   if (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
                                       my @diffs = &Apache::loncommon::compare_arrays($domconfig{$action}{$itemid}{$field},
                                                                                      $confhash{$itemid}{$field});
                                       if (@diffs) {
                                           $changes{$itemid} = 1;
                                       }
                                   } elsif (@{$domconfig{$action}{$itemid}{$field}} > 0) {
                                       $changes{$itemid} = 1;
                                   }
                               } elsif (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
                                   if (@{$confhash{$itemid}{$field}} > 0) {
                                       $changes{$itemid} = 1;
                                   }
                               }
                           }
                       }
                   }
               }
           }
       }
       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 %ltihash = (
                             $action => { %confhash }
                          );
       my $putresult = &Apache::lonnet::put_dom('configuration',\%ltihash,
                                                $dom);
       if ($putresult eq 'ok') {
           my %ltienchash = (
                                $action => { %encconfig }
                            );
           &Apache::lonnet::put_dom('encconfig',\%ltienchash,$dom,undef,1);
           if (keys(%changes) > 0) {
               my $cachetime = 24*60*60;
               my %ltiall = %confhash;
               foreach my $id (keys(%ltiall)) {
                   if (ref($encconfig{$id}) eq 'HASH') {
                       foreach my $item ('key','secret') {
                           $ltiall{$id}{$item} = $encconfig{$id}{$item};
                       }
                   }
               }
               &Apache::lonnet::do_cache_new('lti',$dom,\%ltiall,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'lti'} = 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}{'consumer'}.'</b><ul>';
                       my $position = $pos + 1;
                       $resulttext .= '<li>'.&mt('Order: [_1]',$position).'</li>';
                       foreach my $item ('version','lifetime') {
                           if ($confhash{$itemid}{$item} ne '') {
                               $resulttext .= '<li>'.$lt{$item}.':&nbsp;'.$confhash{$itemid}{$item}.'</li>';
                           }
                       }
                       if ($encconfig{$itemid}{'key'} ne '') {
                           $resulttext .= '<li>'.$lt{'key'}.':&nbsp;'.$encconfig{$itemid}{'key'}.'</li>';
                       }
                       if ($encconfig{$itemid}{'secret'} ne '') {
                           $resulttext .= '<li>'.$lt{'secret'}.':&nbsp;';
                           my $num = length($encconfig{$itemid}{'secret'});
                           $resulttext .= ('*'x$num).'</li>';
                       }
                       if ($confhash{$itemid}{'requser'}) {
                           if ($confhash{$itemid}{'callback'}) {
                               $resulttext .= '<li>'.&mt('Callback setting').': '.$confhash{$itemid}{'callback'}.'</li>';
                           } else {
                               $resulttext .= '<li>'.&mt('Callback to logout LON-CAPA on log out from Consumer').'</li>';
                           }
                           if ($confhash{$itemid}{'mapuser'}) {
                               my $shownmapuser;
                               if ($confhash{$itemid}{'mapuser'} eq 'lis_person_sourcedid') {
                                   $shownmapuser = $lt{'sourcedid'}.' (lis_person_sourcedid)';
                               } elsif ($confhash{$itemid}{'mapuser'} eq 'lis_person_contact_email_primary') {
                                   $shownmapuser = $lt{'email'}.' (lis_person_contact_email_primary)';
                               } else {
                                   $shownmapuser = &mt('Other').' ('.$confhash{$itemid}{'mapuser'}.')';
                               }
                               $resulttext .= '<li>'.&mt('LON-CAPA username').': '.$shownmapuser.'</li>';
                           }
                           if (ref($confhash{$itemid}{'makeuser'}) eq 'ARRAY') {
                               if (@{$confhash{$itemid}{'makeuser'}} > 0) { 
                                   $resulttext .= '<li>'.&mt('Following roles may create user accounts: [_1]',
                                                             join(', ',@{$confhash{$itemid}{'makeuser'}})).'<br />';
                                   if ($confhash{$itemid}{'lcauth'} eq 'lti') {
                                       $resulttext .= &mt('New users will only be able to authenticate via LTI').'</li>';
                                   } else {
                                       $resulttext .= &mt('New users will be assigned LON-CAPA authentication: [_1]',
                                                          $confhash{$itemid}{'lcauth'});
                                       if ($confhash{$itemid}{'lcauth'} eq 'internal') {
                                           $resulttext .= '; '.&mt('a randomly generated password will be created');
                                       } elsif ($confhash{$itemid}{'lcauth'} eq 'localauth') {
                                           if ($confhash{$itemid}{'lcauthparm'} ne '') {
                                               $resulttext .= ' '.&mt('with argument: [_1]',$confhash{$itemid}{'lcauthparm'});
                                           }
                                       } else {
                                           $resulttext .= '; '.&mt('Kerberos domain: [_1]',$confhash{$itemid}{'lcauthparm'});
                                       }
                                   }
                                   $resulttext .= '</li>';
                               } else {
                                   $resulttext .= '<li>'.&mt('User account creation not permitted.').'</li>';
                               }
                           }
                           if (ref($confhash{$itemid}{'instdata'}) eq 'ARRAY') {
                               if (@{$confhash{$itemid}{'instdata'}} > 0) {
                                   $resulttext .= '<li>'.&mt('Institutional data will be used when creating a new user for: [_1]',
                                                             join(', ',map { $fieldtitles{$_}; } @{$confhash{$itemid}{'instdata'}})).'</li>';
                               } else {
                                   $resulttext .= '<li>'.&mt('No institutional data used when creating a new user.').'</li>';
                               }
                           }
                           foreach my $item ('topmenu','inlinemenu') {
                               $resulttext .= '<li>'.$lt{$item}.':&nbsp;';
                               if ($confhash{$itemid}{$item}) {
                                   $resulttext .= &mt('Yes');
                               } else {
                                   $resulttext .= &mt('No');
                               }
                               $resulttext .= '</li>';
                           }
                           if (ref($confhash{$itemid}{'lcmenu'}) eq 'ARRAY') {
                               if (@{$confhash{$itemid}{'lcmenu'}} > 0) {
                                   $resulttext .= '<li>'.&mt('Menu items:').' '.
                                                  join(', ', map { $menutitles{$_}; } (@{$confhash{$itemid}{'lcmenu'}})).'</li>';
                               } else {
                                   $resulttext .= '<li>'.&mt('No menu items displayed in header or online menu').'</li>';
                               }
                           }
                           if ($confhash{$itemid}{'crsinc'}) {
                               if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
                                   my $rolemaps;
                                   foreach my $role (@ltiroles) {
                                       if ($confhash{$itemid}{'maproles'}{$role}) {
                                           $rolemaps .= ('&nbsp;'x2).$role.'='.
                                                        &Apache::lonnet::plaintext($confhash{$itemid}{'maproles'}{$role},
                                                                                   'Course').',';
                                       }
                                   }
                                   if ($rolemaps) {
                                       $rolemaps =~ s/,$//;
                                       $resulttext .= '<li>'.&mt('Role mapping:').$rolemaps.'</li>';
                                   }
                               }
                               if ($confhash{$itemid}{'mapcrs'}) {
                                   $resulttext .= '<li>'.&mt('Unique course identifier').': '.$confhash{$itemid}{'mapcrs'}.'</li>';
                               }
                               if (ref($confhash{$itemid}{'mapcrstype'}) eq 'ARRAY') {
                                   if (@{$confhash{$itemid}{'mapcrstype'}} > 0) {
                                       $resulttext .= '<li>'.&mt('Mapping for the following LON-CAPA course types: [_1]',
                                                      join(', ',map { $coursetypetitles{$_}; } @coursetypes)).
                                                      '</li>';
                                   } else {
                                       $resulttext .= '<li>'.&mt('No mapping to LON-CAPA courses').'</li>';
                                   }
                               }
                               if ($confhash{$itemid}{'storecrs'}) {
                                   $resulttext .= '<li>'.&mt('Store mapping of course identifier to LON-CAPA CourseID').': '.$confhash{$itemid}{'storecrs'}.'</li>';
                               }
                               if ($confhash{$itemid}{'makecrs'}) {
                                   $resulttext .= '<li>'.&mt('Instructor may create course (if absent).').'</li>';
                               } else {
                                   $resulttext .= '<li>'.&mt('Instructor may not create course (if absent).').'</li>';
                               }
                               if (ref($confhash{$itemid}{'selfenroll'}) eq 'ARRAY') {
                                   if (@{$confhash{$itemid}{'selfenroll'}} > 0) {
                                       $resulttext .= '<li>'.&mt('Self-enrollment for following roles: [_1]',
                                                                 join(', ',@{$confhash{$itemid}{'selfenroll'}})).
                                                      '</li>';
                                   } else {
                                       $resulttext .= '<li>'.&mt('Self-enrollment not permitted').'</li>';
                                   }
                               }
                               if ($confhash{$itemid}{'section'}) {
                                   if ($confhash{$itemid}{'section'} eq 'course_section_sourcedid') {
                                       $resulttext .= '<li>'.&mt('User section from standard field:').
                                                            ' (course_section_sourcedid)'.'</li>';  
                                   } else {
                                       $resulttext .= '<li>'.&mt('User section from:').' '.
                                                             $confhash{$itemid}{'section'}.'</li>';
                                   }
                               } else {
                                   $resulttext .= '<li>'.&mt('No section assignment').'</li>';
                               }
                               foreach my $item ('passback','roster','topmenu','inlinemenu') {
                                   $resulttext .= '<li>'.$lt{$item}.':&nbsp;';
                                   if ($confhash{$itemid}{$item}) {
                                       $resulttext .= &mt('Yes');
                                       if ($item eq 'passback') {
                                           if ($confhash{$itemid}{'passbackformat'} eq '1.0') {
                                               $resulttext .= '&nbsp;('.&mt('Outcomes Extension (1.0)').')';
                                           } elsif ($confhash{$itemid}{'passbackformat'} eq '1.1') {
                                               $resulttext .= '&nbsp;('.&mt('Outcomes Service (1.1)').')';
                                           }
                                       }
                                   } else {
                                       $resulttext .= &mt('No');
                                   }
                                   $resulttext .= '</li>';
                               }
                               if (ref($confhash{$itemid}{'lcmenu'}) eq 'ARRAY') {
                                   if (@{$confhash{$itemid}{'lcmenu'}} > 0) {
                                       $resulttext .= '<li>'.&mt('Menu items:').' '.
                                                      join(', ', map { $menutitles{$_}; } (@{$confhash{$itemid}{'lcmenu'}})).'</li>'; 
                                   } else {
                                       $resulttext .= '<li>'.&mt('No menu items displayed in header or online menu').'</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 get_lti_id {
       my ($domain,$consumer) = @_;
       # get lock on lti db
       my $lockhash = {
                         lock => $env{'user.name'}.
                                 ':'.$env{'user.domain'},
                      };
       my $tries = 0;
       my $gotlock = &Apache::lonnet::newput_dom('lti',$lockhash,$domain);
       my ($id,$error);
   
       while (($gotlock ne 'ok') && ($tries<10)) {
           $tries ++;
           sleep (0.1);
           $gotlock = &Apache::lonnet::newput_dom('lti',$lockhash,$domain);
       }
       if ($gotlock eq 'ok') {
           my %currids = &Apache::lonnet::dump_dom('lti',$domain);
           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('lti',{ $id => $consumer },$domain) eq 'ok') {
                       $error = 'nostore';
                   }
               } else {
                   $error = 'nonumber';
               }
           }
           my $dellockoutcome = &Apache::lonnet::del_dom('lti',['lock'],$domain);
       } 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 12590  sub modify_autoenroll { Line 15913  sub modify_autoenroll {
     my %title = ( run => 'Auto-enrollment active',      my %title = ( run => 'Auto-enrollment active',
                   sender => 'Sender for notification messages',                    sender => 'Sender for notification messages',
                   coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)',                    coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)',
                   autofailsafe => 'Failsafe for no drops if institutional data missing for a section');                    failsafe => 'Failsafe for no drops if institutional data missing for a section');
     my @offon = ('off','on');      my @offon = ('off','on');
     my $sender_uname = $env{'form.sender_uname'};      my $sender_uname = $env{'form.sender_uname'};
     my $sender_domain = $env{'form.sender_domain'};      my $sender_domain = $env{'form.sender_domain'};
Line 12600  sub modify_autoenroll { Line 15923  sub modify_autoenroll {
         $sender_domain = '';          $sender_domain = '';
     }      }
     my $coowners = $env{'form.autoassign_coowners'};      my $coowners = $env{'form.autoassign_coowners'};
     my $autofailsafe = $env{'form.autoenroll_autofailsafe'};  
     $autofailsafe =~ s{^\s+|\s+$}{}g;  
     if ($autofailsafe =~ /\D/) {  
         undef($autofailsafe);  
     }  
     my $failsafe = $env{'form.autoenroll_failsafe'};      my $failsafe = $env{'form.autoenroll_failsafe'};
     unless (($failsafe eq 'zero') || ($failsafe eq 'any')) {      $failsafe =~ s{^\s+|\s+$}{}g;
         $failsafe = 'off';      if ($failsafe =~ /\D/) {
         undef($autofailsafe);          undef($failsafe);
     }      }
     my %autoenrollhash =  (      my %autoenrollhash =  (
                        autoenroll => { 'run' => $env{'form.autoenroll_run'},                         autoenroll => { 'run' => $env{'form.autoenroll_run'},
                                        'sender_uname' => $sender_uname,                                         'sender_uname' => $sender_uname,
                                        'sender_domain' => $sender_domain,                                         'sender_domain' => $sender_domain,
                                        'co-owners' => $coowners,                                         'co-owners' => $coowners,
                                        'autofailsafe' => $autofailsafe,                                         'autofailsafe' => $failsafe,
                                        'failsafe' => $failsafe,  
                                 }                                  }
                      );                       );
     my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,
Line 12644  sub modify_autoenroll { Line 15961  sub modify_autoenroll {
         } elsif ($coowners) {          } elsif ($coowners) {
             $changes{'coowners'} = 1;              $changes{'coowners'} = 1;
         }          }
         if ($currautoenroll{'autofailsafe'} ne $autofailsafe) {          if ($currautoenroll{'autofailsafe'} ne $failsafe) {
             $changes{'autofailsafe'} = 1;              $changes{'autofailsafe'} = 1;
         }          }
         if ($currautoenroll{'failsafe'} ne $failsafe) {  
             $changes{'failsafe'} = 1;  
         }  
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if ($changes{'run'}) {              if ($changes{'run'}) {
Line 12670  sub modify_autoenroll { Line 15984  sub modify_autoenroll {
                 }                  }
             }              }
             if ($changes{'autofailsafe'}) {              if ($changes{'autofailsafe'}) {
                 if ($autofailsafe ne '') {                  if ($failsafe ne '') {
                     $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section set to: [_1]',$autofailsafe).'</li>';                      $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section set to: [_1]',$failsafe).'</li>';
                 } else {  
                     $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section not in use').'</li>';  
                 }  
             }  
             if ($changes{'failsafe'}) {  
                 if ($failsafe eq 'off') {  
                     unless ($changes{'autofailsafe'}) {  
                         $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section not in use').'</li>';  
                     }  
                 } elsif ($failsafe eq 'zero') {  
                     $resulttext .= '<li>'.&mt('Failsafe applies if retrieved section enrollment is zero').'</li>';  
                 } else {                  } else {
                     $resulttext .= '<li>'.&mt('Failsafe applies if retrieved section enrollment is zero or greater').'</li>';                      $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section: deleted');
                 }                  }
             }  
             if (($changes{'autofailsafe'}) || ($changes{'failsafe'})) {  
                 &Apache::lonnet::get_domain_defaults($dom,1);                  &Apache::lonnet::get_domain_defaults($dom,1);
                 if (ref($lastactref) eq 'HASH') {                  if (ref($lastactref) eq 'HASH') {
                     $lastactref->{'domdefaults'} = 1;                      $lastactref->{'domdefaults'} = 1;
Line 13336  sub modify_contacts { Line 16637  sub modify_contacts {
                     $contacts_hash{'contacts'}{'overrides'}{$type}{'include'} = $includeloc{$type}.':'.&escape($includestr{$type});                      $contacts_hash{'contacts'}{'overrides'}{$type}{'include'} = $includeloc{$type}.':'.&escape($includestr{$type});
                     $newsetting{'override_'.$type}{'include'} = $contacts_hash{'contacts'}{'overrides'}{$type}{'include'};                      $newsetting{'override_'.$type}{'include'} = $contacts_hash{'contacts'}{'overrides'}{$type}{'include'};
                 }                  }
             }                  }     
         }          }
     }      }
     if (keys(%currsetting) > 0) {      if (keys(%currsetting) > 0) {
Line 13394  sub modify_contacts { Line 16695  sub modify_contacts {
             }              }
         }          }
         if (@statuses) {          if (@statuses) {
             if (ref($currsetting{'overrides'}) eq 'HASH') {              if (ref($currsetting{'overrides'}) eq 'HASH') { 
                 foreach my $key (keys(%{$currsetting{'overrides'}})) {                  foreach my $key (keys(%{$currsetting{'overrides'}})) {
                     if (ref($currsetting{'overrides'}{$key}) eq 'HASH') {                      if (ref($currsetting{'overrides'}{$key}) eq 'HASH') {
                         if (ref($newsetting{'override_'.$key}) eq 'HASH') {                          if (ref($newsetting{'override_'.$key}) eq 'HASH') {
                             foreach my $item (@contacts,'bcc','others','include') {                              foreach my $item (@contacts,'bcc','others','include') {
                                 if ($currsetting{'overrides'}{$key}{$item} ne $newsetting{'override_'.$key}{$item}) {                                  if ($currsetting{'overrides'}{$key}{$item} ne $newsetting{'override_'.$key}{$item}) { 
                                     push(@{$changes{'overrides'}},$key);                                      push(@{$changes{'overrides'}},$key);
                                     last;                                      last;
                                 }                                  }
Line 13416  sub modify_contacts { Line 16717  sub modify_contacts {
                 }                  }
             } else {              } else {
                 foreach my $key (@overrides) {                  foreach my $key (@overrides) {
                     push(@{$changes{'overrides'}},$key);                      push(@{$changes{'overrides'}},$key); 
                 }                  }
             }              }
         }          }
Line 13598  sub modify_contacts { Line 16899  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 13622  sub modify_contacts { Line 16923  sub modify_contacts {
                             if (ref($newsetting{'override_'.$type}) eq 'HASH') {                              if (ref($newsetting{'override_'.$type}) eq 'HASH') {
                                 my @text;                                  my @text;
                                 foreach my $item (@contacts) {                                  foreach my $item (@contacts) {
                                     if ($newsetting{'override_'.$type}{$item}) {                                      if ($newsetting{'override_'.$type}{$item}) { 
                                         push(@text,$short_titles->{$item});                                          push(@text,$short_titles->{$item});
                                     }                                      }
                                 }                                  }
                                 if ($newsetting{'override_'.$type}{'others'} ne '') {                                  if ($newsetting{'override_'.$type}{'others'} ne '') {
                                     push(@text,$newsetting{'override_'.$type}{'others'});                                      push(@text,$newsetting{'override_'.$type}{'others'});
                                 }                                  }
     
                                 if (@text) {                                  if (@text) {
                                     $resulttext .= &mt('Helpdesk e-mail sent to: [_1]',                                      $resulttext .= &mt('Helpdesk e-mail sent to: [_1]',
                                                        '<span class="LC_cusr_emph">'.join(', ',@text).'</span>');                                                         '<span class="LC_cusr_emph">'.join(', ',@text).'</span>');
Line 13791  sub modify_contacts { Line 17092  sub modify_contacts {
     return $resulttext;      return $resulttext;
 }  }
   
   sub modify_privacy {
       my ($dom,%domconfig) = @_;
       my ($resulttext,%current,%changes);
       if (ref($domconfig{'privacy'}) eq 'HASH') {
           %current = %{$domconfig{'privacy'}};
       }
       my @fields = ('lastname','firstname','middlename','generation','permanentemail','id');
       my @items = ('domain','author','course','community');
       my %names = &Apache::lonlocal::texthash (
                      domain => 'Assigned domain role(s)',
                      author => 'Assigned co-author role(s)',
                      course => 'Assigned course role(s)',
                      community => 'Assigned community role',
                   );
       my %roles = &Apache::lonlocal::texthash (
                      domain => 'Domain role',
                      author => 'Co-author role',
                      course => 'Course role',
                      community => 'Community role',
                   );
       my %titles = &Apache::lonlocal::texthash (
                     approval => 'Approval for role in different domain',
                     othdom   => 'User information available in other domain',
                     priv     => 'Information viewable by privileged user in same domain',
                     unpriv   => 'Information viewable by unprivileged user in same domain',
                     instdom  => 'Other domain shares institution/provider',
                     extdom   => 'Other domain has different institution/provider',
                     none     => 'Not allowed',
                     user     => 'User authorizes',
                     domain   => 'Domain Coordinator authorizes',
                     auto     => 'Unrestricted',
       );
       my %fieldnames = &Apache::lonlocal::texthash (
                           id => 'Student/Employee ID',
                           permanentemail => 'E-mail address',
                           lastname => 'Last Name',
                           firstname => 'First Name',
                           middlename => 'Middle Name',
                           generation => 'Generation',
       );
       my ($othertitle,$usertypes,$types) =
           &Apache::loncommon::sorted_inst_types($dom);
       my (%by_ip,%by_location,@intdoms,@instdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
   
       my %privacyhash = (
                          'approval' => {
                                          instdom => {},
                                          extdom  => {},
                                        },
                          'othdom'   => {},
                          'priv'     => {},
                          'unpriv'   => {},
                         );
       foreach my $item (@items) {
           if (@instdoms > 1) {
               if ($env{'form.privacy_approval_instdom'.$item} =~ /^(none|user|domain|auto)$/) {
                   $privacyhash{'approval'}{'instdom'}{$item} = $env{'form.privacy_approval_instdom_'.$item};
               }
               if (ref($current{'approval'}) eq 'HASH') {
                   if (ref($current{'approval'}{'instdom'}) eq 'HASH') {
                       unless ($privacyhash{'approval'}{'instdom'}{$item} eq $current{'approval'}{'instdom'}{$item}) {
                           $changes{'approval'} = 1;
                       }
                   }
               } elsif ($privacyhash{'approval'}{'instdom'}{$item} ne 'auto') {
                   $changes{'approval'} = 1;
               }
           }
           if (keys(%by_location) > 0) {
               if ($env{'form.privacy_approval_extdom_'.$item} =~ /^(none|user|domain|auto)$/) {
                   $privacyhash{'approval'}{'extdom'}{$item} = $env{'form.privacy_approval_extdom_'.$item};
               }
               if (ref($current{'approval'}) eq 'HASH') {
                   if (ref($current{'approval'}{'extdom'}) eq 'HASH') {
                       unless ($privacyhash{'approval'}{'extdom'}{$item} eq $current{'approval'}{'extdom'}{$item}) {
                           $changes{'approval'} = 1;
                       }
                   }
               } elsif ($privacyhash{'approval'}{'extdom'}{$item} ne 'auto') {
                   $changes{'approval'} = 1;
               }
           }
           foreach my $status ('priv','unpriv') {
               my @possibles = sort(&Apache::loncommon::get_env_multiple('form.privacy_'.$status.'_'.$item));
               my @newvalues;
               foreach my $field (@possibles) {
                   if (grep(/^\Q$field\E$/,@fields)) {
                       $privacyhash{$status}{$item}{$field} = 1;
                       push(@newvalues,$field);
                   }
               }
               @newvalues = sort(@newvalues);
               if (ref($current{$status}) eq 'HASH') {
                   if (ref($current{$status}{$item}) eq 'HASH') {
                       my @currvalues = sort(keys(%{$current{$status}{$item}}));
                       my @diffs = &Apache::loncommon::compare_arrays(\@currvalues,\@newvalues);
                       if (@diffs > 0) {
                           $changes{$status} = 1;
                       }
                   }
               } else {
                   my @stdfields;
                   foreach my $field (@fields) {
                       if ($field eq 'id') {
                           next if ($status eq 'unpriv');
                           next if (($status eq 'priv') && ($item eq 'community'));
                       }
                       push(@stdfields,$field);
                   }
                   my @diffs = &Apache::loncommon::compare_arrays(\@stdfields,\@newvalues);
                   if (@diffs > 0) {
                       $changes{$status} = 1;
                   }
               }
           }
       }
       if ((@instdoms > 1) || (keys(%by_location) > 0)) {
           my @statuses;
           if (ref($types) eq 'ARRAY') {
               @statuses = @{$types};
           }
           foreach my $type (@statuses,'default') {
               my @possfields = &Apache::loncommon::get_env_multiple('form.privacy_othdom_'.$type);
               my @newvalues;
               foreach my $field (sort(@possfields)) {
                   if (grep(/^\Q$field\E$/,@fields)) {
                       $privacyhash{'othdom'}{$type}{$field} = 1;
                       push(@newvalues,$field);
                   }
               }
               @newvalues = sort(@newvalues);
               if (ref($current{'othdom'}) eq 'HASH') {
                   if (ref($current{'othdom'}{$type}) eq 'HASH') {
                       my @currvalues = sort(keys(%{$current{'othdom'}{$type}}));
                       my @diffs = &Apache::loncommon::compare_arrays(\@currvalues,\@newvalues);
                       if (@diffs > 0) {
                           $changes{'othdom'} = 1;
                       }
                   }
               } else {
                   my @stdfields = ('lastname','firstname','middlename','generation','permanentemail');
                   my @diffs = &Apache::loncommon::compare_arrays(\@stdfields,\@newvalues);
                   if (@diffs > 0) {
                       $changes{'othdom'} = 1;
                   }
               }
           }
       }
       my %confighash = (
                           privacy => \%privacyhash,
                        );
       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 ('approval','othdom','priv','unpriv') {
                   if ($changes{$key}) {
                       $resulttext .= '<li>'.$titles{$key}.':<ul>';
                       if ($key eq 'approval') {
                           if (keys(%{$privacyhash{$key}{instdom}})) {
                               $resulttext .= '<li>'.$titles{'instdom'}.'<ul>';
                               foreach my $item (@items) {
                                   $resulttext .=  '<li>'.$roles{$item}.': '.$titles{$privacyhash{$key}{instdom}{$item}}.'</li>';
                               }
                               $resulttext .= '</ul></li>';
                           }
                           if (keys(%{$privacyhash{$key}{extdom}})) {
                               $resulttext .= '<li>'.$titles{'extdom'}.'<ul>';
                               foreach my $item (@items) {
                                   $resulttext .=  '<li>'.$roles{$item}.': '.$titles{$privacyhash{$key}{extdom}{$item}}.'</li>';
                               }
                               $resulttext .= '</ul></li>';
                           }
                       } elsif ($key eq 'othdom') {
                           my @statuses;
                           if (ref($types) eq 'ARRAY') {
                               @statuses = @{$types};
                           }
                           if (ref($privacyhash{$key}) eq 'HASH') {
                               foreach my $status (@statuses,'default') {
                                   if ($status eq 'default') {
                                       $resulttext .= '<li>'.$othertitle.': ';
                                   } elsif (ref($usertypes) eq 'HASH') {
                                       $resulttext .= '<li>'.$usertypes->{$status}.': ';
                                   } else {
                                       next;
                                   }
                                   if (ref($privacyhash{$key}{$status}) eq 'HASH') {
                                       if (keys(%{$privacyhash{$key}{$status}})) {
                                           $resulttext .= join(', ', map { $fieldnames{$_}; } (sort(keys(%{$privacyhash{$key}{$status}}))));
                                       } else {
                                           $resulttext .= &mt('none');
                                       }
                                   }
                                   $resulttext .= '</li>';
                               }
                           }
                       } else {
                           foreach my $item (@items) {
                               if (ref($privacyhash{$key}{$item}) eq 'HASH') {
                                   $resulttext .= '<li>'.$names{$item}.': ';
                                   if (keys(%{$privacyhash{$key}{$item}})) {
                                       $resulttext .= join(', ', map { $fieldnames{$_}; } (sort(keys(%{$privacyhash{$key}{$item}}))));
                                   } else {
                                       $resulttext .= &mt('none');
                                   }
                                   $resulttext .= '</li>';
                               }
                           }
                       }
                       $resulttext .= '</ul></li>';
                   }
               }
           } else {
               $resulttext = &mt('No changes made to user information settings');
           }
       } else {
           $resulttext = '<span class="LC_error">'.
               &mt('An error occurred: [_1]',$putresult).'</span>';
       }
       return $resulttext;
   }
   
 sub modify_passwords {  sub modify_passwords {
     my ($r,$dom,$confname,$lastactref,%domconfig) = @_;      my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
     my ($resulttext,%current,%changes,%newvalues,@oktypes,$errors,      my ($resulttext,%current,%changes,%newvalues,@oktypes,$errors,
Line 13816  sub modify_passwords { Line 17341  sub modify_passwords {
         min            => 'Minimum password length',          min            => 'Minimum password length',
         max            => 'Maximum password length',          max            => 'Maximum password length',
         chars          => 'Required characters',          chars          => 'Required characters',
           expire         => 'Password expiration (days)',
         numsaved       => 'Number of previous passwords to save',          numsaved       => 'Number of previous passwords to save',
         reset          => 'Resetting Forgotten Password',          reset          => 'Resetting Forgotten Password',
         intauth        => 'Encryption of Stored Passwords (Internal Auth)',          intauth        => 'Encryption of Stored Passwords (Internal Auth)',
Line 13958  sub modify_passwords { Line 17484  sub modify_passwords {
     }      }
     if ($env{'form.passwords_customfile.filename'} ne '') {      if ($env{'form.passwords_customfile.filename'} ne '') {
         my $servadm = $r->dir_config('lonAdmEMail');          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);
         my $error;          my $error;
Line 14025  sub modify_passwords { Line 17550  sub modify_passwords {
             $updatedefaults = 1;              $updatedefaults = 1;
         }          }
     }      }
     foreach my $rule ('min','max','numsaved') {      foreach my $rule ('min','max','expire','numsaved') {
         $env{'form.passwords_'.$rule} =~ s/^\s+|\s+$//g;          $env{'form.passwords_'.$rule} =~ s/^\s+|\s+$//g;
         my $ruleok;          my $ruleok;
         if ($rule eq 'min') {          if ($rule eq 'expire') {
               if (($env{'form.passwords_'.$rule} =~ /^\d+(|\.\d*)$/) &&
                   ($env{'form.passwords_'.$rule} ne '0')) {
                   $ruleok = 1;
               }
           } elsif ($rule eq 'min') {
             if ($env{'form.passwords_'.$rule} =~ /^\d+$/) {              if ($env{'form.passwords_'.$rule} =~ /^\d+$/) {
                 if ($env{'form.passwords_'.$rule} >= $Apache::lonnet::passwdmin) {                  if ($env{'form.passwords_'.$rule} >= $Apache::lonnet::passwdmin) {
                     $ruleok = 1;                      $ruleok = 1;
Line 14246  sub modify_passwords { Line 17776  sub modify_passwords {
                             $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$titles{$key.'_'.$item},$value).'</li>';                              $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$titles{$key.'_'.$item},$value).'</li>';
                         }                          }
                     } elsif ($key eq 'rules') {                      } elsif ($key eq 'rules') {
                         foreach my $rule ('min','max','numsaved') {                          foreach my $rule ('min','max','expire','numsaved') {
                             if ($confighash{'passwords'}{$rule} eq '') {                              if ($confighash{'passwords'}{$rule} eq '') {
                                 if ($rule eq 'min') {                                  if ($rule eq 'min') {
                                     $resulttext .= '<li>'.&mt('[_1] not set.',$titles{$rule});                                      $resulttext .= '<li>'.&mt('[_1] not set.',$titles{$rule});
Line 14269  sub modify_passwords { Line 17799  sub modify_passwords {
                                                    );                                                     );
                                 my $needed = '<ul><li>'.                                  my $needed = '<ul><li>'.
                                              join('</li><li>',map {$rulenames{$_} } @{$confighash{'passwords'}{'chars'}}).                                               join('</li><li>',map {$rulenames{$_} } @{$confighash{'passwords'}{'chars'}}).
                                              '</li></ul>';                                               '</li></ul>'; 
                                 $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$titles{'chars'},$needed).'</li>';                                  $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$titles{'chars'},$needed).'</li>';
                             } else {                              } else {
                                 $resulttext .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';                                  $resulttext .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';
Line 14418  sub modify_usercreation { Line 17948  sub modify_usercreation {
     }      }
   
     my @authen_contexts = ('author','course','domain');      my @authen_contexts = ('author','course','domain');
     my @authtypes = ('int','krb4','krb5','loc');      my @authtypes = ('int','krb4','krb5','loc','lti');
     my %authhash;      my %authhash;
     foreach my $item (@authen_contexts) {      foreach my $item (@authen_contexts) {
         my @authallowed =  &Apache::loncommon::get_env_multiple('form.'.$item.'_auth');          my @authallowed =  &Apache::loncommon::get_env_multiple('form.'.$item.'_auth');
Line 14633  sub modify_selfcreation { Line 18163  sub modify_selfcreation {
 # 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 ($emailrules,$emailruleorder) = &Apache::lonnet::inst_userrules($dom,'email');
   
     my (@statuses,%email_rule);      my (@statuses,%email_rule);
Line 14683  sub modify_selfcreation { Line 18212  sub modify_selfcreation {
                             if (($chosen eq 'inst') || ($chosen eq 'noninst')) {                              if (($chosen eq 'inst') || ($chosen eq 'noninst')) {
                                 my $emaildom;                                  my $emaildom;
                                 if ($env{'form.cancreate_emaildomain_'.$chosen.'_'.$type} =~ /^\@[^\@]+$/) {                                  if ($env{'form.cancreate_emaildomain_'.$chosen.'_'.$type} =~ /^\@[^\@]+$/) {
                                     $emaildom = $env{'form.cancreate_emaildomain_'.$chosen.'_'.$type};                                      $emaildom = $env{'form.cancreate_emaildomain_'.$chosen.'_'.$type}; 
                                     $cancreate{'emaildomain'}{$type}{$chosen} = $emaildom;                                      $cancreate{'emaildomain'}{$type}{$chosen} = $emaildom;
                                     if (ref($curremaildom{$type}) eq 'HASH') {                                      if (ref($curremaildom{$type}) eq 'HASH') {
                                         if (exists($curremaildom{$type}{$chosen})) {                                          if (exists($curremaildom{$type}{$chosen})) {
Line 14695  sub modify_selfcreation { Line 18224  sub modify_selfcreation {
                                         }                                          }
                                     } elsif ($emaildom ne '') {                                      } elsif ($emaildom ne '') {
                                         push(@{$changes{'cancreate'}},'emaildomain');                                          push(@{$changes{'cancreate'}},'emaildomain');
                                     }                                      } 
                                 }                                  }
                                 $cancreate{'emailoptions'}{$type} = $env{'form.cancreate_emailoptions_'.$type};                                  $cancreate{'emailoptions'}{$type} = $env{'form.cancreate_emailoptions_'.$type};
                             } elsif ($chosen eq 'custom') {                              } elsif ($chosen eq 'custom') {
Line 15122  sub modify_selfcreation { Line 18651  sub modify_selfcreation {
                                                                   );                                                                    );
                         if (@types) {                          if (@types) {
                             if (@statuses) {                              if (@statuses) {
                                 $chgtext .= &mt('Processing of requests to create account with e-mail verification set as follows:').                                  $chgtext .= &mt('Processing of requests to create account with e-mail verification set as follows:'). 
                                             '<ul>';                                              '<ul>';
                                 foreach my $status (@statuses) {                                  foreach my $status (@statuses) {
                                     if ($status eq 'default') {                                      if ($status eq 'default') {
Line 15208  sub modify_selfcreation { Line 18737  sub modify_selfcreation {
                                                 $output = '<li>'.$usertypes{$type}.' -- '.&mt('No restriction on e-mail domain').'</li>';                                                  $output = '<li>'.$usertypes{$type}.' -- '.&mt('No restriction on e-mail domain').'</li>';
                                             } else {                                              } else {
                                                 $output = '<li>'.$usertypes{$type}.' -- '.&mt("User's e-mail address needs to end: [_1]",                                                  $output = '<li>'.$usertypes{$type}.' -- '.&mt("User's e-mail address needs to end: [_1]",
                                                                                               $cancreate{'emaildomain'}{$type}{'inst'}).'</li>';                                                                                                $cancreate{'emaildomain'}{$type}{'inst'}).'</li>'; 
                                             }                                              }
                                         }                                          }
                                     } elsif ($cancreate{'emailoptions'}{$type} eq 'noninst') {                                      } elsif ($cancreate{'emailoptions'}{$type} eq 'noninst') {
Line 15226  sub modify_selfcreation { Line 18755  sub modify_selfcreation {
                                                 $output = '<li>'.$usertypes{$type}.' -- '.&mt('No restriction on e-mail domain').'</li>';                                                  $output = '<li>'.$usertypes{$type}.' -- '.&mt('No restriction on e-mail domain').'</li>';
                                             } else {                                              } else {
                                                 $output = '<li>'.$usertypes{$type}.' -- '.&mt("User's e-mail address must not end: [_1]",                                                  $output = '<li>'.$usertypes{$type}.' -- '.&mt("User's e-mail address must not end: [_1]",
                                                                                                 $cancreate{'emaildomain'}{$type}{'noninst'}).'</li>';                                                                                                  $cancreate{'emaildomain'}{$type}{'noninst'}).'</li>';   
                                             }                                              }
                                         }                                          }
                                     }                                      }
Line 15330  sub modify_selfcreation { Line 18859  sub modify_selfcreation {
                                 $typename = $othertitle;                                  $typename = $othertitle;
                             } else {                              } else {
                                 $typename = $usertypes{$type};                                  $typename = $usertypes{$type};
                             }                              } 
                             $chgtext .= &mt('(Affiliation: [_1])',$typename);                              $chgtext .= &mt('(Affiliation: [_1])',$typename);
                         }                          }
                         if (@{$email_rule{$type}} > 0) {                          if (@{$email_rule{$type}} > 0) {
Line 15611  sub modify_defaults { Line 19140  sub modify_defaults {
     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');
     my @authtypes = ('internal','krb4','krb5','localauth');      my @authtypes = ('internal','krb4','krb5','localauth','lti');
     foreach my $item (@items) {      foreach my $item (@items) {
         $newvalues{$item} = $env{'form.'.$item};          $newvalues{$item} = $env{'form.'.$item};
         if ($item eq 'auth_def') {          if ($item eq 'auth_def') {
Line 15692  sub modify_defaults { Line 19221  sub modify_defaults {
     my @allpos;      my @allpos;
     my %alltypes;      my %alltypes;
     my @inststatusguest;      my @inststatusguest;
     if (ref($currinststatus) eq 'HASH') {      if (ref($currinststatus->{'inststatusguest'}) eq 'ARRAY') {
         if (ref($currinststatus->{'inststatusguest'}) eq 'ARRAY') {          foreach my $type (@{$currinststatus->{'inststatusguest'}}) {
             foreach my $type (@{$currinststatus->{'inststatusguest'}}) {              unless (grep(/^\Q$type\E$/,@todelete)) {
                 unless (grep(/^\Q$type\E$/,@todelete)) {                  push(@inststatusguest,$type);
                     push(@inststatusguest,$type);  
                 }  
             }              }
         }          }
     }      }
Line 15785  sub modify_defaults { Line 19312  sub modify_defaults {
                             $resulttext =~ s/, $//;                              $resulttext =~ s/, $//;
                             $resulttext .= '</li>';                              $resulttext .= '</li>';
                         } else {                          } else {
                             $resulttext .= '<li>'.&mt('Institutional user status types deleted').'</li>';                              $resulttext .= '<li>'.&mt('Institutional user status types deleted').'</li>'; 
                         }                          }
                     }                      }
                 } else {                  } else {
Line 15799  sub modify_defaults { Line 19326  sub modify_defaults {
                                           krb4       => 'krb4',                                            krb4       => 'krb4',
                                           krb5       => 'krb5',                                            krb5       => 'krb5',
                                           localauth  => 'loc',                                            localauth  => 'loc',
                                             lti        => 'lti',
                         );                          );
                         $value = $authnames{$shortauth{$value}};                          $value = $authnames{$shortauth{$value}};
                     }                      }
Line 16012  sub modify_scantron { Line 19540  sub modify_scantron {
                 &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 .= '<p>'.&mt('The following errors occurred: ').'<ul>'.
                        $errors.'</ul>';                         $errors.'</ul></p>';
     }      }
     return $resulttext;      return $resulttext;
 }  }
Line 16045  sub modify_coursecategories { Line 19573  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 16059  sub modify_coursecategories { Line 19596  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 16081  sub modify_coursecategories { Line 19622  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 16143  sub modify_coursecategories { Line 19687  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 16744  sub modify_coursedefaults { Line 20302  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'
                            'inline_chem'     => 'on',  
                          );                           );
     my @toggles = ('uselcmath','usejsme','inline_chem');      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,
Line 16955  sub modify_coursedefaults { Line 20514  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'}) || ($changes{'texengine'})) {
                 ($changes{'inline_chem'})) {                  foreach my $item ('canuse_pdfforms','uselcmath','usejsme','texengine') {
                 foreach my $item ('uselcmath','usejsme','inline_chem','texengine') {  
                     if ($changes{$item}) {                      if ($changes{$item}) {
                         $domdefaults{$item}=$defaultshash{'coursedefaults'}{$item};                          $domdefaults{$item}=$defaultshash{'coursedefaults'}{$item};
                     }                      }
Line 17010  sub modify_coursedefaults { Line 20568  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 17022  sub modify_coursedefaults { Line 20586  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 'inline_chem') {  
                     if ($env{'form.'.$item} eq '1') {  
                         $resulttext .= '<li>'.&mt('Chemical Reaction Response uses inline previewer').'</li>';  
                     } else {  
                         $resulttext .= '<li>'.&mt('Chemical Reaction Response uses pop-up previewer').'</li>';  
                     }  
                 } elsif ($item eq 'texengine') {                  } elsif ($item eq 'texengine') {
                     if ($defaultshash{'coursedefaults'}{'texengine'} ne '') {                      if ($defaultshash{'coursedefaults'}{'texengine'} ne '') {
                         $resulttext .= '<li>'.&mt('Default method to display mathematics set to: "[_1]"',                          $resulttext .= '<li>'.&mt('Default method to display mathematics set to: "[_1]"',
Line 17041  sub modify_coursedefaults { Line 20599  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 17054  sub modify_coursedefaults { Line 20612  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 17089  sub modify_coursedefaults { Line 20648  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 17140  sub modify_coursedefaults { Line 20701  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 17517  sub modify_wafproxy { Line 21078  sub modify_wafproxy {
                 }                  }
             } elsif ($currvalue{$item}) {              } elsif ($currvalue{$item}) {
                 $changes{$item} = 1;                  $changes{$item} = 1;
             }              } 
         }          }
     } else {      } else {
         if (keys(%curralias)) {          if (keys(%curralias)) {
Line 17525  sub modify_wafproxy { Line 21086  sub modify_wafproxy {
         }          }
         if (keys(%currsaml)) {          if (keys(%currsaml)) {
             $changes{'saml'} = 1;              $changes{'saml'} = 1;
         }          } 
         if (keys(%currvalue)) {          if (keys(%currvalue)) {
             foreach my $key (keys(%currvalue)) {              foreach my $key (keys(%currvalue)) {
                 $changes{$key} = 1;                  $changes{$key} = 1;
Line 17535  sub modify_wafproxy { Line 21096  sub modify_wafproxy {
     if (keys(%changes)) {      if (keys(%changes)) {
         my %defaultshash = (          my %defaultshash = (
                               wafproxy => \%wafproxy,                                wafproxy => \%wafproxy,
                            );                             ); 
         my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,          my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                                  $dom);                                                   $dom);
         if ($putresult eq 'ok') {          if ($putresult eq 'ok') {
Line 17551  sub modify_wafproxy { Line 21112  sub modify_wafproxy {
                         $domdefaults{'waf_'.$item} = $wafproxy{$item};                          $domdefaults{'waf_'.$item} = $wafproxy{$item};
                     } elsif (exists($domdefaults{'waf_'.$item})) {                      } elsif (exists($domdefaults{'waf_'.$item})) {
                         delete($domdefaults{'waf_'.$item});                          delete($domdefaults{'waf_'.$item});
                     }                      } 
                 }                  }
             }              }
             if ($updatedomdefs) {              if ($updatedomdefs) {
Line 17595  sub modify_wafproxy { Line 21156  sub modify_wafproxy {
                 }                  }
             }              }
             $output = &mt('Changes were made to Web Application Firewall/Reverse Proxy').'<ul>';              $output = &mt('Changes were made to Web Application Firewall/Reverse Proxy').'<ul>';
             foreach my $item ('alias','saml','remoteip','ipheader','trusted','vpnint','vpnext','sslopt') {              foreach my $item ('alias','remoteip','ipheader','trusted','vpnint','vpnext','sslopt') {
                 if ($changes{$item}) {                  if ($changes{$item}) {
                     if ($item eq 'alias') {                      if ($item eq 'alias') {
                         my $numaliased = 0;                          my $numaliased = 0;
Line 17618  sub modify_wafproxy { Line 21179  sub modify_wafproxy {
                             $output .= '<li>'.&mt('Aliases deleted for hostnames').'</li>';                              $output .= '<li>'.&mt('Aliases deleted for hostnames').'</li>';
                         }                          }
                     } elsif ($item eq 'saml') {                      } elsif ($item eq 'saml') {
                         my $shown;                          my $shown; 
                         if (ref($wafproxy{'saml'}) eq 'HASH') {                          if (ref($wafproxy{'saml'}) eq 'HASH') {
                             if (keys(%{$wafproxy{'saml'}})) {                              if (keys(%{$wafproxy{'saml'}})) {
                                 $shown = join(', ',sort(keys(%{$wafproxy{'saml'}})));                                  $shown = join(', ',sort(keys(%{$wafproxy{'saml'}})));
Line 17725  sub modify_usersessions { Line 21286  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 17947  sub modify_usersessions { Line 21508  sub modify_usersessions {
                 if (($offload eq 'offloadoth') && (@okoffloadoth)) {                  if (($offload eq 'offloadoth') && (@okoffloadoth)) {
                     $changes{'offloadoth'} = 1;                      $changes{'offloadoth'} = 1;
                 }                  }
             }              } 
         }          }
     } else {      } else {
         if (@okoffload) {          if (@okoffload) {
Line 18015  sub modify_usersessions { Line 21576  sub modify_usersessions {
                         } else {                          } else {
                             foreach my $type (@{$types{$prefix}}) {                              foreach my $type (@{$types{$prefix}}) {
                                 if (defined($changes{$prefix}{$type})) {                                  if (defined($changes{$prefix}{$type})) {
                                     my $newvalue;                                      my ($newvalue,$notinuse);
                                     if (ref($defaultshash{'usersessions'}) eq 'HASH') {                                      if (ref($defaultshash{'usersessions'}) eq 'HASH') {
                                         if (ref($defaultshash{'usersessions'}{$prefix})) {                                          if (ref($defaultshash{'usersessions'}{$prefix})) {
                                             if ($type eq 'version') {                                              if ($type eq 'version') {
                                                 $newvalue = $defaultshash{'usersessions'}{$prefix}{$type};                                                  $newvalue = $defaultshash{'usersessions'}{$prefix}{$type};
                                             } elsif (ref($defaultshash{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {                                              } else {
                                                 if (@{$defaultshash{'usersessions'}{$prefix}{$type}} > 0) {                                                  if (ref($defaultshash{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {
                                                     $newvalue = join(', ',@{$defaultshash{'usersessions'}{$prefix}{$type}});                                                      if (@{$defaultshash{'usersessions'}{$prefix}{$type}} > 0) {
                                                           $newvalue = join(', ',@{$defaultshash{'usersessions'}{$prefix}{$type}});
                                                       }
                                                   } else {
                                                       $notinuse = 1;
                                                 }                                                  }
                                             }                                              }
                                         }                                          }
Line 18030  sub modify_usersessions { Line 21595  sub modify_usersessions {
                                     if ($newvalue eq '') {                                      if ($newvalue eq '') {
                                         if ($type eq 'version') {                                          if ($type eq 'version') {
                                             $resulttext .= '<li>'.&mt('[_1] set to: off',$lt{$type}).'</li>';                                              $resulttext .= '<li>'.&mt('[_1] set to: off',$lt{$type}).'</li>';
                                           } elsif ($notinuse) {
                                               $resulttext .= '<li>'.&mt('[_1] set to: not in use',$lt{$type}).'</li>';
                                         } else {                                          } else {
                                             $resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';                                              $resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';
                                         }                                          }
                                     } else {                                      } else {
                                         if ($type eq 'version') {                                          if ($type eq 'version') {
                                             $newvalue .= ' '.&mt('(or later)');                                               $newvalue .= ' '.&mt('(or later)');
                                         }                                          }
                                         $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';                                          $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';
                                     }                                      }
Line 18089  sub modify_usersessions { Line 21656  sub modify_usersessions {
     return $resulttext;      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}) eq 'HASH') {
                       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;
                       }
                   } 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);
                                   }
                               }
                           } else {
                               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;
                           }
                       }
                   }
               }
           }
       }
       if (keys(%changes)) {
           foreach my $prefix (keys(%changes)) {
               if (ref($changes{$prefix}) eq 'HASH') {
                   if (scalar(keys(%{$changes{$prefix}})) == 0) {
                       delete($changes{$prefix});
                   }
               } else {
                   delete($changes{$prefix});
               }
           }
       }
       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'} = $defaultshash{$action}{'connto'};
                   }
                   if (ref($defaultshash{$action}{'connfrom'}) eq 'HASH') {
                       $domdefaults{'connfrom'} = $defaultshash{$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,$notinuse);
                                   if (ref($defaultshash{$action}) eq 'HASH') {
                                       if (ref($defaultshash{$action}{$prefix})) {
                                           if (($prefix eq 'connto') || ($prefix eq 'connfrom')) {
                                               $newvalue = $titles{$defaultshash{$action}{$prefix}{$type}};
                                           } else {
                                               if (ref($defaultshash{$action}{$prefix}{$type}) eq 'ARRAY') {
                                                   if (@{$defaultshash{$action}{$prefix}{$type}} > 0) {
                                                       $newvalue = join(', ',@{$defaultshash{$action}{$prefix}{$type}});
                                                   }
                                               } else {
                                                   $notinuse = 1;
                                               }
                                           }
                                       }
                                       if ($notinuse) {
                                           $resulttext .= '<li>'.&mt('[_1] set to: not in use',$titles{$type}).'</li>';
                                       } elsif ($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 {
                           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,$notinuse);
                                   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}});
                                               }
                                           } else {
                                               $notinuse = 1;
                                           }
                                       }
                                   }
                                   if ($notinuse) {
                                       $resulttext .= '<li>'.&mt('[_1] set to: not in use',$lt{$type}).'</li>';
                                   } elsif ($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>';
               } else {
                   $resulttext = $nochgmsg;
               }
           } else {
               $resulttext = '<span class="LC_error">'.
                             &mt('An error occurred: [_1]',$putresult).'</span>';
           }
       } else {
           $resulttext = $nochgmsg;
       }
       return $resulttext;
   }
   
 sub modify_loadbalancing {  sub modify_loadbalancing {
     my ($dom,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my $primary_id = &Apache::lonnet::domain($dom,'primary');      my $primary_id = &Apache::lonnet::domain($dom,'primary');
Line 18159  sub modify_loadbalancing { Line 22044  sub modify_loadbalancing {
         }          }
         if ($env{'form.loadbalancing_cookie_'.$i}) {          if ($env{'form.loadbalancing_cookie_'.$i}) {
             $defaultshash{'loadbalancing'}{$balancer}{'cookie'} = 1;              $defaultshash{'loadbalancing'}{$balancer}{'cookie'} = 1;
             if (exists($currbalancer{$balancer})) {              if (exists($currbalancer{$balancer})) { 
                 unless ($currcookies{$balancer}) {                  unless ($currcookies{$balancer}) {
                     $changes{'curr'}{$balancer}{'cookie'} = 1;                      $changes{'curr'}{$balancer}{'cookie'} = 1;
                 }                  }
Line 18845  function balancerChange(balnum,baltotal, Line 22730  function balancerChange(balnum,baltotal,
 END  END
 }  }
   
   
 sub new_spares_js {  sub new_spares_js {
     my @sparestypes = ('primary','default');      my @sparestypes = ('primary','default');
     my $types = join("','",@sparestypes);      my $types = join("','",@sparestypes);
Line 18918  function updateNewSpares(formname,lonhos Line 22804  function updateNewSpares(formname,lonhos
 function checkNewSpares(lonhost,type) {  function checkNewSpares(lonhost,type) {
     var newSpare = document.getElementById('newspare_'+type+'_'+lonhost);      var newSpare = document.getElementById('newspare_'+type+'_'+lonhost);
     var chosen =  newSpare.options[newSpare.selectedIndex].value;      var chosen =  newSpare.options[newSpare.selectedIndex].value;
     if (chosen != '') {       if (chosen != '') {
         var othertype;          var othertype;
         var othernewSpare;          var othernewSpare;
         if (type == 'primary') {          if (type == 'primary') {
Line 19052  function toggleDisplay(domForm,caller) { Line 22938  function toggleDisplay(domForm,caller) {
         var dispval = 'block';          var dispval = 'block';
         var selfcreateRegExp = /^cancreate_emailverified/;          var selfcreateRegExp = /^cancreate_emailverified/;
         if (caller == 'emailoptions') {          if (caller == 'emailoptions') {
             optionsElement = domForm.cancreate_email;               optionsElement = domForm.cancreate_email;
         }          }
         if (caller == 'studentsubmission') {          if (caller == 'studentsubmission') {
             optionsElement = domForm.postsubmit;              optionsElement = domForm.postsubmit;

Removed from v.1.160.6.118.2.1  
changed lines
  Added in v.1.396


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