Diff for /loncom/interface/domainprefs.pm between versions 1.241 and 1.295

version 1.241, 2014/05/05 23:28:53 version 1.295, 2017/03/20 03:19:43
Line 19 Line 19
 #  #
 # You should have received a copy of the GNU General Public License  # You should have received a copy of the GNU General Public License
 # along with LON-CAPA; if not, write to the Free Software  # along with LON-CAPA; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA#  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   #
 # /home/httpd/html/adm/gpl.txt  # /home/httpd/html/adm/gpl.txt
 #  #
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
Line 103  $datatable  - HTML containing form eleme Line 104  $datatable  - HTML containing form eleme
   
 In the case of course requests, radio buttons are displayed for each institutional  In the case of course requests, radio buttons are displayed for each institutional
 affiliate type (and also default, and _LC_adv) for each of the course types   affiliate type (and also default, and _LC_adv) for each of the course types 
 (official, unofficial, community, and textbook).  In each case the radio buttons   (official, unofficial, community, textbook, and placement).  
 allow the selection of one of four values:  In each case the radio buttons allow the selection of one of four values:  
   
 0, approval, validate, autolimit=N (where N is blank, or a positive integer).  0, approval, validate, autolimit=N (where N is blank, or a positive integer).
 which have the following effects:  which have the following effects:
Line 169  use Apache::loncoursequeueadmin(); Line 170  use Apache::loncoursequeueadmin();
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
 use LONCAPA::Enrollment;  use LONCAPA::Enrollment;
 use LONCAPA::lonauthcgi();  use LONCAPA::lonauthcgi();
   use LONCAPA::SSL;
 use File::Copy;  use File::Copy;
 use Locale::Language;  use Locale::Language;
 use DateTime::TimeZone;  use DateTime::TimeZone;
 use DateTime::Locale;  use DateTime::Locale;
   use Time::HiRes qw( sleep );
   
 my $registered_cleanup;  my $registered_cleanup;
 my $modified_urls;  my $modified_urls;
Line 215  sub handler { Line 218  sub handler {
                 'contacts','defaults','scantron','coursecategories',                  'contacts','defaults','scantron','coursecategories',
                 'serverstatuses','requestcourses','helpsettings',                  'serverstatuses','requestcourses','helpsettings',
                 'coursedefaults','usersessions','loadbalancing',                  'coursedefaults','usersessions','loadbalancing',
                 'requestauthor','selfenrollment','inststatus'],$dom);                  'requestauthor','selfenrollment','inststatus',
                   'ltitools','ssl','trust'],$dom);
     my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',      my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
                        'autoupdate','autocreate','directorysrch','contacts',                         'autoupdate','autocreate','directorysrch','contacts',
                        'usercreation','selfcreation','usermodification','scantron',                         'usercreation','selfcreation','usermodification','scantron',
                        'requestcourses','requestauthor','coursecategories',                         'requestcourses','requestauthor','coursecategories',
                        'serverstatuses','helpsettings',                         'serverstatuses','helpsettings','coursedefaults',
                        'coursedefaults','selfenrollment','usersessions');                         'ltitools','selfenrollment','usersessions','ssl','trust');
     my %existing;      my %existing;
     if (ref($domconfig{'loadbalancing'}) eq 'HASH') {      if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
         %existing = %{$domconfig{'loadbalancing'}};          %existing = %{$domconfig{'loadbalancing'}};
Line 250  sub handler { Line 254  sub handler {
                       header => [{col1 => 'Log-in Page Items',                        header => [{col1 => 'Log-in Page Items',
                                   col2 => '',},                                    col2 => '',},
                                  {col1 => 'Log-in Help',                                   {col1 => 'Log-in Help',
                                     col2 => 'Value'},
                                    {col1 => 'Custom HTML in document head',
                                   col2 => 'Value'}],                                    col2 => 'Value'}],
                       print => \&print_login,                        print => \&print_login,
                       modify => \&modify_login,                        modify => \&modify_login,
Line 259  sub handler { Line 265  sub handler {
                       help => 'Domain_Configuration_LangTZAuth',                        help => 'Domain_Configuration_LangTZAuth',
                       header => [{col1 => 'Setting',                        header => [{col1 => 'Setting',
                                   col2 => 'Value'},                                    col2 => 'Value'},
                                    {col1 => 'Internal Authentication',
                                     col2 => 'Value'},
                                  {col1 => 'Institutional user types',                                   {col1 => 'Institutional user types',
                                   col2 => 'Assignable to e-mail usernames'}],                                    col2 => 'Assignable to e-mail usernames'}],
                       print => \&print_defaults,                        print => \&print_defaults,
Line 302  sub handler { Line 310  sub handler {
                      modify => \&modify_autocreate,                       modify => \&modify_autocreate,
                   },                    },
         'directorysrch' =>           'directorysrch' => 
                   { text => 'Institutional directory searches',                    { text => 'Directory searches',
                     help => 'Domain_Configuration_InstDirectory_Search',                      help => 'Domain_Configuration_InstDirectory_Search',
                     header => [{col1 => 'Setting',                      header => [{col1 => 'Institutional Directory Setting',
                                   col2 => 'Value',},
                                  {col1 => 'LON-CAPA Directory Setting',
                                 col2 => 'Value',}],                                  col2 => 'Value',}],
                     print => \&print_directorysrch,                      print => \&print_directorysrch,
                     modify => \&modify_directorysrch,                      modify => \&modify_directorysrch,
                   },                    },
         'contacts' =>          'contacts' =>
                   { text => 'Contact Information',                    { text => 'E-mail addresses and helpform',
                     help => 'Domain_Configuration_Contact_Info',                      help => 'Domain_Configuration_Contact_Info',
                     header => [{col1 => 'Setting',                      header => [{col1 => 'Default e-mail addresses',
                                 col2 => 'Value',}],                                  col2 => 'Value',},
                                  {col1 => 'Recipient(s) for notifications',
                                   col2 => 'Value',},
                                  {col1 => 'Ask helpdesk form settings',
                                   col2 => 'Value',},],
                     print => \&print_contacts,                      print => \&print_contacts,
                     modify => \&modify_contacts,                      modify => \&modify_contacts,
                   },                    },
Line 369  sub handler { Line 383  sub handler {
                               col2 => 'Value'},                                col2 => 'Value'},
                              {col1 => 'Available textbooks',                               {col1 => 'Available textbooks',
                               col2 => ''},                                col2 => ''},
                                {col1 => 'Available templates',
                                 col2 => ''},
                              {col1 => 'Validation (not official courses)',                               {col1 => 'Validation (not official courses)',
                               col2 => 'Value'},],                                col2 => 'Value'},],
                   print => \&print_quotas,                    print => \&print_quotas,
Line 408  sub handler { Line 424  sub handler {
                   modify => \&modify_serverstatuses,                    modify => \&modify_serverstatuses,
                  },                   },
         'helpsettings' =>          'helpsettings' =>
                  {text   => 'Help page settings',                   {text   => 'Support settings',
                   help   => 'Domain_Configuration_Help_Settings',                    help   => 'Domain_Configuration_Help_Settings',
                   header => [{col1 => 'Help Settings (logged-in users)',                    header => [{col1 => 'Help Page Settings (logged-in users)',
                               col2 => 'Value'}],                                col2 => 'Value'},
                                {col1 => 'Helpdesk Roles',
                                 col2 => 'Settings'},],
                   print  => \&print_helpsettings,                    print  => \&print_helpsettings,
                   modify => \&modify_helpsettings,                    modify => \&modify_helpsettings,
                  },                   },
Line 457  sub handler { Line 475  sub handler {
                   print => \&print_usersessions,                    print => \&print_usersessions,
                   modify => \&modify_usersessions,                    modify => \&modify_usersessions,
                  },                   },
          'loadbalancing' =>          'loadbalancing' =>
                  {text  => 'Dedicated Load Balancer(s)',                   {text  => 'Dedicated Load Balancer(s)',
                   help  => 'Domain_Configuration_Load_Balancing',                    help  => 'Domain_Configuration_Load_Balancing',
                   header => [{col1 => 'Balancers',                    header => [{col1 => 'Balancers',
Line 468  sub handler { Line 486  sub handler {
                   print => \&print_loadbalancing,                    print => \&print_loadbalancing,
                   modify => \&modify_loadbalancing,                    modify => \&modify_loadbalancing,
                  },                   },
           'ltitools' => 
                    {text => 'External Tools (LTI)',
                     help => 'Domain_configuration_LTI_Tools',
                     header => [{col1 => 'Setting',
                                 col2 => 'Value',}],
                     print => \&print_ltitools,
                     modify => \&modify_ltitools,
                    },
           'ssl' =>
                    {text  => 'LON-CAPA Network (SSL)',
                     help  => 'Domain_Configuration_Network_SSL',
                     header => [{col1 => 'Server',
                                 col2 => 'Certificate Status'},
                                {col1 => 'Connections to other servers',
                                 col2 => 'Rules'},
                                {col1 => 'Connections from other servers',
                                 col2 => 'Rules'},
                                {col1 => "Replicating domain's published content",
                                 col2 => 'Rules'}],
                     print => \&print_ssl,
                     modify => \&modify_ssl,
                    },
           'trust' =>
                    {text   => 'Trust Settings',
                     help   => 'Domain_Configuration_Trust',
                     header => [{col1 => "Access to this domain's content by others",
                                 col2 => 'Rules'},
                                {col1 => "Access to other domain's content by this domain",
                                 col2 => 'Rules'},
                                {col1 => "Enrollment in this domain's courses by others",
                                 col2 => 'Rules',},
                                {col1 => "Co-author roles in this domain for others",
                                 col2 => 'Rules',},
                                {col1 => "Co-author roles for this domain's users elsewhere",
                                 col2 => 'Rules',},
                                {col1 => "Domain roles in this domain assignable to others",
                                 col2 => 'Rules'},
                                {col1 => "Course catalog for this domain displayed elsewhere",
                                 col2 => 'Rules'},
                                {col1 => "Requests for creation of courses in this domain by others",
                                 col2 => 'Rules'},
                                {col1 => "Users in other domains can send messages to this domain",
                                 col2 => 'Rules'},],
                     print => \&print_trust,
                     modify => \&modify_trust,
                    },
     );      );
     if (keys(%servers) > 1) {      if (keys(%servers) > 1) {
         $prefs{'login'}  = { text   => 'Log-in page options',          $prefs{'login'}  = { text   => 'Log-in page options',
Line 477  sub handler { Line 541  sub handler {
                                        {col1 => 'Log-in Page Items',                                         {col1 => 'Log-in Page Items',
                                         col2 => ''},                                          col2 => ''},
                                        {col1 => 'Log-in Help',                                         {col1 => 'Log-in Help',
                                           col2 => 'Value'},
                                          {col1 => 'Custom HTML in document head',
                                         col2 => 'Value'}],                                          col2 => 'Value'}],
                             print => \&print_login,                              print => \&print_login,
                             modify => \&modify_login,                              modify => \&modify_login,
Line 519  $javascript_validations Line 585  $javascript_validations
 $coursebrowserjs  $coursebrowserjs
 END  END
         }          }
           if (grep(/^contacts$/,@actions)) {
               $js .= &contacts_javascript();
           }
         &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);          &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);
     } else {      } else {
 # check if domconfig user exists for the domain.  # check if domconfig user exists for the domain.
Line 608  sub process_changes { Line 677  sub process_changes {
     } elsif ($action eq 'autocreate') {      } elsif ($action eq 'autocreate') {
         $output = &modify_autocreate($dom,%domconfig);          $output = &modify_autocreate($dom,%domconfig);
     } elsif ($action eq 'directorysrch') {      } elsif ($action eq 'directorysrch') {
         $output = &modify_directorysrch($dom,%domconfig);          $output = &modify_directorysrch($dom,$lastactref,%domconfig);
     } elsif ($action eq 'usercreation') {      } elsif ($action eq 'usercreation') {
         $output = &modify_usercreation($dom,%domconfig);          $output = &modify_usercreation($dom,%domconfig);
     } elsif ($action eq 'selfcreation') {      } elsif ($action eq 'selfcreation') {
Line 630  sub process_changes { Line 699  sub process_changes {
     } elsif ($action eq 'requestauthor') {      } elsif ($action eq 'requestauthor') {
         $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);          $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);
     } elsif ($action eq 'helpsettings') {      } elsif ($action eq 'helpsettings') {
         $output = &modify_helpsettings($r,$dom,$confname,%domconfig);          $output = &modify_helpsettings($r,$dom,$confname,$lastactref,%domconfig);
     } elsif ($action eq 'coursedefaults') {      } elsif ($action eq 'coursedefaults') {
         $output = &modify_coursedefaults($dom,$lastactref,%domconfig);          $output = &modify_coursedefaults($dom,$lastactref,%domconfig);
     } elsif ($action eq 'selfenrollment') {      } elsif ($action eq 'selfenrollment') {
Line 639  sub process_changes { Line 708  sub process_changes {
         $output = &modify_usersessions($dom,$lastactref,%domconfig);          $output = &modify_usersessions($dom,$lastactref,%domconfig);
     } elsif ($action eq 'loadbalancing') {      } elsif ($action eq 'loadbalancing') {
         $output = &modify_loadbalancing($dom,%domconfig);          $output = &modify_loadbalancing($dom,%domconfig);
       } elsif ($action eq 'ltitools') {
           $output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig);
       } elsif ($action eq 'ssl') {
           $output = &modify_ssl($dom,$lastactref,%domconfig);
       } elsif ($action eq 'trust') {
           $output = &modify_trust($dom,$lastactref,%domconfig);
     }      }
     return $output;      return $output;
 }  }
Line 651  sub print_config_box { Line 726  sub print_config_box {
         $output = &coursecategories_javascript($settings);          $output = &coursecategories_javascript($settings);
     } elsif ($action eq 'defaults') {      } elsif ($action eq 'defaults') {
         $output = &defaults_javascript($settings);           $output = &defaults_javascript($settings); 
       } elsif ($action eq 'helpsettings') {
           my (%privs,%levelscurrent);
           my %full=();
           my %levels=(
                        course => {},
                        domain => {},
                        system => {},
                      );
           my $context = 'domain';
           my $crstype = 'Course';
           my $formname = 'display';
           &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
           my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
           $output =
               &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full, 
                                                         \@templateroles);
     }      }
     $output .=      $output .=
          '<table class="LC_nested_outer">           '<table class="LC_nested_outer">
Line 668  sub print_config_box { Line 759  sub print_config_box {
         my $colspan = '';          my $colspan = '';
         my $rightcolspan = '';          my $rightcolspan = '';
         if (($action eq 'rolecolors') || ($action eq 'defaults') ||          if (($action eq 'rolecolors') || ($action eq 'defaults') ||
             (($action eq 'login') && ($numheaders < 3))) {              ($action eq 'directorysrch') ||
               (($action eq 'login') && ($numheaders < 4))) {
             $colspan = ' colspan="2"';              $colspan = ' colspan="2"';
         }          }
         if ($action eq 'usersessions') {          if ($action eq 'usersessions') {
Line 685  sub print_config_box { Line 777  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 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'ssl') ||
               ($action eq 'directorysrch') || ($action eq 'trust') || ($action eq 'helpsettings') ||
               ($action eq 'contacts')) {
             $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);              $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'coursecategories') {          } elsif ($action eq 'coursecategories') {
             $output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal);              $output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal);
         } elsif ($action eq 'login') {          } elsif ($action eq 'login') {
             if ($numheaders == 3) {              if ($numheaders == 4) {
                 $colspan = ' colspan="2"';                  $colspan = ' colspan="2"';
                 $output .= &print_login('service',$dom,$confname,$phase,$settings,\$rowtotal);                  $output .= &print_login('service',$dom,$confname,$phase,$settings,\$rowtotal);
             } else {              } else {
Line 715  sub print_config_box { Line 809  sub print_config_box {
             $rowtotal ++;              $rowtotal ++;
         if (($action eq 'autoupdate') || ($action eq 'usercreation') ||          if (($action eq 'autoupdate') || ($action eq 'usercreation') ||
             ($action eq 'selfcreation') || ($action eq 'selfenrollment') ||              ($action eq 'selfcreation') || ($action eq 'selfenrollment') ||
             ($action eq 'usersessions') || ($action eq 'coursecategories')) {              ($action eq 'usersessions') || ($action eq 'coursecategories') || 
               ($action eq 'trust') || ($action eq 'contacts') || ($action eq 'defaults')) {
             if ($action eq 'coursecategories') {              if ($action eq 'coursecategories') {
                 $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);                  $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);
                 $colspan = ' colspan="2"';                  $colspan = ' colspan="2"';
               } elsif ($action eq 'trust') {
                   $output .= $item->{'print'}->('shared',$dom,$settings,\$rowtotal);
             } else {              } else {
                 $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);                  $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);
             }              }
             $output .= '              if ($action eq 'trust') {
                   $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 733  sub print_config_box { Line 859  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);
             } 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') ||
                   ($action eq 'defaults')) {                   ($action eq 'defaults') || ($action eq 'directorysrch') ||
                    ($action eq 'helpsettings')) {
             $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);              $output .= $item->{'print'}->('bottom',$dom,$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 == 3) {              if ($numheaders == 4) {
                 $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'                  $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'
            </table>             </table>
           </td>            </td>
Line 759  sub print_config_box { Line 909  sub print_config_box {
             } else {              } else {
                 $output .= &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);                  $output .= &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);
             }              }
               $output .= '
              </table>
             </td>
            </tr>
            <tr>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">';
               if ($numheaders == 4) {
                   $output .= '
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
                 <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td>
                </tr>';
               } else {
                   $output .= '
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
                 <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
                </tr>';
               }
               $rowtotal ++;
               $output .= &print_login('headtag',$dom,$confname,$phase,$settings,\$rowtotal);
         } elsif ($action eq 'requestcourses') {          } elsif ($action eq 'requestcourses') {
             $output .= &print_requestmail($dom,$action,$settings,\$rowtotal).              $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);
                        &print_studentcode($settings,\$rowtotal).'              $rowtotal ++;
               $output .= &print_studentcode($settings,\$rowtotal).'
            </table>             </table>
           </td>            </td>
          </tr>           </tr>
Line 771  sub print_config_box { Line 943  sub print_config_box {
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td> </tr>'.                <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td> </tr>'.
                        &print_textbookcourses($dom,$settings,\$rowtotal).'                         &textbookcourses_javascript($settings).
                          &print_textbookcourses($dom,'textbooks',$settings,\$rowtotal).'
               </table>
              </td>
             </tr>
            <tr>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
                 <td class="LC_right_item">'.&mt($item->{'header'}->[3]->{'col2'}).'</td> </tr>'.
                          &print_textbookcourses($dom,'templates',$settings,\$rowtotal).'
             </table>              </table>
            </td>             </td>
           </tr>            </tr>
Line 779  sub print_config_box { Line 962  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'}->[3]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.' valign="top">'.&mt($item->{'header'}->[4]->{'col1'}).'</td>
               <td class="LC_right_item" valign="top">'.&mt($item->{'header'}->[3]->{'col2'}).'</td>                <td class="LC_right_item" valign="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') {
             $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);              $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);
               $rowtotal ++;
         } elsif ($action eq 'rolecolors') {          } elsif ($action eq 'rolecolors') {
             $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'              $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'
            </table>             </table>
Line 819  sub print_config_box { Line 1003  sub print_config_box {
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">';               <tr class="LC_info_row">';
         if (($action eq 'login') || ($action eq 'directorysrch')) {          if ($action eq 'login') {
             $output .= '                $output .= '  
               <td class="LC_left_item" colspan="2">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';                <td class="LC_left_item" colspan="2">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
         } elsif ($action eq 'serverstatuses') {          } elsif ($action eq 'serverstatuses') {
Line 863  sub print_config_box { Line 1047  sub print_config_box {
         $rowtotal ++;          $rowtotal ++;
         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') || ($action eq 'directorysrch') ||          } elsif (($action eq 'autoenroll') || ($action eq 'autocreate') || 
                  ($action eq 'contacts') || ($action eq 'serverstatuses') || ($action eq 'loadbalancing')) {                   ($action eq 'serverstatuses') || ($action eq 'loadbalancing') || 
                    ($action eq 'ltitools')) {
             $output .= $item->{'print'}->($dom,$settings,\$rowtotal);              $output .= $item->{'print'}->($dom,$settings,\$rowtotal);
         } elsif ($action eq 'scantron') {          } elsif ($action eq 'scantron') {
             $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);              $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);
         } elsif ($action eq 'helpsettings') {  
             $output .= &print_helpsettings($dom,$confname,$settings,\$rowtotal);  
         }          }
     }      }
     $output .= '      $output .= '
Line 1166  sub print_login { Line 1349  sub print_login {
             $itemcount ++;              $itemcount ++;
         }          }
         $datatable .= &captcha_choice('login',$settings,$itemcount);          $datatable .= &captcha_choice('login',$settings,$itemcount);
       } elsif ($caller eq 'headtag') {
           my %domservers = &Apache::lonnet::get_servers($dom);
           my $choice = $choices{'headtag'};
           $css_class = ' class="LC_odd_row"';
           $datatable .= '<tr'.$css_class.'><td colspan="2">'.$choice.'</td>'.
                         '<td align="left"><table><tr><th>'.$choices{'hostid'}.'</th>'.
                         '<th>'.$choices{'current'}.'</th>'.
                         '<th>'.$choices{'action'}.'</th>'.
                         '<th>'.$choices{'exempt'}.'</th></tr>'."\n";
           my (%currurls,%currexempt);
           if (ref($settings) eq 'HASH') {
               if (ref($settings->{'headtag'}) eq 'HASH') {
                   foreach my $lonhost (keys(%{$settings->{'headtag'}})) {
                       if (ref($settings->{'headtag'}{$lonhost}) eq 'HASH') {
                           $currurls{$lonhost} = $settings->{'headtag'}{$lonhost}{'url'};
                           $currexempt{$lonhost} = $settings->{'headtag'}{$lonhost}{'exempt'};
                       }
                   }
               }
           }
           my %lt = &Apache::lonlocal::texthash(
                                                  del  => 'Delete?',
                                                  rep  => 'Replace:',
                                                  upl  => 'Upload:',
                                                  curr => 'View contents',
                                                  none => 'None',
           );
           my $switchserver = &check_switchserver($dom,$confname);
           foreach my $lonhost (sort(keys(%domservers))) {
               my $exempt = &check_exempt_addresses($currexempt{$lonhost});
               $datatable .= '<tr><td>'.$domservers{$lonhost}.'</td>';
               if ($currurls{$lonhost}) {
                   $datatable .= '<td class="LC_right_item"><a href="'.
                                 "javascript:void(open('$currurls{$lonhost}?inhibitmenu=yes','Custom_HeadTag',
                                 'menubar=0,toolbar=1,scrollbars=1,width=600,height=500,resizable=yes'))".
                                 '">'.$lt{'curr'}.'</a></td>'.
                                 '<td><span class="LC_nobreak"><label>'.
                                 '<input type="checkbox" name="loginheadtag_del" value="'.$lonhost.'" />'.
                                 $lt{'del'}.'</label>&nbsp;'.$lt{'rep'}.'</span>';
               } else {
                   $datatable .= '<td class="LC_right_item">'.$lt{'none'}.'</td><td>'.$lt{'upl'};
               }
               $datatable .='<br />';
               if ($switchserver) {
                   $datatable .= &mt('Upload to library server: [_1]',$switchserver);
               } else {
                   $datatable .= '<input type="file" name="loginheadtag_'.$lonhost.'" />';
               }
               $datatable .= '</td><td><input type="textbox" name="loginheadtagexempt_'.$lonhost.'" value="'.$exempt.'" /></td></tr>';
           }
           $datatable .= '</table></td></tr>';
     }      }
     return $datatable;      return $datatable;
 }  }
Line 1199  sub login_choices { Line 1433  sub login_choices {
             link          => "Link",              link          => "Link",
             alink         => "Active link",              alink         => "Active link",
             vlink         => "Visited link",              vlink         => "Visited link",
               headtag       => "Custom markup",
               action        => "Action",
               current       => "Current",
         );          );
     return %choices;      return %choices;
 }  }
Line 1616  sub print_quotas { Line 1853  sub print_quotas {
     my $typecount = 0;      my $typecount = 0;
     my ($css_class,%titles);      my ($css_class,%titles);
     if ($context eq 'requestcourses') {      if ($context eq 'requestcourses') {
         @usertools = ('official','unofficial','community','textbook');          @usertools = ('official','unofficial','community','textbook','placement');
         @options =('norequest','approval','validate','autolimit');          @options =('norequest','approval','validate','autolimit');
         %validations = &Apache::lonnet::auto_courserequest_checks($dom);          %validations = &Apache::lonnet::auto_courserequest_checks($dom);
         %titles = &courserequest_titles();          %titles = &courserequest_titles();
Line 2061  sub print_requestmail { Line 2298  sub print_requestmail {
         $datatable .= &mt('There are no active Domain Coordinators');          $datatable .= &mt('There are no active Domain Coordinators');
     }      }
     $datatable .='</td></tr>';      $datatable .='</td></tr>';
     $$rowtotal += $rows;  
     return $datatable;      return $datatable;
 }  }
   
Line 2069  sub print_studentcode { Line 2305  sub print_studentcode {
     my ($settings,$rowtotal) = @_;      my ($settings,$rowtotal) = @_;
     my $rownum = 0;       my $rownum = 0; 
     my ($output,%current);      my ($output,%current);
     my @crstypes = ('official','unofficial','community','textbook');      my @crstypes = ('official','unofficial','community','textbook','placement');
     if (ref($settings->{'uniquecode'}) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         foreach my $type (@crstypes) {          if (ref($settings->{'uniquecode'}) eq 'HASH') {
             $current{$type} = $settings->{'uniquecode'}{$type};              foreach my $type (@crstypes) {
                   $current{$type} = $settings->{'uniquecode'}{$type};
               }
         }          }
     }      }
     $output .= '<tr>'.      $output .= '<tr>'.
Line 2093  sub print_studentcode { Line 2331  sub print_studentcode {
 }  }
   
 sub print_textbookcourses {  sub print_textbookcourses {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$type,$settings,$rowtotal) = @_;
     my $rownum = 0;      my $rownum = 0;
     my $css_class;      my $css_class;
     my $itemcount = 1;      my $itemcount = 1;
     my $maxnum = 0;      my $maxnum = 0;
     my $bookshash;      my $bookshash;
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         $bookshash = $settings->{'textbooks'};          $bookshash = $settings->{$type};
     }      }
     my %ordered;      my %ordered;
     if (ref($bookshash) eq 'HASH') {      if (ref($bookshash) eq 'HASH') {
Line 2113  sub print_textbookcourses { Line 2351  sub print_textbookcourses {
     }      }
     my $confname = $dom.'-domainconfig';      my $confname = $dom.'-domainconfig';
     my $switchserver = &check_switchserver($dom,$confname);      my $switchserver = &check_switchserver($dom,$confname);
     $maxnum = scalar(keys(%ordered));      my $maxnum = scalar(keys(%ordered));
     my $datatable = &textbookcourses_javascript(\%ordered);      my $datatable;
     if (keys(%ordered)) {      if (keys(%ordered)) {
         my @items = sort { $a <=> $b } keys(%ordered);          my @items = sort { $a <=> $b } keys(%ordered);
         for (my $i=0; $i<@items; $i++) {          for (my $i=0; $i<@items; $i++) {
Line 2122  sub print_textbookcourses { Line 2360  sub print_textbookcourses {
             my $key = $ordered{$items[$i]};              my $key = $ordered{$items[$i]};
             my %coursehash=&Apache::lonnet::coursedescription($key);              my %coursehash=&Apache::lonnet::coursedescription($key);
             my $coursetitle = $coursehash{'description'};              my $coursetitle = $coursehash{'description'};
             my ($subject,$title,$author,$image,$imgsrc,$cdom,$cnum);              my ($subject,$title,$author,$publisher,$image,$imgsrc,$cdom,$cnum);
             if (ref($bookshash->{$key}) eq 'HASH') {              if (ref($bookshash->{$key}) eq 'HASH') {
                 $subject = $bookshash->{$key}->{'subject'};                  $subject = $bookshash->{$key}->{'subject'};
                 $title = $bookshash->{$key}->{'title'};                  $title = $bookshash->{$key}->{'title'};
                 $author = $bookshash->{$key}->{'author'};                  if ($type eq 'textbooks') {
                 $image = $bookshash->{$key}->{'image'};                      $publisher = $bookshash->{$key}->{'publisher'};
                 if ($image ne '') {                      $author = $bookshash->{$key}->{'author'};
                     my ($path,$imagefile) = ($image =~ m{^(.+)/([^/]+)$});                      $image = $bookshash->{$key}->{'image'};
                     my $imagethumb = "$path/tn-".$imagefile;                      if ($image ne '') {
                     $imgsrc = '<img src="'.$imagethumb.'" alt="'.&mt('Textbook image').'" />';                          my ($path,$imagefile) = ($image =~ m{^(.+)/([^/]+)$});
                           my $imagethumb = "$path/tn-".$imagefile;
                           $imgsrc = '<img src="'.$imagethumb.'" alt="'.&mt('Textbook image').'" />';
                       }
                 }                  }
             }              }
             my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$key'".');"';              my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$type".'_'."$key','$type'".');"';
             $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'              $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
                          .'<select name="'.$key.'"'.$chgstr.'>';                           .'<select name="'.$type.'_'.$key.'"'.$chgstr.'>';
             for (my $k=0; $k<=$maxnum; $k++) {              for (my $k=0; $k<=$maxnum; $k++) {
                 my $vpos = $k+1;                  my $vpos = $k+1;
                 my $selstr;                  my $selstr;
Line 2146  sub print_textbookcourses { Line 2387  sub print_textbookcourses {
                 $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';                  $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
             }              }
             $datatable .= '</select>'.('&nbsp;'x2).              $datatable .= '</select>'.('&nbsp;'x2).
                 '<label><input type="checkbox" name="book_del" value="'.$key.'" />'.                  '<label><input type="checkbox" name="'.$type.'_del" value="'.$key.'" />'.
                 &mt('Delete?').'</label></span></td>'.                  &mt('Delete?').'</label></span></td>'.
                 '<td colspan="2">'.                  '<td colspan="2">'.
                 '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="book_subject_'.$i.'" value="'.$subject.'" /></span> '.                  '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_subject_'.$i.'" value="'.$subject.'" /></span> '.
                 ('&nbsp;'x2).  
                 '<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="book_title_'.$i.'" value="'.$title.'" /></span> '.  
                 ('&nbsp;'x2).  
                 '<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="book_author_'.$i.'" value="'.$author.'" /></span> '.  
                 ('&nbsp;'x2).                  ('&nbsp;'x2).
                 '<span class="LC_nobreak">'.&mt('Thumbnail:');                  '<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="'.$type.'_title_'.$i.'" value="'.$title.'" /></span> ';
             if ($image) {              if ($type eq 'textbooks') {
                 $datatable .= '<span class="LC_nobreak">'.                  $datatable .= ('&nbsp;'x2).
                               $imgsrc.                                '<span class="LC_nobreak">'.&mt('Publisher:').'<input type="text" size="10" name="'.$type.'_publisher_'.$i.'" value="'.$publisher.'" /></span> '.
                               '<label><input type="checkbox" name="book_image_del"'.                                ('&nbsp;'x2).
                               ' value="'.$key.'" />'.&mt('Delete?').'</label></span> '.                                '<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="'.$type.'_author_'.$i.'" value="'.$author.'" /></span> '.
                               '<span class="LC_nobreak">&nbsp;'.&mt('Replace:').'&nbsp;';                                ('&nbsp;'x2).
             }                                '<span class="LC_nobreak">'.&mt('Thumbnail:');
             if ($switchserver) {                  if ($image) {
                 $datatable .= &mt('Upload to library server: [_1]',$switchserver);                      $datatable .= $imgsrc.
             } else {                                    '<label><input type="checkbox" name="'.$type.'_image_del"'.
                 $datatable .= '<input type="file" name="book_image_'.$i.'" value="" />';                                    ' value="'.$key.'" />'.&mt('Delete?').'</label></span> '.
                                     '<span class="LC_nobreak">&nbsp;'.&mt('Replace:').'&nbsp;';
                   }
                   if ($switchserver) {
                       $datatable .= &mt('Upload to library server: [_1]',$switchserver);
                   } else {
                       $datatable .= '<input type="file" name="'.$type.'_image_'.$i.'" value="" />';
                   }
             }              }
             $datatable .= '<input type="hidden" name="book_id_'.$i.'" value="'.$key.'" /></span> '.              $datatable .= '<input type="hidden" name="'.$type.'_id_'.$i.'" value="'.$type.'_'.$key.'" /></span> '.
                           '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.                            '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.
                           $coursetitle.'</span></td></tr>'."\n";                            $coursetitle.'</span></td></tr>'."\n";
             $itemcount ++;              $itemcount ++;
         }          }
     }      }
     $css_class = $itemcount%2?' class="LC_odd_row"':'';      $css_class = $itemcount%2?' class="LC_odd_row"':'';
     my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'addbook_pos'".');"';      my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$type"."_addbook_pos','$type'".');"';
     $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".      $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
                   '<input type="hidden" name="book_maxnum" value="'.$maxnum.'" />'."\n".                    '<input type="hidden" name="'.$type.'_maxnum" value="'.$maxnum.'" />'."\n".
                   '<select name="addbook_pos"'.$chgstr.'>';                    '<select name="'.$type.'_addbook_pos"'.$chgstr.'>';
     for (my $k=0; $k<$maxnum+1; $k++) {      for (my $k=0; $k<$maxnum+1; $k++) {
         my $vpos = $k+1;          my $vpos = $k+1;
         my $selstr;          my $selstr;
Line 2188  sub print_textbookcourses { Line 2432  sub print_textbookcourses {
         $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';          $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
     }      }
     $datatable .= '</select>&nbsp;'."\n".      $datatable .= '</select>&nbsp;'."\n".
                   '<input type="checkbox" name="addbook" value="1" />'.&mt('Add').'</td>'."\n".                    '<input type="checkbox" name="'.$type.'_addbook" value="1" />'.&mt('Add').'</td>'."\n".
                   '<td colspan="2">'.                    '<td colspan="2">'.
                   '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="addbook_subject" value="" /></span> '."\n".                    '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_addbook_subject" value="" /></span> '."\n".
                   ('&nbsp;'x2).  
                   '<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="addbook_title" value="" /></span> '."\n".  
                   ('&nbsp;'x2).                    ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="addbook_author" value="" /></span> '."\n".                    '<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="'.$type.'_addbook_title" value="" /></span> '."\n".
                   ('&nbsp;'x2).                    ('&nbsp;'x2);
                   '<span class="LC_nobreak">'.&mt('Image:').'&nbsp;';      if ($type eq 'textbooks') {
     if ($switchserver) {          $datatable .= '<span class="LC_nobreak">'.&mt('Publisher:').'<input type="text" size="10" name="'.$type.'_addbook_publisher" value="" /></span> '."\n".
         $datatable .= &mt('Upload to library server: [_1]',$switchserver);                        ('&nbsp;'x2).
     } else {                        '<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="'.$type.'_addbook_author" value="" /></span> '."\n".
         $datatable .= '<input type="file" name="addbook_image" value="" />';                        ('&nbsp;'x2).
                         '<span class="LC_nobreak">'.&mt('Image:').'&nbsp;';
           if ($switchserver) {
               $datatable .= &mt('Upload to library server: [_1]',$switchserver);
           } else {
               $datatable .= '<input type="file" name="'.$type.'_addbook_image" value="" />';
           }
     }      }
     $datatable .= '</span>'."\n".      $datatable .= '</span>'."\n".
                   '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.                    '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.
                   &Apache::loncommon::select_dom_form($env{'request.role.domain'},'addbook_cdom').                    &Apache::loncommon::select_dom_form($env{'request.role.domain'},$type.'_addbook_cdom').
                   '<input type="text" size="25" name="addbook_cnum" value="" />'.                    '<input type="text" size="25" name="'.$type.'_addbook_cnum" value="" />'.
                   &Apache::loncommon::selectcourse_link                    &Apache::loncommon::selectcourse_link
                       ('display','addbook_cnum','addbook_cdom',undef,undef,undef,'Course');                        ('display',$type.'_addbook_cnum',$type.'_addbook_cdom',undef,undef,undef,'Course');
                   '</span></td>'."\n".                    '</span></td>'."\n".
                   '</tr>'."\n";                    '</tr>'."\n";
     $itemcount ++;      $itemcount ++;
Line 2215  sub print_textbookcourses { Line 2463  sub print_textbookcourses {
 }  }
   
 sub textbookcourses_javascript {  sub textbookcourses_javascript {
     my ($textbooks) = @_;      my ($settings) = @_;
     return unless(ref($textbooks) eq 'HASH');      return unless(ref($settings) eq 'HASH');
     my $num = scalar(keys(%{$textbooks}));      my (%ordered,%total,%jstext);
     my @jsarray;      foreach my $type ('textbooks','templates') {
     foreach my $item (sort {$a <=> $b } (keys(%{$textbooks}))) {          $total{$type} = 0;
         push(@jsarray,$textbooks->{$item});          if (ref($settings->{$type}) eq 'HASH') {
               foreach my $item (keys(%{$settings->{$type}})) {
                   if (ref($settings->{$type}->{$item}) eq 'HASH') {
                       my $num = $settings->{$type}->{$item}{'order'};
                       $ordered{$type}{$num} = $item;
                   }
               }
               $total{$type} = scalar(keys(%{$settings->{$type}}));
           }
           my @jsarray = ();
           foreach my $item (sort {$a <=> $b } (keys(%{$ordered{$type}}))) {
               push(@jsarray,$ordered{$type}{$item});
           }
           $jstext{$type} = '    var '.$type.' = Array('."'".join("','",@jsarray)."'".');'."\n";
     }      }
     my $jstext = '    var textbooks = Array('."'".join("','",@jsarray)."'".');'."\n";  
     return <<"ENDSCRIPT";      return <<"ENDSCRIPT";
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
 function reorderBooks(form,item) {  function reorderBooks(form,item,caller) {
     var changedVal;      var changedVal;
 $jstext   $jstext{'textbooks'};
     var newpos = 'addbook_pos';  $jstext{'templates'};
       var newpos;
       var maxh;
       if (caller == 'textbooks') {  
           newpos = 'textbooks_addbook_pos';
           maxh = 1 + $total{'textbooks'};
       } else {
           newpos = 'templates_addbook_pos';
           maxh = 1 + $total{'templates'};
       }
       var current = new Array;
       var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
       if (item == newpos) {
           changedVal = newitemVal;
       } else {
           changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
           current[newitemVal] = newpos;
       }
       if (caller == 'textbooks') {
           for (var i=0; i<textbooks.length; i++) {
               var elementName = 'textbooks_'+textbooks[i];
               if (elementName != item) {
                   if (form.elements[elementName]) {
                       var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
                       current[currVal] = elementName;
                   }
               }
           }
       }
       if (caller == 'templates') {
           for (var i=0; i<templates.length; i++) {
               var elementName = 'templates_'+templates[i];
               if (elementName != item) {
                   if (form.elements[elementName]) {
                       var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
                       current[currVal] = elementName;
                   }
               }
           }
       }
       var oldVal;
       for (var j=0; j<maxh; j++) {
           if (current[j] == undefined) {
               oldVal = j;
           }
       }
       if (oldVal < changedVal) {
           for (var k=oldVal+1; k<=changedVal ; k++) {
              var elementName = current[k];
              form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
           }
       } else {
           for (var k=changedVal; k<oldVal; k++) {
               var elementName = current[k];
               form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   ENDSCRIPT
   }
   
   sub ltitools_javascript {
       my ($settings) = @_;
       return unless(ref($settings) eq 'HASH');
       my (%ordered,$total,%jstext);
       $total = 0;
       foreach my $item (keys(%{$settings})) {
           if (ref($settings->{$item}) eq 'HASH') {
               my $num = $settings->{$item}{'order'};
               $ordered{$num} = $item;
           }
       }
       $total = scalar(keys(%{$settings}));
       my @jsarray = ();
       foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
           push(@jsarray,$ordered{$item});
       }
       my $jstext = '    var ltitools = Array('."'".join("','",@jsarray)."'".');'."\n";
       return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   function reorderLTI(form,item) {
       var changedVal;
   $jstext
       var newpos = 'ltitools_add_pos';
       var maxh = 1 + $total;
     var current = new Array;      var current = new Array;
     var maxh = 1 + $num;  
     var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;      var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
     if (item == newpos) {      if (item == newpos) {
         changedVal = newitemVal;          changedVal = newitemVal;
Line 2239  $jstext Line 2588  $jstext
         changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;          changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
         current[newitemVal] = newpos;          current[newitemVal] = newpos;
     }      }
     for (var i=0; i<textbooks.length; i++) {      for (var i=0; i<ltitools.length; i++) {
         var elementName = textbooks[i];          var elementName = 'ltitools_'+ltitools[i];
         if (elementName != item) {          if (elementName != item) {
             if (form.elements[elementName]) {              if (form.elements[elementName]) {
                 var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;                  var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
Line 2277  ENDSCRIPT Line 2626  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);
     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 2311  sub print_autoenroll { Line 2660  sub print_autoenroll {
         if (exists($settings->{'sender_domain'})) {          if (exists($settings->{'sender_domain'})) {
             $defdom = $settings->{'sender_domain'};              $defdom = $settings->{'sender_domain'};
         }          }
           if (exists($settings->{'autofailsafe'})) {
               $failsafe = $settings->{'autofailsafe'};
           }
     } else {      } else {
         if ($autorun) {          if ($autorun) {
             $runon = ' checked="checked" ';              $runon = ' checked="checked" ';
Line 2346  sub print_autoenroll { Line 2698  sub print_autoenroll {
                   $coownerson.' value="1" />'.&mt('Yes').'</label>&nbsp;'.                    $coownerson.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                   '<label><input type="radio" name="autoassign_coowners"'.                    '<label><input type="radio" name="autoassign_coowners"'.
                   $coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.                    $coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.
                   '</tr>';                    '</tr><tr>'.
     $$rowtotal += 3;                    '<td>'.&mt('Failsafe for no drops when institutional data missing').'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak">'.
                     '<input type="text" name="autoenroll_failsafe"'.
                     ' value="'.$failsafe.'" size="4" /></td></tr>';
       $$rowtotal += 4;
     return $datatable;      return $datatable;
 }  }
   
Line 2462  sub print_autocreate { Line 2818  sub print_autocreate {
                   $createoff{'req'}.' value="0" />'.&mt('No').'</label></span>';                    $createoff{'req'}.' value="0" />'.&mt('No').'</label></span>';
     my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',      my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',
                                                    'autocreate_xmldc',%currhash);                                                     'autocreate_xmldc',%currhash);
       $datatable .= '</td></tr><tr class="LC_odd_row"><td>';
     if ($numdc > 1) {      if ($numdc > 1) {
         $datatable .= '</td></tr><tr class="LC_odd_row"><td>'.          $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)').
                       &mt('Course creation processed as: (choose Dom. Coord.)').                        '</td><td class="LC_left_item">';
                       '</td><td class="LC_left_item">'.$dctable.'</td></tr>';  
     } else {      } else {
         $datatable .= $dctable.'</td></tr>';          $datatable .= &mt('Course creation processed as:').
                         '</td><td class="LC_right_item">';
     }      }
       $datatable .= $dctable.'</td></tr>';
     $$rowtotal += $rows;      $$rowtotal += $rows;
     return $datatable;      return $datatable;
 }  }
   
 sub print_directorysrch {  sub print_directorysrch {
     my ($dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my $srchon = ' ';      my $datatable;
     my $srchoff = ' checked="checked" ';      if ($position eq 'top') {
     my ($exacton,$containson,$beginson);          my $instsrchon = ' ';
     my $localon = ' ';          my $instsrchoff = ' checked="checked" ';
     my $localoff = ' checked="checked" ';          my ($exacton,$containson,$beginson);
     if (ref($settings) eq 'HASH') {          my $instlocalon = ' ';
         if ($settings->{'available'} eq '1') {          my $instlocaloff = ' checked="checked" ';
             $srchon = $srchoff;          if (ref($settings) eq 'HASH') {
             $srchoff = ' ';              if ($settings->{'available'} eq '1') {
         }                  $instsrchon = $instsrchoff;
         if ($settings->{'localonly'} eq '1') {                  $instsrchoff = ' ';
             $localon = $localoff;              }
             $localoff = ' ';              if ($settings->{'localonly'} eq '1') {
         }                  $instlocalon = $instlocaloff;
         if (ref($settings->{'searchtypes'}) eq 'ARRAY') {                  $instlocaloff = ' ';
             foreach my $type (@{$settings->{'searchtypes'}}) {              }
                 if ($type eq 'exact') {              if (ref($settings->{'searchtypes'}) eq 'ARRAY') {
                   foreach my $type (@{$settings->{'searchtypes'}}) {
                       if ($type eq 'exact') {
                           $exacton = ' checked="checked" ';
                       } elsif ($type eq 'contains') {
                           $containson = ' checked="checked" ';
                       } elsif ($type eq 'begins') {
                           $beginson = ' checked="checked" ';
                       }
                   }
               } else {
                   if ($settings->{'searchtypes'} eq 'exact') {
                       $exacton = ' checked="checked" ';
                   } elsif ($settings->{'searchtypes'} eq 'contains') {
                       $containson = ' checked="checked" ';
                   } elsif ($settings->{'searchtypes'} eq 'specify') {
                     $exacton = ' checked="checked" ';                      $exacton = ' checked="checked" ';
                 } elsif ($type eq 'contains') {  
                     $containson = ' checked="checked" ';                      $containson = ' checked="checked" ';
                 } elsif ($type eq 'begins') {  
                     $beginson = ' checked="checked" ';  
                 }                  }
             }              }
         } else {  
             if ($settings->{'searchtypes'} eq 'exact') {  
                 $exacton = ' checked="checked" ';  
             } elsif ($settings->{'searchtypes'} eq 'contains') {  
                 $containson = ' checked="checked" ';  
             } elsif ($settings->{'searchtypes'} eq 'specify') {  
                 $exacton = ' checked="checked" ';  
                 $containson = ' checked="checked" ';  
             }  
         }          }
     }          my ($searchtitles,$titleorder) = &sorted_searchtitles();
     my ($searchtitles,$titleorder) = &sorted_searchtitles();          my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
   
     my $numinrow = 4;          my $numinrow = 4;
     my $cansrchrow = 0;          my $cansrchrow = 0;
     my $datatable='<tr class="LC_odd_row">'.          $datatable='<tr class="LC_odd_row">'.
                   '<td colspan="2"><span class ="LC_nobreak">'.&mt('Directory search available?').'</span></td>'.                     '<td colspan="2"><span class ="LC_nobreak">'.&mt('Institutional directory search available?').'</span></td>'.
                   '<td class="LC_right_item"><span class="LC_nobreak"><label>'.                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                   '<input type="radio" name="dirsrch_available"'.                     '<input type="radio" name="dirsrch_available"'.
                   $srchon.' value="1" />'.&mt('Yes').'</label>&nbsp;'.                     $instsrchon.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                   '<label><input type="radio" name="dirsrch_available"'.                     '<label><input type="radio" name="dirsrch_available"'.
                   $srchoff.' value="0" />'.&mt('No').'</label></span></td>'.                     $instsrchoff.' value="0" />'.&mt('No').'</label></span></td>'.
                   '</tr><tr>'.                     '</tr><tr>'.
                   '<td colspan="2"><span class ="LC_nobreak">'.&mt('Other domains can search?').'</span></td>'.                     '<td colspan="2"><span class ="LC_nobreak">'.&mt('Other domains can search institution?').'</span></td>'.
                   '<td class="LC_right_item"><span class="LC_nobreak"><label>'.                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                   '<input type="radio" name="dirsrch_localonly"'.                     '<input type="radio" name="dirsrch_instlocalonly"'.
                   $localoff.' value="0" />'.&mt('Yes').'</label>&nbsp;'.                     $instlocaloff.' value="0" />'.&mt('Yes').'</label>&nbsp;'.
                   '<label><input type="radio" name="dirsrch_localonly"'.                     '<label><input type="radio" name="dirsrch_instlocalonly"'.
                   $localon.' value="1" />'.&mt('No').'</label></span></td>'.                     $instlocalon.' value="1" />'.&mt('No').'</label></span></td>'.
                   '</tr>';                     '</tr>';
     $$rowtotal += 2;          $$rowtotal += 2;
     if (ref($usertypes) eq 'HASH') {          if (ref($usertypes) eq 'HASH') {
         if (keys(%{$usertypes}) > 0) {              if (keys(%{$usertypes}) > 0) {
             $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,                  $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,
                                          $numinrow,$othertitle,'cansearch');                                               $numinrow,$othertitle,'cansearch');
             $cansrchrow = 1;                  $cansrchrow = 1;
               }
         }          }
     }          if ($cansrchrow) {
     if ($cansrchrow) {              $$rowtotal ++;
         $$rowtotal ++;              $datatable .= '<tr>';
         $datatable .= '<tr>';          } else {
     } else {              $datatable .= '<tr class="LC_odd_row">';
         $datatable .= '<tr class="LC_odd_row">';          }
     }          $datatable .= '<td><span class ="LC_nobreak">'.&mt('Supported search methods').
     $datatable .= '<td><span class ="LC_nobreak">'.&mt('Supported search methods').                        '</span></td><td class="LC_left_item" colspan="2"><table><tr>';
                   '</span></td><td class="LC_left_item" colspan="2"><table><tr>';          foreach my $title (@{$titleorder}) {
     foreach my $title (@{$titleorder}) {              if (defined($searchtitles->{$title})) {
         if (defined($searchtitles->{$title})) {                  my $check = ' ';
             my $check = ' ';                  if (ref($settings) eq 'HASH') {
             if (ref($settings) eq 'HASH') {                      if (ref($settings->{'searchby'}) eq 'ARRAY') {
                 if (ref($settings->{'searchby'}) eq 'ARRAY') {                          if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) {
                     if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) {                              $check = ' checked="checked" ';
                         $check = ' checked="checked" ';                          }
                     }                      }
                 }                  }
                   $datatable .= '<td class="LC_left_item">'.
                                 '<span class="LC_nobreak"><label>'.
                                 '<input type="checkbox" name="searchby" '.
                                 'value="'.$title.'"'.$check.'/>'.
                                 $searchtitles->{$title}.'</label></span></td>';
             }              }
             $datatable .= '<td class="LC_left_item">'.  
                           '<span class="LC_nobreak"><label>'.  
                           '<input type="checkbox" name="searchby" '.  
                           'value="'.$title.'"'.$check.'/>'.  
                           $searchtitles->{$title}.'</label></span></td>';  
         }          }
     }          $datatable .= '</tr></table></td></tr>';
     $datatable .= '</tr></table></td></tr>';          $$rowtotal ++;
     $$rowtotal ++;          if ($cansrchrow) {
     if ($cansrchrow) {              $datatable .= '<tr class="LC_odd_row">';
         $datatable .= '<tr class="LC_odd_row">';          } else {
               $datatable .= '<tr>';
           }
           $datatable .= '<td><span class ="LC_nobreak">'.&mt('Search latitude').'</span></td>'.   
                         '<td class="LC_left_item" colspan="2">'.
                         '<span class="LC_nobreak"><label>'.
                         '<input type="checkbox" name="searchtypes" '.
                         $exacton.' value="exact" />'.&mt('Exact match').
                         '</label>&nbsp;'.
                         '<label><input type="checkbox" name="searchtypes" '.
                         $beginson.' value="begins" />'.&mt('Begins with').
                         '</label>&nbsp;'.
                         '<label><input type="checkbox" name="searchtypes" '.
                         $containson.' value="contains" />'.&mt('Contains').
                         '</label></span></td></tr>';
           $$rowtotal ++;
     } else {      } else {
         $datatable .= '<tr>';          my $domsrchon = ' checked="checked" ';
           my $domsrchoff = ' ';
           my $domlocalon = ' ';
           my $domlocaloff = ' checked="checked" ';
           if (ref($settings) eq 'HASH') {
               if ($settings->{'lclocalonly'} eq '1') {
                   $domlocalon = $domlocaloff;
                   $domlocaloff = ' ';
               }
               if ($settings->{'lcavailable'} eq '0') {
                   $domsrchoff = $domsrchon;
                   $domsrchon = ' ';
               }
           }
           $datatable='<tr class="LC_odd_row">'.
                         '<td colspan="2"><span class ="LC_nobreak">'.&mt('LON-CAPA directory search available?').'</span></td>'.
                         '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                         '<input type="radio" name="dirsrch_domavailable"'.
                         $domsrchon.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                         '<label><input type="radio" name="dirsrch_domavailable"'.
                         $domsrchoff.' value="0" />'.&mt('No').'</label></span></td>'.
                         '</tr><tr>'.
                         '<td colspan="2"><span class ="LC_nobreak">'.&mt('Other domains can search LON-CAPA domain?').'</span></td>'.
                         '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                         '<input type="radio" name="dirsrch_domlocalonly"'.
                         $domlocaloff.' value="0" />'.&mt('Yes').'</label>&nbsp;'.
                         '<label><input type="radio" name="dirsrch_domlocalonly"'.
                         $domlocalon.' value="1" />'.&mt('No').'</label></span></td>'.
                         '</tr>';
           $$rowtotal += 2;
     }      }
     $datatable .= '<td><span class ="LC_nobreak">'.&mt('Search latitude').'</span></td>'.     
                   '<td class="LC_left_item" colspan="2">'.  
                   '<span class="LC_nobreak"><label>'.  
                   '<input type="checkbox" name="searchtypes" '.  
                   $exacton.' value="exact" />'.&mt('Exact match').  
                   '</label>&nbsp;'.  
                   '<label><input type="checkbox" name="searchtypes" '.  
                   $beginson.' value="begins" />'.&mt('Begins with').  
                   '</label>&nbsp;'.  
                   '<label><input type="checkbox" name="searchtypes" '.  
                   $containson.' value="contains" />'.&mt('Contains').  
                   '</label></span></td></tr>';  
     $$rowtotal ++;  
     return $datatable;      return $datatable;
 }  }
   
 sub print_contacts {  sub print_contacts {
     my ($dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my $datatable;      my $datatable;
     my @contacts = ('adminemail','supportemail');      my @contacts = ('adminemail','supportemail');
     my (%checked,%to,%otheremails,%bccemails);      my (%checked,%to,%otheremails,%bccemails,%includestr,%includeloc,%currfield,
     my @mailings = ('errormail','packagesmail','lonstatusmail','helpdeskmail',          $maxsize,$fields,$fieldtitles,$fieldoptions,$possoptions,@mailings);
                     'requestsmail','updatesmail','idconflictsmail');      if ($position eq 'top') {
     foreach my $type (@mailings) {          if (ref($settings) eq 'HASH') {
         $otheremails{$type} = '';              foreach my $item (@contacts) {
     }                  if (exists($settings->{$item})) {
     $bccemails{'helpdeskmail'} = '';                      $to{$item} = $settings->{$item};
     if (ref($settings) eq 'HASH') {                  }
         foreach my $item (@contacts) {  
             if (exists($settings->{$item})) {  
                 $to{$item} = $settings->{$item};  
             }              }
         }          }
       } elsif ($position eq 'middle') {
           @mailings = ('errormail','packagesmail','lonstatusmail','requestsmail',
                        'updatesmail','idconflictsmail');
         foreach my $type (@mailings) {          foreach my $type (@mailings) {
             if (exists($settings->{$type})) {              $otheremails{$type} = '';
                 if (ref($settings->{$type}) eq 'HASH') {          }
                     foreach my $item (@contacts) {      } else {
                         if ($settings->{$type}{$item}) {          @mailings = ('helpdeskmail','otherdomsmail');
                             $checked{$type}{$item} = ' checked="checked" ';          foreach my $type (@mailings) {
               $otheremails{$type} = '';
           }
           $bccemails{'helpdeskmail'} = '';
           $bccemails{'otherdomsmail'} = '';
           $includestr{'helpdeskmail'} = '';
           $includestr{'otherdomsmail'} = '';
           ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();
       }
       if (ref($settings) eq 'HASH') {
           unless ($position eq 'top') {
               foreach my $type (@mailings) {
                   if (exists($settings->{$type})) {
                       if (ref($settings->{$type}) eq 'HASH') {
                           foreach my $item (@contacts) {
                               if ($settings->{$type}{$item}) {
                                   $checked{$type}{$item} = ' checked="checked" ';
                               }
                           }
                           $otheremails{$type} = $settings->{$type}{'others'};
                           if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                               $bccemails{$type} = $settings->{$type}{'bcc'};
                               if ($settings->{$type}{'include'} ne '') {
                                   ($includeloc{$type},$includestr{$type}) = split(/:/,$settings->{$type}{'include'},2);
                                   $includestr{$type} = &unescape($includestr{$type});
                               }
                         }                          }
                     }                      }
                     $otheremails{$type} = $settings->{$type}{'others'};                  } elsif ($type eq 'lonstatusmail') {
                     if ($type eq 'helpdeskmail') {                      $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';
                         $bccemails{$type} = $settings->{$type}{'bcc'};                  }
               }
           }
           if ($position eq 'bottom') {
               foreach my $type (@mailings) {
                   $bccemails{$type} = $settings->{$type}{'bcc'};
                   if ($settings->{$type}{'include'} ne '') {
                       ($includeloc{$type},$includestr{$type}) = split(/:/,$settings->{$type}{'include'},2);
                       $includestr{$type} = &unescape($includestr{$type});
                   }
               }
               if (ref($settings->{'helpform'}) eq 'HASH') {
                   if (ref($fields) eq 'ARRAY') {
                       foreach my $field (@{$fields}) {
                           $currfield{$field} = $settings->{'helpform'}{$field};
                     }                      }
                 }                  }
             } elsif ($type eq 'lonstatusmail') {                  if (exists($settings->{'helpform'}{'maxsize'})) {
                 $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';                      $maxsize = $settings->{'helpform'}{'maxsize'};
                   } else {
                       $maxsize = '1.0';
                   }
               } else {
                   if (ref($fields) eq 'ARRAY') {
                       foreach my $field (@{$fields}) {
                           $currfield{$field} = 'yes';
                       }
                   }
                   $maxsize = '1.0';
             }              }
         }          }
     } else {      } else {
         $to{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};          if ($position eq 'top') {
         $to{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'};              $to{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};
         $checked{'errormail'}{'adminemail'} = ' checked="checked" ';              $to{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'};
         $checked{'packagesmail'}{'adminemail'} = ' checked="checked" ';              $checked{'errormail'}{'adminemail'} = ' checked="checked" ';
         $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';              $checked{'packagesmail'}{'adminemail'} = ' checked="checked" ';
         $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';               $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';
         $checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';              $checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';
         $checked{'updatesmail'}{'adminemail'} = ' checked="checked" ';              $checked{'updatesmail'}{'adminemail'} = ' checked="checked" ';
         $checked{'idconflictsmail'}{'adminemail'} = ' checked="checked" ';              $checked{'idconflictsmail'}{'adminemail'} = ' checked="checked" ';
           } elsif ($position eq 'bottom') {
               $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';
               $checked{'otherdomsmail'}{'supportemail'} = ' checked="checked" ';
               if (ref($fields) eq 'ARRAY') {
                   foreach my $field (@{$fields}) {
                       $currfield{$field} = 'yes';
                   }
               }
               $maxsize = '1.0';
           }
     }      }
     my ($titles,$short_titles) = &contact_titles();      my ($titles,$short_titles) = &contact_titles();
     my $rownum = 0;      my $rownum = 0;
     my $css_class;      my $css_class;
     foreach my $item (@contacts) {      if ($position eq 'top') {
         $css_class = $rownum%2?' class="LC_odd_row"':'';          foreach my $item (@contacts) {
         $datatable .= '<tr'.$css_class.'>'.               $css_class = $rownum%2?' class="LC_odd_row"':'';
                   '<td><span class="LC_nobreak">'.$titles->{$item}.              $datatable .= '<tr'.$css_class.'>'. 
                   '</span></td><td class="LC_right_item">'.                            '<td><span class="LC_nobreak">'.$titles->{$item}.
                   '<input type="text" name="'.$item.'" value="'.                            '</span></td><td class="LC_right_item">'.
                   $to{$item}.'" /></td></tr>';                            '<input type="text" name="'.$item.'" value="'.
         $rownum ++;                            $to{$item}.'" /></td></tr>';
               $rownum ++;
           }
       } else {
           foreach my $type (@mailings) {
               $css_class = $rownum%2?' class="LC_odd_row"':'';
               $datatable .= '<tr'.$css_class.'>'.
                             '<td><span class="LC_nobreak">'.
                             $titles->{$type}.': </span></td>'.
                             '<td class="LC_left_item">';
               if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                   $datatable .= '<fieldset><legend>'.&mt('E-mail recipient(s)').'</legend>';
               }
               $datatable .= '<span class="LC_nobreak">';
               foreach my $item (@contacts) {
                   $datatable .= '<label>'.
                                 '<input type="checkbox" name="'.$type.'"'.
                                 $checked{$type}{$item}.
                                 ' value="'.$item.'" />'.$short_titles->{$item}.
                                 '</label>&nbsp;';
               }
               $datatable .= '</span><br />'.&mt('Others').':&nbsp;&nbsp;'.
                             '<input type="text" name="'.$type.'_others" '.
                             'value="'.$otheremails{$type}.'"  />';
               my %locchecked;
               if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                   foreach my $loc ('s','b') {
                       if ($includeloc{$type} eq $loc) {
                           $locchecked{$loc} = ' checked="checked"';
                           last;
                       }
                   }
                   $datatable .= '<br />'.&mt('Bcc:').('&nbsp;'x6).
                                 '<input type="text" name="'.$type.'_bcc" '.
                                 'value="'.$bccemails{$type}.'"  /></fieldset>'.
                                 '<fieldset><legend>'.&mt('Optional added text').'</legend>'.
                                 &mt('Text automatically added to e-mail:').' '.
                                 '<input type="text" name="'.$type.'_includestr" value="'.$includestr{$type}.'" /><br >'.
                                 '<span class="LC_nobreak">'.&mt('Location:').'&nbsp;'.
                                 '<label><input type="radio" name="'.$type.'_includeloc" value="s"'.$locchecked{'s'}.' />'.&mt('in subject').'</label>'.
                                 ('&nbsp;'x2).
                                 '<label><input type="radio" name="'.$type.'_includeloc" value="b"'.$locchecked{'b'}.' />'.&mt('in body').'</label>'.
                                 '</span></fieldset>';
               }
               $datatable .= '</td></tr>'."\n";
               $rownum ++;
           }
     }      }
     foreach my $type (@mailings) {      if ($position eq 'middle') {
           my %choices;
           $choices{'reporterrors'} = &mt('E-mail error reports to [_1]',
                                          &Apache::loncommon::modal_link('http://loncapa.org/core.html',
                                          &mt('LON-CAPA core group - MSU'),600,500));
           $choices{'reportupdates'} = &mt('E-mail record of completed LON-CAPA updates to [_1]',
                                           &Apache::loncommon::modal_link('http://loncapa.org/core.html',
                                           &mt('LON-CAPA core group - MSU'),600,500));
           my @toggles = ('reporterrors','reportupdates');
           my %defaultchecked = ('reporterrors'  => 'on',
                                 'reportupdates' => 'on');
           (my $reports,$rownum) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
                                                      \%choices,$rownum);
           $datatable .= $reports;
       } elsif ($position eq 'bottom') {
         $css_class = $rownum%2?' class="LC_odd_row"':'';          $css_class = $rownum%2?' class="LC_odd_row"':'';
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                       '<td><span class="LC_nobreak">'.                        '<td>'.&mt('Extra helpdesk form fields:').'<br />'.
                       $titles->{$type}.': </span></td>'.                        &mt('(e-mail, subject, and description always shown)').
                       '<td class="LC_left_item">'.                        '</td><td class="LC_left_item">';
                       '<span class="LC_nobreak">';          if ((ref($fields) eq 'ARRAY') && (ref($fieldtitles) eq 'HASH') &&
         foreach my $item (@contacts) {              (ref($fieldoptions) eq 'HASH') && (ref($possoptions) eq 'HASH')) {
             $datatable .= '<label>'.              $datatable .= '<table><tr><th>'.&mt('Field').'</th><th>'.&mt('Status').'</th></tr>';
                           '<input type="checkbox" name="'.$type.'"'.              foreach my $field (@{$fields}) {
                           $checked{$type}{$item}.                  $datatable .= '<tr><td>'.$fieldtitles->{$field};
                           ' value="'.$item.'" />'.$short_titles->{$item}.                  if (($field eq 'screenshot') || ($field eq 'cc')) {
                           '</label>&nbsp;';                      $datatable .= ' '.&mt('(logged-in users)');
         }                  }
         $datatable .= '</span><br />'.&mt('Others').':&nbsp;&nbsp;'.                  $datatable .='</td><td>';
                       '<input type="text" name="'.$type.'_others" '.                  my $clickaction;
                       'value="'.$otheremails{$type}.'"  />';                  if ($field eq 'screenshot') {
         if ($type eq 'helpdeskmail') {                      $clickaction = ' onclick="screenshotSize(this);"';
             $datatable .= '<br />'.&mt('Bcc:').('&nbsp;'x6).                  }
                           '<input type="text" name="'.$type.'_bcc" '.                  if (ref($possoptions->{$field}) eq 'ARRAY') {
                           'value="'.$bccemails{$type}.'"  />';                      foreach my $option (@{$possoptions->{$field}}) {
                           my $checked;
                           if ($currfield{$field} eq $option) {
                               $checked = ' checked="checked"';
                           }
                           $datatable .= '<span class="LC_nobreak"><label>'.
                                         '<input type="radio" name="helpform_'.$field.'" '.
                                         'value="'.$option.'"'.$checked.$clickaction.' />'.$fieldoptions->{$option}.
                                         '</label></span>'.('&nbsp;'x2);
                       }
                   }
                   if ($field eq 'screenshot') {
                       my $display;
                       if ($currfield{$field} eq 'no') {
                           $display = ' style="display:none"';
                       }
                       $datatable .= '</td></tr><tr id="help_screenshotsize"'.$display.' />'.
                                     '<td>'.&mt('Maximum size for upload (MB)').'</td><td>'.
                                     '<input type="text" size="5" name="helpform_maxsize" value="'.$maxsize.'" />';
                   }
                   $datatable .= '</td></tr>';
               }
               $datatable .= '</table>';
         }          }
         $datatable .= '</td></tr>'."\n";          $datatable .= '</td></tr>'."\n";
         $rownum ++;          $rownum ++;
     }      }
     my %choices;  
     $choices{'reporterrors'} = &mt('E-mail error reports to [_1]',  
                                    &Apache::loncommon::modal_link('http://loncapa.org/core.html',  
                                    &mt('LON-CAPA core group - MSU'),600,500));  
     $choices{'reportupdates'} = &mt('E-mail record of completed LON-CAPA updates to [_1]',  
                                     &Apache::loncommon::modal_link('http://loncapa.org/core.html',  
                                     &mt('LON-CAPA core group - MSU'),600,500));  
     my @toggles = ('reporterrors','reportupdates');  
     my %defaultchecked = ('reporterrors'  => 'on',  
                           'reportupdates' => 'on');  
     (my $reports,$rownum) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,  
                                                \%choices,$rownum);  
     $datatable .= $reports;  
     $$rowtotal += $rownum;      $$rowtotal += $rownum;
     return $datatable;      return $datatable;
 }  }
   
   sub contacts_javascript {
       return <<"ENDSCRIPT";
   
   <script type="text/javascript">
   // <![CDATA[
   
   function screenshotSize(field) {
       if (document.getElementById('help_screenshotsize')) {
           if (field.value == 'no') {
               document.getElementById('help_screenshotsize').style.display="none";
           } else {
               document.getElementById('help_screenshotsize').style.display="";
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   ENDSCRIPT
   }
   
 sub print_helpsettings {  sub print_helpsettings {
     my ($dom,$confname,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
       my $confname = $dom.'-domainconfig';
       my $formname = 'display';
     my ($datatable,$itemcount);      my ($datatable,$itemcount);
     $itemcount = 1;      if ($position eq 'top') {
     my (%choices,%defaultchecked,@toggles);          $itemcount = 1;
     $choices{'submitbugs'} = &mt('Display link to: [_1]?',          my (%choices,%defaultchecked,@toggles);
                                  &Apache::loncommon::modal_link('http://bugs.loncapa.org',          $choices{'submitbugs'} = &mt('Display link to: [_1]?',
                                  &mt('LON-CAPA bug tracker'),600,500));                                       &Apache::loncommon::modal_link('http://bugs.loncapa.org',
     %defaultchecked = ('submitbugs' => 'on');                                       &mt('LON-CAPA bug tracker'),600,500));
     @toggles = ('submitbugs',);          %defaultchecked = ('submitbugs' => 'on');
           @toggles = ('submitbugs');
     ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,          ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
                                                  \%choices,$itemcount);                                                       \%choices,$itemcount);
           $$rowtotal ++;
       } else {
           my $css_class;
           my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');
           my (%customroles,%ordered,%current);
           if (ref($settings->{'adhoc'}) eq 'HASH') {
               %current = %{$settings->{'adhoc'}};
           }
           my $count = 0;
           foreach my $key (sort(keys(%existing))) {
               if ($key=~/^rolesdef\_(\w+)$/) {
                   my $rolename = $1;
                   my (%privs,$order);
                   ($privs{'system'},$privs{'domain'},$privs{'course'}) = split(/\_/,$existing{$key});
                   $customroles{$rolename} = \%privs;
                   if (ref($current{$rolename}) eq 'HASH') {
                       $order = $current{$rolename}{'order'};
                   }
                   if ($order eq '') {
                       $order = $count;
                   }
                   $ordered{$order} = $rolename;
                   $count++;
               }
           }
           my $maxnum = scalar(keys(%ordered));
           my @roles_by_num = ();
           foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
               push(@roles_by_num,$item);
           }
           my $context = 'domprefs';
           my $crstype = 'Course';
           my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
           my @accesstypes = ('all','dh','da','none');
           my ($numstatustypes,@jsarray);
           if (ref($types) eq 'ARRAY') {
               if (@{$types} > 0) {
                   $numstatustypes = scalar(@{$types});
                   push(@accesstypes,'status');
                   @jsarray = ('bystatus');
               }
           }
           my %domhelpdesk = &Apache::lonnet::get_active_domroles($dom,['dh','da']);
           if (keys(%domhelpdesk)) {
               push(@accesstypes,('inc','exc'));
               push(@jsarray,('notinc','notexc'));
           }
           my $hiddenstr = join("','",@jsarray);
           $datatable .= &helpsettings_javascript(\@roles_by_num,$maxnum,$hiddenstr,$formname);
           my $context = 'domprefs';
           my $crstype = 'Course';
           my $prefix = 'helproles_';
           my $add_class = 'LC_hidden';
           foreach my $num (@roles_by_num) {
               my $role = $ordered{$num};
               my ($desc,$access,@statuses);
               if (ref($current{$role}) eq 'HASH') {
                   $desc = $current{$role}{'desc'};
                   $access = $current{$role}{'access'};
                   if (ref($current{$role}{'insttypes'}) eq 'ARRAY') {
                       @statuses = @{$current{$role}{'insttypes'}};
                   }
               }
               if ($desc eq '') {
                   $desc = $role;
               }
               my $identifier = 'custhelp'.$num;
               my %full=();
               my %levels= (
                            course => {},
                            domain => {},
                            system => {},
                           );
               my %levelscurrent=(
                                  course => {},
                                  domain => {},
                                  system => {},
                                 );
               &Apache::lonuserutils::custom_role_privs($customroles{$role},\%full,\%levels,\%levelscurrent);
               my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
               $css_class = $itemcount%2?' class="LC_odd_row"':'';
               my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$num."_pos'".');"';
               $datatable .= '<tr '.$css_class.'><td valign="top"><b>'.$role.'</b><br />'.
                             '<select name="helproles_'.$num.'_pos"'.$chgstr.'>';
               for (my $k=0; $k<=$maxnum; $k++) {
                   my $vpos = $k+1;
                   my $selstr;
                   if ($k == $num) {
                       $selstr = ' selected="selected" ';
                   }
                   $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
               }
               $datatable .= '</select>'.('&nbsp;'x2).
                             '<input type="hidden" name="helproles_'.$num.'" value="'.$role.'" />'.
                             '</td>'.
                             '<td><fieldset><legend>'.&mt('Role name').'</legend>'.
                             &mt('Name shown to users:').
                             '<input type="text" name="helproles_'.$num.'_desc" value="'.$desc.'" />'.
                             '</fieldset>'.
                             &helpdeskroles_access($dom,$prefix,$num,$add_class,$current{$role},\@accesstypes,
                                                   $othertitle,$usertypes,$types,\%domhelpdesk).
                             '<fieldset>'.
                             '<legend>'.&mt('Role privileges').&adhocbutton($prefix,$num,'privs','show').'</legend>'.
                             &Apache::lonuserutils::custom_role_table($crstype,\%full,\%levels,
                                                                      \%levelscurrent,$identifier,
                                                                      'LC_hidden',$prefix.$num.'_privs').
                             '</fieldset></td>';
               $itemcount ++;
           }
           $css_class = $itemcount%2?' class="LC_odd_row"':'';
           my $newcust = 'custhelp'.$count;
           my (%privs,%levelscurrent);
           my %full=();
           my %levels= (
                        course => {},
                        domain => {},
                        system => {},
                       );
           &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
           my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
           my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$count."_pos'".');"';
           $datatable .= '<tr '.$css_class.'><td valign="top"><span class="LC_nobreak"><label>'.
                         '<input type="hidden" name="helproles_maxnum" value="'.$maxnum.'" />'."\n".
                         '<select name="helproles_'.$count.'_pos"'.$chgstr.'>';
           for (my $k=0; $k<$maxnum+1; $k++) {
               my $vpos = $k+1;
               my $selstr;
               if ($k == $maxnum) {
                   $selstr = ' selected="selected" ';
               }
               $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
           }
           $datatable .= '</select>&nbsp;'."\n".
                         '<input type="checkbox" name="newcusthelp" value="'.$count.'" />'. &mt('Add').
                         '</label></span></td>'.
                         '<td><fieldset><legend>'.&mt('Role name').'</legend>'.
                         '<span class="LC_nobreak">'.
                         &mt('Internal name:').
                         '<input type="text" size="10" name="custhelpname'.$count.'" value="" />'.
                         '</span>'.('&nbsp;'x4).
                         '<span class="LC_nobreak">'.
                         &mt('Name shown to users:').
                         '<input type="text" size="20" name="helproles_'.$count.'_desc" value="" />'.
                         '</span></fieldset>'.
                          &helpdeskroles_access($dom,$prefix,$count,'',undef,\@accesstypes,$othertitle,
                                                $usertypes,$types,\%domhelpdesk).
                         '<fieldset><legend>'.&mt('Role privileges').'</legend>'.
                         &Apache::lonuserutils::custom_role_header($context,$crstype,
                                                                   \@templateroles,$newcust).
                         &Apache::lonuserutils::custom_role_table('Course',\%full,\%levels,
                                                                  \%levelscurrent,$newcust).
                         '</fieldset></td></tr>';
           $count ++;
           $$rowtotal += $count;
       }
     return $datatable;      return $datatable;
 }  }
   
   sub adhocbutton {
       my ($prefix,$num,$field,$visibility) = @_;
       my %lt = &Apache::lonlocal::texthash(
                                             show => 'Show details',
                                             hide => 'Hide details',
                                           );
       return '<span style="text-decoration:line-through; font-weight: normal;">'.('&nbsp;'x10).
              '</span>'.('&nbsp;'x2).'<input type="button" id="'.$prefix.$num.'_'.$field.'_vis"'.
              ' value="'.$lt{$visibility}.'" style="height:20px;" '.
              'onclick="toggleHelpdeskItem('."'$num','$field'".');" />'.('&nbsp;'x2);
   }
   
   sub helpsettings_javascript {
       my ($roles_by_num,$total,$hiddenstr,$formname) = @_;
       return unless(ref($roles_by_num) eq 'ARRAY');
       my %html_js_lt = &Apache::lonlocal::texthash(
                                             show => 'Show details',
                                             hide => 'Hide details',
                                           );
       &html_escape(\%html_js_lt);
       my $jstext = '    var helproles = Array('."'".join("','",@{$roles_by_num})."'".');'."\n";
       return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   
   function reorderHelpRoles(form,item) {
       var changedVal;
   $jstext
       var newpos = 'helproles_${total}_pos';
       var maxh = 1 + $total;
       var current = new Array();
       var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
       if (item == newpos) {
           changedVal = newitemVal;
       } else {
           changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
           current[newitemVal] = newpos;
       }
       for (var i=0; i<helproles.length; i++) {
           var elementName = 'helproles_'+helproles[i]+'_pos';
           if (elementName != item) {
               if (form.elements[elementName]) {
                   var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
                   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 helpdeskAccess(num) {
       var curraccess = null;
       if (document.$formname.elements['helproles_'+num+'_access'].length) {
           for (var i=0; i<document.$formname.elements['helproles_'+num+'_access'].length; i++) {
               if (document.$formname.elements['helproles_'+num+'_access'][i].checked) {
                   curraccess = document.$formname.elements['helproles_'+num+'_access'][i].value;
               }
           }
       }
       var shown = Array();
       var hidden = Array();
       if (curraccess == 'none') {
           hidden = Array('$hiddenstr');
       } else {
           if (curraccess == 'status') {
               shown = Array('bystatus');
               hidden = Array('notinc','notexc');
           } else {
               if (curraccess == 'exc') {
                   shown = Array('notexc');
                   hidden = Array('notinc','bystatus');
               }
               if (curraccess == 'inc') {
                   shown = Array('notinc');
                   hidden = Array('notexc','bystatus');
               }
               if ((curraccess == 'all') || (curraccess == 'dh') || (curraccess == 'da')) {
                   hidden = Array('notinc','notexc','bystatus');
               }
           }
       }
       if (hidden.length > 0) {
           for (var i=0; i<hidden.length; i++) {
               if (document.getElementById('helproles_'+num+'_'+hidden[i])) {
                   document.getElementById('helproles_'+num+'_'+hidden[i]).style.display = 'none';
               }
           }
       }
       if (shown.length > 0) {
           for (var i=0; i<shown.length; i++) {
               if (document.getElementById('helproles_'+num+'_'+shown[i])) {
                   if (shown[i] == 'privs') {
                       document.getElementById('helproles_'+num+'_'+shown[i]).style.display = 'block';
                   } else {
                       document.getElementById('helproles_'+num+'_'+shown[i]).style.display = 'inline-block';
                   }
               }
           }
       }
       return;
   }
   
   function toggleHelpdeskItem(num,field) {
       if (document.getElementById('helproles_'+num+'_'+field)) {
           if (document.getElementById('helproles_'+num+'_'+field).className.match(/(?:^|\\s)LC_hidden(?!\\S)/)) {
               document.getElementById('helproles_'+num+'_'+field).className =
                   document.getElementById('helproles_'+num+'_'+field).className.replace(/(?:^|\\s)LC_hidden(?!\\S)/g ,'');
               if (document.getElementById('helproles_'+num+'_'+field+'_vis')) {
                   document.getElementById('helproles_'+num+'_'+field+'_vis').value = '$html_js_lt{hide}';
               }
           } else {
               document.getElementById('helproles_'+num+'_'+field).className += ' LC_hidden';
               if (document.getElementById('helproles_'+num+'_'+field+'_vis')) {
                   document.getElementById('helproles_'+num+'_'+field+'_vis').value = '$html_js_lt{show}';
               }
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   ENDSCRIPT
   }
   
   sub helpdeskroles_access {
       my ($dom,$prefix,$num,$add_class,$current,$accesstypes,$othertitle,
           $usertypes,$types,$domhelpdesk) = @_;
       return unless ((ref($accesstypes) eq 'ARRAY') && (ref($domhelpdesk) eq 'HASH'));
       my %lt = &Apache::lonlocal::texthash(
                       'rou'    => 'Role usage',
                       'whi'    => 'Which helpdesk personnel may use this role?',
                       'all'    => 'All with domain helpdesk or helpdesk assistant role',
                       'dh'     => 'All with domain helpdesk role',
                       'da'     => 'All with domain helpdesk assistant role',
                       'none'   => 'None',
                       'status' => 'Determined based on institutional status',
                       'inc'    => 'Include all, but exclude specific personnel',
                       'exc'    => 'Exclude all, but include specific personnel',
                     );
       my %usecheck = (
                        all => ' checked="checked"',
                      );
       my %displaydiv = (
                         status => 'none',
                         inc    => 'none',
                         exc    => 'none',
                         priv   => 'block',
                        );
       my $output;
       if (ref($current) eq 'HASH') {
           if (($current->{'access'} ne '') && ($current->{'access'} ne 'all')) {
               if (grep(/^\Q$current->{access}\E$/,@{$accesstypes})) {
                   $usecheck{$current->{access}} = $usecheck{'all'};
                   delete($usecheck{'all'});
                   if ($current->{access} =~ /^(status|inc|exc)$/) {
                       my $access = $1;
                       $displaydiv{$access} = 'inline';
                   } elsif ($current->{access} eq 'none') {
                       $displaydiv{'priv'} = 'none';
                   }
               }
           }
       }
       $output = '<fieldset id="'.$prefix.$num.'_usage"><legend>'.$lt{'rou'}.'</legend>'.
                 '<p>'.$lt{'whi'}.'</p>';
       foreach my $access (@{$accesstypes}) {
           $output .= '<p><label><input type="radio" name="'.$prefix.$num.'_access" value="'.$access.'" '.$usecheck{$access}.
                      ' onclick="helpdeskAccess('."'$num'".');" />'.
                      $lt{$access}.'</label>';
           if ($access eq 'status') {
               $output .= '<div id="'.$prefix.$num.'_bystatus" style="display:'.$displaydiv{$access}.'">'.
                          &Apache::lonuserutils::adhoc_status_types($dom,$prefix,$num,$current->{$access},
                                                                    $othertitle,$usertypes,$types).
                          '</div>';
           } elsif (($access eq 'inc') && (keys(%{$domhelpdesk}) > 0)) {
               $output .= '<div id="'.$prefix.$num.'_notinc" style="display:'.$displaydiv{$access}.'">'.
                          &Apache::lonuserutils::adhoc_staff($access,$prefix,$num,$current->{$access},$domhelpdesk).
                          '</div>';
           } elsif (($access eq 'exc') && (keys(%{$domhelpdesk}) > 0)) {
               $output .= '<div id="'.$prefix.$num.'_notexc" style="display:'.$displaydiv{$access}.'">'.
                          &Apache::lonuserutils::adhoc_staff($access,$prefix,$num,$current->{$access},$domhelpdesk).
                          '</div>';
           }
           $output .= '</p>';
       }
       $output .= '</fieldset>';
       return $output;
   }
   
 sub radiobutton_prefs {  sub radiobutton_prefs {
     my ($settings,$toggles,$defaultchecked,$choices,$itemcount,$onclick,      my ($settings,$toggles,$defaultchecked,$choices,$itemcount,$onclick,
         $additional) = @_;          $additional,$align) = @_;
     return unless ((ref($toggles) eq 'ARRAY') && (ref($defaultchecked) eq 'HASH') &&      return unless ((ref($toggles) eq 'ARRAY') && (ref($defaultchecked) eq 'HASH') &&
                    (ref($choices) eq 'HASH'));                     (ref($choices) eq 'HASH'));
   
Line 2737  sub radiobutton_prefs { Line 3645  sub radiobutton_prefs {
         $datatable .=          $datatable .=
             '<tr'.$css_class.'><td valign="top">'.              '<tr'.$css_class.'><td valign="top">'.
             '<span class="LC_nobreak">'.$choices->{$item}.              '<span class="LC_nobreak">'.$choices->{$item}.
             '</span></td>'.              '</span></td>';
             '<td class="LC_right_item"><span class="LC_nobreak">'.          if ($align eq 'left') {
               $datatable .= '<td class="LC_left_item">';
           } else {
               $datatable .= '<td class="LC_right_item">';
           }
           $datatable .=
               '<span class="LC_nobreak">'.
             '<label><input type="radio" name="'.              '<label><input type="radio" name="'.
             $item.'" '.$checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').              $item.'" '.$checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').
             '</label>&nbsp;<label><input type="radio" name="'.$item.'" '.              '</label>&nbsp;<label><input type="radio" name="'.$item.'" '.
Line 2751  sub radiobutton_prefs { Line 3665  sub radiobutton_prefs {
     return ($datatable,$itemcount);      return ($datatable,$itemcount);
 }  }
   
   sub print_ltitools {
       my ($dom,$settings,$rowtotal) = @_;
       my $rownum = 0;
       my $css_class;
       my $itemcount = 1;
       my $maxnum = 0;
       my %ordered;
       if (ref($settings) eq 'HASH') {
           foreach my $item (keys(%{$settings})) {
               if (ref($settings->{$item}) eq 'HASH') {
                   my $num = $settings->{$item}{'order'};
                   $ordered{$num} = $item;
               }
           }
       }
       my $confname = $dom.'-domainconfig';
       my $switchserver = &check_switchserver($dom,$confname);
       my $maxnum = scalar(keys(%ordered));
       my $datatable = &ltitools_javascript($settings);
       my %lt = &ltitools_names();
       my @courseroles = ('cc','in','ta','ep','st');
       my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner);
       my @fields = ('fullname','firstname','lastname','email','user','roles');
       if (keys(%ordered)) {
           my @items = sort { $a <=> $b } keys(%ordered);
           for (my $i=0; $i<@items; $i++) {
               $css_class = $itemcount%2?' class="LC_odd_row"':'';
               my $item = $ordered{$items[$i]};
               my ($title,$key,$secret,$url,$imgsrc,$version);
               if (ref($settings->{$item}) eq 'HASH') {
                   $title = $settings->{$item}->{'title'};
                   $url = $settings->{$item}->{'url'};
                   $key = $settings->{$item}->{'key'};
                   $secret = $settings->{$item}->{'secret'};
                   my $image = $settings->{$item}->{'image'};
                   if ($image ne '') {
                       $imgsrc = '<img src="'.$image.'" alt="'.&mt('Tool Provider icon').'" />';
                   }
               }
               my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_".$item."'".');"';
               $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
                            .'<select name="ltitools_'.$item.'"'.$chgstr.'>';
               for (my $k=0; $k<=$maxnum; $k++) {
                   my $vpos = $k+1;
                   my $selstr;
                   if ($k == $i) {
                       $selstr = ' selected="selected" ';
                   }
                   $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
               }
               $datatable .= '</select>'.('&nbsp;'x2).
                   '<label><input type="checkbox" name="ltitools_del" value="'.$item.'" />'.
                   &mt('Delete?').'</label></span></td>'.
                   '<td colspan="2">'.
                   '<fieldset><legend>'.&mt('Required settings').'</legend>'.
                   '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="30" name="ltitools_title_'.$i.'" value="'.$title.'" /></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'version'}.':<select name="ltitools_version_'.$i.'">'.
                   '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'msgtype'}.':<select name="ltitools_msgtype_'.$i.'">'.
                   '<option value="basic-lti-launch-request" selected="selected">Launch</option></select></span> '.
                   '<br /><br />'.
                   '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="30" name="ltitools_url_'.$i.'"'.
                   ' value="'.$url.'" /></span>'.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'key'}.
                   '<input type="text" size="25" name="ltitools_key_'.$i.'" value="'.$key.'" /></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'secret'}.':'.
                   '<input type="password" size="20" name="ltitools_secret_'.$i.'" value="'.$secret.'" />'.
                   '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.ltitools_secret_'.$i.'.type='."'text'".' } else { this.form.ltitools_secret_'.$i.'.type='."'password'".' }" />'.&mt('Visible input').'</label>'.
                   '<input type="hidden" name="ltitools_id_'.$i.'" value="'.$item.'" /></span>'.
                   '</fieldset>'.
                   '<fieldset><legend>'.&mt('Optional settings').'</legend>'.
                   '<span class="LC_nobreak">'.&mt('Display target:');
               my %currdisp;
               if (ref($settings->{$item}->{'display'}) eq 'HASH') {
                   if ($settings->{$item}->{'display'}->{'target'} eq 'window') {
                       $currdisp{'window'} = ' checked="checked"';
                   } else {
                       $currdisp{'iframe'} = ' checked="checked"';
                   }
                   if ($settings->{$item}->{'display'}->{'width'} =~ /^(\d+)$/) {
                       $currdisp{'width'} = $1;
                   }
                   if ($settings->{$item}->{'display'}->{'height'} =~ /^(\d+)$/) {
                        $currdisp{'height'} = $1;
                   }
               } else {
                   $currdisp{'iframe'} = ' checked="checked"';
               }
               foreach my $disp ('iframe','window') {
                   $datatable .= '<label><input type="radio" name="ltitools_target_'.$i.'" value="'.$disp.'"'.$currdisp{$disp}.' />'.
                                 $lt{$disp}.'</label>'.('&nbsp;'x2);
               }
               $datatable .= ('&nbsp;'x4);
               foreach my $dimen ('width','height') {
                   $datatable .= '<label>'.$lt{$dimen}.'&nbsp;'.
                                 '<input type="text" name="ltitools_'.$dimen.'_'.$i.'" size="5" value="'.$currdisp{$dimen}.'" /></label>'.
                                 ('&nbsp;'x2);
               }
               $datatable .= '<br />';
               foreach my $extra ('passback','roster') {
                   my $checkedon = '';
                   my $checkedoff = ' checked="checked"';
                   if ($settings->{$item}->{$extra}) {
                       $checkedon = $checkedoff;
                       $checkedoff = '';
                   }
                   $datatable .= $lt{$extra}.'&nbsp;'.
                                 '<label><input type="radio" name="ltitools_'.$extra.'_'.$i.'" value="1"'.$checkedon.' />'.
                                 &mt('Yes').'</label>'.('&nbsp;'x2).
                                 '<label><input type="radio" name="ltitools_'.$extra.'_'.$i.'" value="0"'.$checkedoff.' />'.
                                 &mt('No').'</label>'.('&nbsp;'x4);
               }
               $datatable .= '<br /><br /><span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;';
               if ($imgsrc) {
                   $datatable .= $imgsrc.
                                 '<label><input type="checkbox" name="ltitools_image_del"'.
                                 ' value="'.$item.'" />'.&mt('Delete?').'</label></span> '.
                                 '<span class="LC_nobreak">&nbsp;'.&mt('Replace:').'&nbsp;';
               } else {
                   $datatable .= '('.&mt('if larger than 21x21 pixels, image will be scaled').')&nbsp;';
               }
               if ($switchserver) {
                   $datatable .= &mt('Upload to library server: [_1]',$switchserver);
               } else {
                   $datatable .= '<input type="file" name="ltitools_image_'.$i.'" value="" />';
               }
               $datatable .= '</span></fieldset>';
               my (%checkedfields,%rolemaps);
               if (ref($settings->{$item}) eq 'HASH') {
                   if (ref($settings->{$item}->{'fields'}) eq 'HASH') {
                       %checkedfields = %{$settings->{$item}->{'fields'}};
                   }
                   if (ref($settings->{$item}->{'roles'}) eq 'HASH') {
                       %rolemaps = %{$settings->{$item}->{'roles'}};
                       $checkedfields{'roles'} = 1;
                   }
               }
               $datatable .= '<fieldset><legend>'.&mt('User data sent on launch').'</legend>'.
                             '<span class="LC_nobreak">';
               foreach my $field (@fields) {
                   my $checked;
                   if ($checkedfields{$field}) {
                       $checked = ' checked="checked"';
                   }
                   $datatable .= '<label>'.
                                 '<input type="checkbox" name="ltitools_fields_'.$i.'" value="'.$field.'"'.$checked.' />'.
                                 $lt{$field}.'</label>'.('&nbsp;' x2);
               }
               $datatable .= '</span></fieldset>'.
                             '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';
               foreach my $role (@courseroles) {
                   my ($selected,$selectnone);
                   if (!$rolemaps{$role}) {
                       $selectnone = ' selected="selected"';
                   }
                   $datatable .= '<td align="center">'. 
                                 &Apache::lonnet::plaintext($role,'Course').'<br />'.
                                 '<select name="ltitools_roles_'.$role.'_'.$i.'">'.
                                 '<option value=""'.$selectnone.'>'.&mt('Select').'</option>';
                   foreach my $ltirole (@ltiroles) {
                       unless ($selectnone) {
                           if ($rolemaps{$role} eq $ltirole) {
                               $selected = ' selected="selected"';
                           } else {
                               $selected = '';
                           }
                       }
                       $datatable .= '<option value="'.$ltirole.'"'.$selected.'>'.$ltirole.'</option>';
                   }
                   $datatable .= '</select></td>';
               }
               $datatable .= '</tr></table></fieldset>';
               my %courseconfig;
               if (ref($settings->{$item}) eq 'HASH') {
                   if (ref($settings->{$item}->{'crsconf'}) eq 'HASH') {
                       %courseconfig = %{$settings->{$item}->{'crsconf'}};
                   }
               }
               $datatable .= '<fieldset><legend>'.&mt('Configurable in course').'</legend><span class="LC_nobreak">';
               foreach my $item ('label','title','target') {
                   my $checked;
                   if ($courseconfig{$item}) {
                       $checked = ' checked="checked"';
                   }
                   $datatable .= '<label>'.
                          '<input type="checkbox" name="ltitools_courseconfig_'.$i.'" value="'.$item.'"'.$checked.' />'.
                          $lt{'crs'.$item}.'</label>'.('&nbsp;' x2)."\n";
               }
               $datatable .= '</span></fieldset>'.
                             '<fieldset><legend>'.&mt('Custom items sent on launch').'</legend>'.
                             '<table><tr><th>'.&mt('Action').'</th><th>'.&mt('Name').'</th><th>'.&mt('Value').'</th></tr>';
               if (ref($settings->{$item}->{'custom'}) eq 'HASH') {
                   my %custom = %{$settings->{$item}->{'custom'}};
                   if (keys(%custom) > 0) {
                       foreach my $key (sort(keys(%custom))) {
                           $datatable .= '<tr><td><span class="LC_nobreak">'.
                                         '<label><input type="checkbox" name="ltitools_customdel_'.$i.'" value="'.
                                         $key.'" />'.&mt('Delete').'</label></span></td><td>'.$key.'</td>'.
                                         '<td><input type="text" name="ltitools_customval_'.$key.'_'.$i.'"'.
                                         ' value="'.$custom{$key}.'" /></td></tr>';
                       }
                   }
               }
               $datatable .= '<tr><td><span class="LC_nobreak">'.
                             '<label><input type="checkbox" name="ltitools_customadd" value="'.$i.'" />'.
                             &mt('Add').'</label></span></td><td><input type="text" name="ltitools_custom_name_'.$i.'" />'.
                             '</td><td><input type="text" name="ltitools_custom_value_'.$i.'" /></td></tr>';
               $datatable .= '</table></fieldset></td></tr>'."\n";
               $itemcount ++;
           }
       }
       $css_class = $itemcount%2?' class="LC_odd_row"':'';
       my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_add_pos'".');"';
       $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
                     '<input type="hidden" name="ltitools_maxnum" value="'.$maxnum.'" />'."\n".
                     '<select name="ltitools_add_pos"'.$chgstr.'>';
       for (my $k=0; $k<$maxnum+1; $k++) {
           my $vpos = $k+1;
           my $selstr;
           if ($k == $maxnum) {
               $selstr = ' selected="selected" ';
           }
           $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
       }
       $datatable .= '</select>&nbsp;'."\n".
                     '<input type="checkbox" name="ltitools_add" value="1" />'.&mt('Add').'</td>'."\n".
                     '<td colspan="2">'.
                     '<fieldset><legend>'.&mt('Required settings').'</legend>'.
                     '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="30" name="ltitools_add_title" value="" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'version'}.':<select name="ltitools_add_version">'.
                     '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'msgtype'}.':<select name="ltitools_add_msgtype">'.
                     '<option value="basic-lti-launch-request" selected="selected">Launch</option></select></span> '.
                     '<br />'.
                     '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="30" name="ltitools_add_url" value="" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'key'}.':<input type="text" size="25" name="ltitools_add_key" value="" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'secret'}.':<input type="password" size="20" name="ltitools_add_secret" value="" />'.
                     '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.ltitools_add_secret.type='."'text'".' } else { this.form.ltitools_add_secret.type='."'password'".' }" />'.&mt('Visible input').'</label></span> '."\n".
                     '</fieldset>'.
                     '<fieldset><legend>'.&mt('Optional settings').'</legend>'.
                     '<span class="LC_nobreak">'.&mt('Display target:');
       my %defaultdisp;
       $defaultdisp{'iframe'} = ' checked="checked"';
       foreach my $disp ('iframe','window') {
           $datatable .= '<label><input type="radio" name="ltitools_add_target" value="'.$disp.'"'.$defaultdisp{$disp}.' />'.
                         $lt{$disp}.'</label>'.('&nbsp;'x2);
       }
       $datatable .= ('&nbsp;'x4);
       foreach my $dimen ('width','height') {
           $datatable .= '<label>'.$lt{$dimen}.'&nbsp;'.
                         '<input type="text" name="ltitools_add_'.$dimen.'" size="5" /></label>'.
                         ('&nbsp;'x2);
       }
       $datatable .= '<br />';
       foreach my $extra ('passback','roster') {
           $datatable .= $lt{$extra}.'&nbsp;'.
                         '<label><input type="radio" name="ltitools_add_'.$extra.'" value="1" />'.
                         &mt('Yes').'</label>'.('&nbsp;'x2).
                         '<label><input type="radio" name="ltitools_add_'.$extra.'" value="0" checked="checked" />'.
                         &mt('No').'</label>'.('&nbsp;'x4);
       }
       $datatable .= '<br /><br /><span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;'.
                     '('.&mt('if larger than 21x21 pixels, image will be scaled').')&nbsp;';
       if ($switchserver) {
           $datatable .= &mt('Upload to library server: [_1]',$switchserver);
       } else {
           $datatable .= '<input type="file" name="ltitools_add_image" value="" />';
       }
       $datatable .= '</span></fieldset>'.
                     '<fieldset><legend>'.&mt('User data sent on launch').'</legend>'.
                     '<span class="LC_nobreak">';
       foreach my $field (@fields) {
           $datatable .= '<label>'.
                         '<input type="checkbox" name="ltitools_add_fields" value="'.$field.'" />'.
                         $lt{$field}.'</label>'.('&nbsp;' x2);
       }
       $datatable .= '</span></fieldset>'.
                     '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';
       foreach my $role (@courseroles) {
           my ($checked,$checkednone);
           $datatable .= '<td align="center">'.
                         &Apache::lonnet::plaintext($role,'Course').'<br />'.
                         '<select name="ltitools_add_roles_'.$role.'">'.
                         '<option value="" selected="selected">'.&mt('Select').'</option>';
           foreach my $ltirole (@ltiroles) {
               $datatable .= '<option value="'.$ltirole.'">'.$ltirole.'</option>';
           }
           $datatable .= '</select></td>';
       }
       $datatable .= '</tr></table></fieldset>'.
                     '<fieldset><legend>'.&mt('Configurable in course').'</legend><span class="LC_nobreak">';
       foreach my $item ('label','title','target') {
            $datatable .= '<label>'.
                          '<input type="checkbox" name="ltitools_courseconfig" value="'.$item.'" checked="checked" />'.
                          $lt{'crs'.$item}.'</label>'.('&nbsp;' x2)."\n";
       }
       $datatable .= '</span></fieldset>'.
                     '<fieldset><legend>'.&mt('Custom items sent on launch').'</legend>'.
                     '<table><tr><th>'.&mt('Action').'</th><th>'.&mt('Name').'</th><th>'.&mt('Value').'</th></tr>'.
                     '<tr><td><span class="LC_nobreak">'.
                     '<label><input type="checkbox" name="ltitools_add_custom" value="1" />'.
                     &mt('Add').'</label></span></td><td><input type="text" name="ltitools_add_custom_name" />'.
                     '</td><td><input type="text" name="ltitools_add_custom_value" /></td></tr>'.
                     '</table></fieldset></td></tr>'."\n".
                     '</td>'."\n".
                     '</tr>'."\n";
       $itemcount ++;
       return $datatable;
   }
   
   sub ltitools_names {
       my %lt = &Apache::lonlocal::texthash(
                                             'title'     => 'Title',
                                             'version'   => 'Version',
                                             'msgtype'   => 'Message Type',
                                             'url'       => 'URL',
                                             'key'       => 'Key',
                                             'secret'    => 'Secret',
                                             'icon'      => 'Icon',   
                                             'user'      => 'Username:domain',
                                             'fullname'  => 'Full Name',
                                             'firstname' => 'First Name',
                                             'lastname'  => 'Last Name',
                                             'email'     => 'E-mail',
                                             'roles'     => 'Role',
                                             'window'    => 'Window/Tab',
                                             'iframe'    => 'iFrame',
                                             'height'    => 'Height',
                                             'width'     => 'Width',
                                             'passback'  => 'Tool can return grades:',
                                             'roster'    => 'Tool can retrieve roster:',
                                             'crstarget' => 'Display target',
                                             'crslabel'  => 'Course label',
                                             'crstitle'  => 'Course title', 
                                           );
       return %lt;
   }
   
 sub print_coursedefaults {  sub print_coursedefaults {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles);      my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles);
Line 2760  sub print_coursedefaults { Line 4020  sub print_coursedefaults {
         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)',
           usejsme              => 'Molecule editor uses JSME (HTML5) in place of JME (Java)',
           postsubmit           => 'Disable submit button/keypress following student submission',
           canclone             => "People who may clone a course (besides course's owner and coordinators)",
           mysqltables          => 'Lifetime (s) of "Temporary" MySQL tables (student performance data) on homeserver',
     );      );
     my %staticdefaults = (      my %staticdefaults = (
                            anonsurvey_threshold => 10,                             anonsurvey_threshold => 10,
                            uploadquota          => 500,                             uploadquota          => 500,
                              postsubmit           => 60,
                              mysqltables          => 172800,
                          );                           );
     if ($position eq 'top') {      if ($position eq 'top') {
         %defaultchecked = ('canuse_pdfforms' => 'off');          %defaultchecked = (
         @toggles = ('canuse_pdfforms');                              'canuse_pdfforms' => 'off',
                               'uselcmath'       => 'on',
                               'usejsme'         => 'on',
                               'canclone'        => 'none',
                             );
           @toggles = ('canuse_pdfforms','uselcmath','usejsme');
         ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,          ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
                                                  \%choices,$itemcount);                                                       \%choices,$itemcount);
           $css_class = $itemcount%2?' class="LC_odd_row"':'';
           $datatable .=
               '<tr'.$css_class.'><td valign="top">'.
               '<span class="LC_nobreak">'.$choices{'canclone'}.
               '</span></td><td class="LC_left_item">';
           my $currcanclone = 'none';
           my $onclick;
           my @cloneoptions = ('none','domain');
           my %clonetitles = (
                                none     => 'No additional course requesters',
                                domain   => "Any course requester in course's domain",
                                instcode => 'Course requests for official courses ...',
                             );
           my (%codedefaults,@code_order,@posscodes);
           if (&Apache::lonnet::auto_instcode_defaults($dom,\%codedefaults,
                                                       \@code_order) eq 'ok') {
               if (@code_order > 0) {
                   push(@cloneoptions,'instcode');
                   $onclick = ' onclick="toggleDisplay(this.form,'."'cloneinstcode'".');"';
               }
           }
           if (ref($settings) eq 'HASH') {
               if ($settings->{'canclone'}) {
                   if (ref($settings->{'canclone'}) eq 'HASH') {
                       if (ref($settings->{'canclone'}{'instcode'}) eq 'ARRAY') {
                           if (@code_order > 0) {
                               $currcanclone = 'instcode';
                               @posscodes = @{$settings->{'canclone'}{'instcode'}};
                           }
                       }
                   } elsif ($settings->{'canclone'} eq 'domain') {
                       $currcanclone = $settings->{'canclone'};
                   }
               }
           }
           foreach my $option (@cloneoptions) {
               my ($checked,$additional);
               if ($currcanclone eq $option) {
                   $checked = ' checked="checked"';
               }
               if ($option eq 'instcode') {
                   if (@code_order) {
                       my $show = 'none';
                       if ($checked) {
                           $show = 'block';
                       }
                       $additional = '<div id="cloneinstcode" style="display:'.$show.'" />'.
                                     &mt('Institutional codes for new and cloned course have identical:').
                                     '<br />';
                       foreach my $item (@code_order) {
                           my $codechk;
                           if ($checked) {
                               if (grep(/^\Q$item\E$/,@posscodes)) {
                                   $codechk = ' checked="checked"';
                               }
                           }
                           $additional .= '<label>'.
                                          '<input type="checkbox" name="clonecode" value="'.$item.'"'.$codechk.' />'.
                                          $item.'</label>';
                       }
                       $additional .= ('&nbsp;'x2).'('.&mt('check as many as needed').')</div>';
                   }
               }
               $datatable .=
                   '<span class="LC_nobreak"><label><input type="radio" name="canclone"'.$checked.
                   ' value="'.$option.'"'.$onclick.' />'.$clonetitles{$option}.
                   '</label>&nbsp;'.$additional.'</span><br />';
           }
           $datatable .= '</td>'.
                         '</tr>';
           $itemcount ++;
     } else {      } else {
         $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';          $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
         my ($currdefresponder,$def_official_credits,$def_unofficial_credits,$def_textbook_credits,          my ($currdefresponder,%defcredits,%curruploadquota,%deftimeout,%currmysql);
             %curruploadquota);  
         my $currusecredits = 0;          my $currusecredits = 0;
         my @types = ('official','unofficial','community','textbook');          my $postsubmitclient = 1;
           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 2784  sub print_coursedefaults { Line 4127  sub print_coursedefaults {
                 }                  }
             }              }
             if (ref($settings->{'coursecredits'}) eq 'HASH') {              if (ref($settings->{'coursecredits'}) eq 'HASH') {
                 $def_official_credits = $settings->{'coursecredits'}->{'official'};                  foreach my $type (@types) {
                 $def_unofficial_credits = $settings->{'coursecredits'}->{'unofficial'};                      next if ($type eq 'community');
                 $def_textbook_credits = $settings->{'coursecredits'}->{'textbook'};                      $defcredits{$type} = $settings->{'coursecredits'}->{$type};
                 if (($def_official_credits ne '') || ($def_unofficial_credits ne '') ||                      if ($defcredits{$type} ne '') {
                     ($def_textbook_credits ne '')) {                          $currusecredits = 1;
                     $currusecredits = 1;                      }
                   }
               }
               if (ref($settings->{'postsubmit'}) eq 'HASH') {
                   if ($settings->{'postsubmit'}->{'client'} eq 'off') {
                       $postsubmitclient = 0;
                       foreach my $type (@types) {
                           $deftimeout{$type} = $staticdefaults{'postsubmit'};
                       }
                   } else {
                       foreach my $type (@types) {
                           if (ref($settings->{'postsubmit'}->{'timeout'}) eq 'HASH') {
                               if ($settings->{'postsubmit'}->{'timeout'}->{$type} =~ /^\d+$/) {
                                   $deftimeout{$type} = $settings->{'postsubmit'}->{'timeout'}->{$type};
                               } else {
                                   $deftimeout{$type} = $staticdefaults{'postsubmit'};
                               }
                           } else {
                               $deftimeout{$type} = $staticdefaults{'postsubmit'};
                           }
                       }
                   }
               } else {
                   foreach my $type (@types) {
                       $deftimeout{$type} = $staticdefaults{'postsubmit'};
                   }
               }
               if (ref($settings->{'mysqltables'}) eq 'HASH') {
                   foreach my $type (keys(%{$settings->{'mysqltables'}})) {
                       $currmysql{$type} = $settings->{'mysqltables'}{$type};
                   }
               } else {
                   foreach my $type (@types) {
                       $currmysql{$type} = $staticdefaults{'mysqltables'};
                 }                  }
             }              }
           } else {
               foreach my $type (@types) {
                   $deftimeout{$type} = $staticdefaults{'postsubmit'};
               }
         }          }
         if (!$currdefresponder) {          if (!$currdefresponder) {
             $currdefresponder = $staticdefaults{'anonsurvey_threshold'};              $currdefresponder = $staticdefaults{'anonsurvey_threshold'};
Line 2831  sub print_coursedefaults { Line 4211  sub print_coursedefaults {
             $display = 'block';              $display = 'block';
         }          }
         my $additional = '<div id="credits" style="display: '.$display.'">'.          my $additional = '<div id="credits" style="display: '.$display.'">'.
                          '<span class="LC_nobreak">'.                           '<i>'.&mt('Default credits').'</i><br /><table><tr>';
                          &mt('Default credits for official courses [_1]',          foreach my $type (@types) {
                          '<input type="text" name="official_credits" value="'.              next if ($type eq 'community');
                          $def_official_credits.'" size="3" />').              $additional .= '<td align="center">'.&mt($type).'<br />'.
                          '</span><br />'.                             '<input type="text" name="'.$type.'_credits"'.
                          '<span class="LC_nobreak">'.                             ' value="'.$defcredits{$type}.'" size="3" /></td>';
                          &mt('Default credits for unofficial courses [_1]',          }
                          '<input type="text" name="unofficial_credits" value="'.          $additional .= '</tr></table></div>'."\n";
                          $def_unofficial_credits.'" size="3" />').  
                          '</span><br />'.  
                          '<span class="LC_nobreak">'.  
                          &mt('Default credits for textbook courses [_1]',  
                          '<input type="text" name="textbook_credits" value="'.  
                          $def_textbook_credits.'" size="3" />').  
                          '</span></div>'."\n";  
         %defaultchecked = ('coursecredits' => 'off');          %defaultchecked = ('coursecredits' => 'off');
         @toggles = ('coursecredits');          @toggles = ('coursecredits');
         my $current = {          my $current = {
Line 2853  sub print_coursedefaults { Line 4226  sub print_coursedefaults {
                       };                        };
         (my $table,$itemcount) =          (my $table,$itemcount) =
             &radiobutton_prefs($current,\@toggles,\%defaultchecked,              &radiobutton_prefs($current,\@toggles,\%defaultchecked,
                                \%choices,$itemcount,$onclick,$additional);                                 \%choices,$itemcount,$onclick,$additional,'left');
         $datatable .= $table;          $datatable .= $table;
           $onclick = "toggleDisplay(this.form,'studentsubmission');";
           my $display = 'none';
           if ($postsubmitclient) {
               $display = 'block';
           }
           $additional = '<div id="studentsubmission" style="display: '.$display.'">'.
                         &mt('Number of seconds submit is disabled').'<br />'.
                         '<i>'.&mt('Enter 0 to remain disabled until page reload.').'</i><br />'.
                         '<table><tr>';
           foreach my $type (@types) {
               $additional .= '<td align="center">'.&mt($type).'<br />'.
                              '<input type="text" name="'.$type.'_timeout" value="'.
                              $deftimeout{$type}.'" size="5" /></td>';
           }
           $additional .= '</tr></table></div>'."\n";
           %defaultchecked = ('postsubmit' => 'on');
           @toggles = ('postsubmit');
           $current = {
                          'postsubmit' => $postsubmitclient,
                      };
           ($table,$itemcount) =
               &radiobutton_prefs($current,\@toggles,\%defaultchecked,
                                  \%choices,$itemcount,$onclick,$additional,'left');
           $datatable .= $table;
           $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
           $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
                         $choices{'mysqltables'}.
                         '</span></td>'.
                         '<td align="right" class="LC_right_item">'.
                         '<table><tr>';
           foreach my $type (@types) {
               $datatable .= '<td align="center">'.&mt($type).'<br />'.
                              '<input type="text" name="mysqltables_'.$type.'"'.
                              ' value="'.$currmysql{$type}.'" size="8" /></td>';
           }
           $datatable .= '</tr></table></td></tr>'."\n";
         $itemcount ++;          $itemcount ++;
   
     }      }
     $$rowtotal += $itemcount;      $$rowtotal += $itemcount;
     return $datatable;      return $datatable;
Line 2865  sub print_selfenrollment { Line 4275  sub print_selfenrollment {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable);      my ($css_class,$datatable);
     my $itemcount = 1;      my $itemcount = 1;
     my @types = ('official','unofficial','community','textbook');      my @types = ('official','unofficial','community','textbook','placement');
     if (($position eq 'top') || ($position eq 'middle')) {      if (($position eq 'top') || ($position eq 'middle')) {
         my ($rowsref,$titlesref) = &Apache::lonuserutils::get_selfenroll_titles();          my ($rowsref,$titlesref) = &Apache::lonuserutils::get_selfenroll_titles();
         my %descs = &Apache::lonuserutils::selfenroll_default_descs();          my %descs = &Apache::lonuserutils::selfenroll_default_descs();
Line 3060  sub print_validation_rows { Line 4470  sub print_validation_rows {
     }      }
     if ($caller eq 'requestcourses') {      if ($caller eq 'requestcourses') {
         my %currhash;          my %currhash;
         if (ref($settings->{'validation'}) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if ($settings->{'validation'}{'dc'} ne '') {              if (ref($settings->{'validation'}) eq 'HASH') {
                 $currhash{$settings->{'validation'}{'dc'}} = 1;                  if ($settings->{'validation'}{'dc'} ne '') {
                       $currhash{$settings->{'validation'}{'dc'}} = 1;
                   }
             }              }
         }          }
         my $numinrow = 2;          my $numinrow = 2;
         my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',          my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',
                                                        'validationdc',%currhash);                                                         'validationdc',%currhash);
           my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
           $datatable .= '</td></tr><tr'.$css_class.'><td>';
         if ($numdc > 1) {          if ($numdc > 1) {
             $datatable .= '</td></tr><tr class="LC_odd_row"><td>'.              $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)');
                           &mt('Course creation processed as: (choose Dom. Coord.)').  
                           '</td><td class="LC_left_item">'.$dctable.'</td></tr>';  
         } else {          } else {
             $datatable .= $dctable.'</td></tr>';              $datatable .=  &mt('Course creation processed as: ');
         }          }
           $datatable .= '</td><td class="LC_left_item">'.$dctable.'</td></tr>';
         $itemcount ++;          $itemcount ++;
     }      }
     if (ref($rowtotal)) {      if (ref($rowtotal)) {
Line 3085  sub print_validation_rows { Line 4498  sub print_validation_rows {
   
 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);
             $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$rowtotal);              my $curroffloadnow;
               if (ref($settings) eq 'HASH') {
                   if (ref($settings->{'offloadnow'}) eq 'HASH') {
                       $curroffloadnow = $settings->{'offloadnow'};
                   }
               }
               $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$curroffloadnow,$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 3219  sub print_usersessions { Line 4775  sub print_usersessions {
     return $datatable;      return $datatable;
 }  }
   
   sub ssl_titles {
       return &Apache::lonlocal::texthash (
                  dom           => 'LON-CAPA servers/VMs from same domain',
                  intdom        => 'LON-CAPA servers/VMs from same "internet" domain',
                  other         => 'External LON-CAPA servers/VMs',
                  connto        => 'Connections to other servers',
                  connfrom      => 'Connections from other servers',
                  replication   => 'Replicating content to other institutions',
                  certreq       => 'Client certificate required, but specific domains exempt',
                  nocertreq     => 'No client certificate required, except for specific domains',
                  no            => 'SSL not used',
                  yes           => 'SSL Optional (used if available)',
                  req           => 'SSL Required',
       );
   }
   
   sub print_trust {
       my ($prefix,$dom,$settings,$rowtotal) = @_;
       my ($css_class,$datatable,%checked,%choices);
       my (%by_ip,%by_location,@intdoms,@instdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
       my $itemcount = 1;
       my %titles = &trust_titles();
       my @types = ('exc','inc');
       if ($prefix eq 'top') {
           $prefix = 'content';
       } elsif ($prefix eq 'bottom') {
           $prefix = 'msg';
       }
       ($datatable,$itemcount) = &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
       $$rowtotal += $itemcount;
       return $datatable;
   }
   
   sub trust_titles {
       return &Apache::lonlocal::texthash(
                  content  => "Access to this domain's content by others",
                  shared   => "Access to other domain's content by this domain",
                  enroll   => "Enrollment in this domain's courses by others", 
                  othcoau  => "Co-author roles in this domain for others",
                  coaurem  => "Co-author roles for this domain's users elsewhere", 
                  domroles => "Domain roles in this domain assignable to others",
                  catalog  => "Course Catalog for this domain displayed elsewhere",
                  reqcrs   => "Requests for creation of courses in this domain by others",
                  msg      => "Users in other domains can send messages to this domain",
                  exc      => "Allow all, but exclude specific domains",
                  inc      => "Deny all, but include specific domains",
              );
   } 
   
 sub build_location_hashes {  sub build_location_hashes {
     my ($intdoms,$by_ip,$by_location) = @_;      my ($intdoms,$by_ip,$by_location,$instdoms) = @_;
     return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') &&      return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') &&
                   (ref($by_location) eq 'HASH'));                     (ref($by_location) eq 'HASH') && (ref($instdoms) eq 'ARRAY'));
     my %iphost = &Apache::lonnet::get_iphost();      my %iphost = &Apache::lonnet::get_iphost();
     my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary');      my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary');
     my $primary_ip = &Apache::lonnet::get_host_ip($primary_id);      my $primary_ip = &Apache::lonnet::get_host_ip($primary_id);
Line 3239  sub build_location_hashes { Line 4845  sub build_location_hashes {
             foreach my $id (@{$iphost{$ip}}) {              foreach my $id (@{$iphost{$ip}}) {
                 my $location = &Apache::lonnet::internet_dom($id);                  my $location = &Apache::lonnet::internet_dom($id);
                 if ($location) {                  if ($location) {
                     next if (grep(/^\Q$location\E$/,@{$intdoms}));                      if (grep(/^\Q$location\E$/,@{$intdoms})) {
                           my $dom = &Apache::lonnet::host_domain($id);
                           unless (grep(/^\Q$dom\E/,@{$instdoms})) {
                               push(@{$instdoms},$dom);
                           }
                           next;
                       }
                     if (ref($by_ip->{$ip}) eq 'ARRAY') {                      if (ref($by_ip->{$ip}) eq 'ARRAY') {
                         unless(grep(/^\Q$location\E$/,@{$by_ip->{$ip}})) {                          unless(grep(/^\Q$location\E$/,@{$by_ip->{$ip}})) {
                             push(@{$by_ip->{$ip}},$location);                              push(@{$by_ip->{$ip}},$location);
Line 3347  sub current_offloads_to { Line 4959  sub current_offloads_to {
 }  }
   
 sub spares_row {  sub spares_row {
     my ($dom,$servers,$spareid,$serverhomes,$altids,$rowtotal) = @_;      my ($dom,$servers,$spareid,$serverhomes,$altids,$curroffloadnow,$rowtotal) = @_;
     my $css_class;      my $css_class;
     my $numinrow = 4;      my $numinrow = 4;
     my $itemcount = 1;      my $itemcount = 1;
Line 3367  sub spares_row { Line 4979  sub spares_row {
                 }                  }
             }              }
             next unless (ref($spareid->{$server}) eq 'HASH');              next unless (ref($spareid->{$server}) eq 'HASH');
               my $checkednow;
               if (ref($curroffloadnow) eq 'HASH') {
                   if ($curroffloadnow->{$server}) {
                       $checkednow = ' checked="checked"';
                   }
               }
             $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';              $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
             $datatable .= '<tr'.$css_class.'>              $datatable .= '<tr'.$css_class.'>
                            <td rowspan="2">                             <td rowspan="2">
                             <span class="LC_nobreak">'.                              <span class="LC_nobreak">'.
                           &mt('[_1] when busy, offloads to:'                            &mt('[_1] when busy, offloads to:'
                               ,'<b>'.$server.'</b>').                                ,'<b>'.$server.'</b>').'</span><br />'.
                             '<span class="LC_nobreak">'."\n".
                             '<label><input type="checkbox" name="offloadnow" value="'.$server.'"'.$checkednow.' />'.
                             '&nbsp;'.&mt('Switch active users on next access').'</label></span>'.
                           "\n";                            "\n";
             my (%current,%canselect);              my (%current,%canselect);
             my @choices =               my @choices = 
Line 3577  sub print_loadbalancing { Line 5198  sub print_loadbalancing {
         my ($numspares,@spares) = &count_servers($lonhost,%servers);          my ($numspares,@spares) = &count_servers($lonhost,%servers);
         my @sparestypes = ('primary','default');          my @sparestypes = ('primary','default');
         my %typetitles = &sparestype_titles();          my %typetitles = &sparestype_titles();
           my %hostherechecked = (
                                     no => ' checked="checked"',
                                 );
         foreach my $sparetype (@sparestypes) {          foreach my $sparetype (@sparestypes) {
             my $targettable;              my $targettable;
             for (my $i=0; $i<$numspares; $i++) {              for (my $i=0; $i<$numspares; $i++) {
Line 3596  sub print_loadbalancing { Line 5220  sub print_loadbalancing {
                     $disabled = ' disabled="disabled"';                      $disabled = ' disabled="disabled"';
                 }                  }
                 $targettable .=                  $targettable .=
                     '<td><label><input type="checkbox" name="loadbalancing_target_'.$balnum.'_'.$sparetype.'"'.                      '<td><span class="LC_nobreak"><label>'.
                       '<input type="checkbox" name="loadbalancing_target_'.$balnum.'_'.$sparetype.'"'.
                     $checked.$disabled.' value="'.$chkboxval.'" id="loadbalancing_target_'.$balnum.'_'.$sparetype.'_'.$i.'" onclick="checkOffloads('."this,'$balnum','$sparetype'".');" /><span id="loadbalancing_targettxt_'.$balnum.'_'.$sparetype.'_'.$i.'">&nbsp;'.$chkboxval.                      $checked.$disabled.' value="'.$chkboxval.'" id="loadbalancing_target_'.$balnum.'_'.$sparetype.'_'.$i.'" onclick="checkOffloads('."this,'$balnum','$sparetype'".');" /><span id="loadbalancing_targettxt_'.$balnum.'_'.$sparetype.'_'.$i.'">&nbsp;'.$chkboxval.
                     '</span></label></td>';                      '</span></label></span></td>';
                 my $rem = $i%($numinrow);                  my $rem = $i%($numinrow);
                 if ($rem == 0) {                  if ($rem == 0) {
                     if (($i > 0) && ($i < $numspares-1)) {                      if (($i > 0) && ($i < $numspares-1)) {
Line 3621  sub print_loadbalancing { Line 5246  sub print_loadbalancing {
                 $datatable .=  '<i>'.$typetitles{$sparetype}.'</i><br />'.                  $datatable .=  '<i>'.$typetitles{$sparetype}.'</i><br />'.
                                '<table><tr>'.$targettable.'</tr></table><br />';                                 '<table><tr>'.$targettable.'</tr></table><br />';
             }              }
               $hostherechecked{$sparetype} = '';
               if (ref($currtargets{$lonhost}) eq 'HASH') {
                   if (ref($currtargets{$lonhost}{$sparetype}) eq 'ARRAY') {
                       if (grep(/^\Q$lonhost\E$/,@{$currtargets{$lonhost}{$sparetype}})) {
                           $hostherechecked{$sparetype} = ' checked="checked"';
                           $hostherechecked{'no'} = '';
                       }
                   }
               }
           }
           $datatable .= &mt('Hosting on balancer itself').'<br />'.
                         '<label><input type="radio" name="loadbalancing_target_'.$balnum.'_hosthere" value="no"'.
                         $hostherechecked{'no'}.' />'.&mt('No').'</label><br />';
           foreach my $sparetype (@sparestypes) {
               $datatable .= '<label><input type="radio" name="loadbalancing_target_'.$balnum.'_hosthere" '.
                             'value="'.$sparetype.'"'.$hostherechecked{$sparetype}.' /><i>'.$typetitles{$sparetype}.
                             '</i></label><br />';
         }          }
         $datatable .= '</div></td></tr>'.          $datatable .= '</div></td></tr>'.
                       &loadbalancing_rules($dom,$intdom,$currrules{$lonhost},                        &loadbalancing_rules($dom,$intdom,$currrules{$lonhost},
Line 3688  sub loadbalancing_rules { Line 5330  sub loadbalancing_rules {
             if (ref($currrules) eq 'HASH') {              if (ref($currrules) eq 'HASH') {
                 $current = $currrules->{$type};                  $current = $currrules->{$type};
             }              }
             if (($type eq '_LC_external') || ($type eq '_LC_internetdom') || ($type eq '_LC_ipchange')) {              if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {
                 if ($dom ne &Apache::lonnet::host_domain($lonhost)) {                  if ($dom ne &Apache::lonnet::host_domain($lonhost)) {
                     $current = '';                      $current = '';
                 }                  }
Line 3740  sub loadbalance_rule_row { Line 5382  sub loadbalance_rule_row {
     my @rulenames;      my @rulenames;
     my %ruletitles = &offloadtype_text();      my %ruletitles = &offloadtype_text();
     if (($type eq '_LC_ipchangesso') || ($type eq '_LC_ipchange')) {      if (($type eq '_LC_ipchangesso') || ($type eq '_LC_ipchange')) {
         @rulenames = ('balancer','offloadedto');          @rulenames = ('balancer','offloadedto','specific');
     } else {      } else {
         @rulenames = ('default','homeserver');          @rulenames = ('default','homeserver');
         if ($type eq '_LC_external') {          if ($type eq '_LC_external') {
Line 3751  sub loadbalance_rule_row { Line 5393  sub loadbalance_rule_row {
         push(@rulenames,'none');          push(@rulenames,'none');
     }      }
     my $style = $targets_div_style;      my $style = $targets_div_style;
     if (($type eq '_LC_external') || ($type eq '_LC_internetdom') || ($type eq '_LC_ipchange')) {      if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {
         $style = $homedom_div_style;          $style = $homedom_div_style;
     }      }
     my $space;      my $space;
Line 3802  sub loadbalance_rule_row { Line 5444  sub loadbalance_rule_row {
                    '<input type="radio" name="loadbalancing_rules_'.$balnum.'_'.$type.                     '<input type="radio" name="loadbalancing_rules_'.$balnum.'_'.$type.
                    '" id="loadbalancing_rules_'.$balnum.'_'.$type.'_'.$i.'" value="'.                     '" id="loadbalancing_rules_'.$balnum.'_'.$type.'_'.$i.'" value="'.
                    $rule.'" onclick="balanceruleChange('."this.form,'$balnum','$type'".                     $rule.'" onclick="balanceruleChange('."this.form,'$balnum','$type'".
                    ')"'.$checked.' />&nbsp;'.$ruletitles{$rulenames[$i]}.                     ')"'.$checked.' />&nbsp;';
                    '</label>'.$extra.'</span><br />'."\n";          if (($rulenames[$i] eq 'specific') && ($type =~ /^_LC_ipchange/)) {
               $output .= $ruletitles{'particular'};
           } else {
               $output .= $ruletitles{$rulenames[$i]};
           }
           $output .= '</label>'.$extra.'</span><br />'."\n";
     }      }
     $output .= '</div></td></tr>'."\n";      $output .= '</div></td></tr>'."\n";
     return $output;      return $output;
Line 3818  sub offloadtype_text { Line 5465  sub offloadtype_text {
            'none'             => 'No offload',             'none'             => 'No offload',
            'balancer'         => 'Session hosted on Load Balancer, after re-authentication',             'balancer'         => 'Session hosted on Load Balancer, after re-authentication',
            'offloadedto'      => 'Session hosted on offload server, after re-authentication',             'offloadedto'      => 'Session hosted on offload server, after re-authentication',
              'particular'       => 'Session hosted (after re-auth) on server:',
     );      );
     return %ruletitles;      return %ruletitles;
 }  }
Line 3832  sub sparestype_titles { Line 5480  sub sparestype_titles {
   
 sub contact_titles {  sub contact_titles {
     my %titles = &Apache::lonlocal::texthash (      my %titles = &Apache::lonlocal::texthash (
                    'supportemail' => 'Support E-mail address',                     'supportemail'    => 'Support E-mail address',
                    'adminemail'   => 'Default Server Admin E-mail address',                     'adminemail'      => 'Default Server Admin E-mail address',
                    'errormail'    => 'Error reports to be e-mailed to',                     'errormail'       => 'Error reports to be e-mailed to',
                    'packagesmail' => 'Package update alerts to be e-mailed to',                     'packagesmail'    => 'Package update alerts to be e-mailed to',
                    'helpdeskmail' => 'Helpdesk requests to be e-mailed to',                     'helpdeskmail'    => "Helpdesk requests for this domain's users",
                    'lonstatusmail' => 'E-mail from nightly status check (warnings/errors)',                     'otherdomsmail'   => 'Helpdesk requests for other (unconfigured) domains',
                    'requestsmail' => 'E-mail from course requests requiring approval',                     'lonstatusmail'   => 'E-mail from nightly status check (warnings/errors)',
                    'updatesmail'  => 'E-mail from nightly check of LON-CAPA module integrity/updates',                     'requestsmail'    => 'E-mail from course requests requiring approval',
                      'updatesmail'     => 'E-mail from nightly check of LON-CAPA module integrity/updates',
                    'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID',                     'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID',
                  );                   );
     my %short_titles = &Apache::lonlocal::texthash (      my %short_titles = &Apache::lonlocal::texthash (
Line 3849  sub contact_titles { Line 5498  sub contact_titles {
     return (\%titles,\%short_titles);      return (\%titles,\%short_titles);
 }  }
   
   sub helpform_fields {
       my %titles =  &Apache::lonlocal::texthash (
                          'username'   => 'Name',
                          'user'       => 'Username/domain',
                          'phone'      => 'Phone',
                          'cc'         => 'Cc e-mail',
                          'course'     => 'Course Details',
                          'section'    => 'Sections',
                          'screenshot' => 'File upload',
       );
       my @fields = ('username','phone','user','course','section','cc','screenshot');
       my %possoptions = (
                           username     => ['yes','no','req'],
                           phone        => ['yes','no','req'],
                           user         => ['yes','no'],
                           cc           => ['yes','no'],
                           course       => ['yes','no'],
                           section      => ['yes','no'],
                           screenshot   => ['yes','no'],
                         );
       my %fieldoptions = &Apache::lonlocal::texthash (
                            'yes'  => 'Optional',
                            'req'  => 'Required',
                            'no'   => "Not shown",
       );
       return (\@fields,\%titles,\%fieldoptions,\%possoptions);
   }
   
 sub tool_titles {  sub tool_titles {
     my %titles = &Apache::lonlocal::texthash (      my %titles = &Apache::lonlocal::texthash (
                      aboutme    => 'Personal web page',                       aboutme    => 'Personal web page',
Line 3859  sub tool_titles { Line 5536  sub tool_titles {
                      unofficial => 'Unofficial courses',                       unofficial => 'Unofficial courses',
                      community  => 'Communities',                       community  => 'Communities',
                      textbook   => 'Textbook courses',                       textbook   => 'Textbook courses',
                        placement  => 'Placement tests',
                  );                   );
     return %titles;      return %titles;
 }  }
Line 3869  sub courserequest_titles { Line 5547  sub courserequest_titles {
                                    unofficial => 'Unofficial',                                     unofficial => 'Unofficial',
                                    community  => 'Communities',                                     community  => 'Communities',
                                    textbook   => 'Textbook',                                     textbook   => 'Textbook',
                                      placement  => 'Placement tests',
                                    norequest  => 'Not allowed',                                     norequest  => 'Not allowed',
                                    approval   => 'Approval by Dom. Coord.',                                     approval   => 'Approval by Dom. Coord.',
                                    validate   => 'With validation',                                     validate   => 'With validation',
Line 4100  sub print_selfcreation { Line 5779  sub print_selfcreation {
                 $datatable .= '<tr>';                  $datatable .= '<tr>';
             }              }
             my $currval;              my $currval;
             if (ref($createsettings->{'shibenv'}) eq 'HASH') {              if (ref($createsettings) eq 'HASH') {
                 $currval = $createsettings->{'shibenv'}{$fields[$i]};                  if (ref($createsettings->{'shibenv'}) eq 'HASH') {
                       $currval = $createsettings->{'shibenv'}{$fields[$i]};
                   }
             }              }
             $datatable .= '<td class="LC_left_item">'.              $datatable .= '<td class="LC_left_item">'.
                           '<span class="LC_nobreak">'.                            '<span class="LC_nobreak">'.
Line 4256  sub email_as_username { Line 5937  sub email_as_username {
   
 sub captcha_choice {  sub captcha_choice {
     my ($context,$settings,$itemcount) = @_;      my ($context,$settings,$itemcount) = @_;
     my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext);      my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext,
           $vertext,$currver);
     my %lt = &captcha_phrases();      my %lt = &captcha_phrases();
     $keyentry = 'hidden';      $keyentry = 'hidden';
     if ($context eq 'cancreate') {      if ($context eq 'cancreate') {
Line 4274  sub captcha_choice { Line 5956  sub captcha_choice {
             $pubtext = $lt{'pub'};              $pubtext = $lt{'pub'};
             $privtext = $lt{'priv'};              $privtext = $lt{'priv'};
             $keyentry = 'text';              $keyentry = 'text';
               $vertext = $lt{'ver'};
               $currver = $settings->{'recaptchaversion'};
               if ($currver ne '2') {
                   $currver = 1;
               }
         }          }
         if (ref($settings->{'recaptchakeys'}) eq 'HASH') {          if (ref($settings->{'recaptchakeys'}) eq 'HASH') {
             $currpub = $settings->{'recaptchakeys'}{'public'};              $currpub = $settings->{'recaptchakeys'}{'public'};
Line 4307  sub captcha_choice { Line 5994  sub captcha_choice {
                $currpub.'" size="40" /></span><br />'."\n".                 $currpub.'" size="40" /></span><br />'."\n".
                '<span class="LC_nobreak"><span id="'.$context.'_recaptchaprivtxt">'.$privtext.'</span>&nbsp;'."\n".                 '<span class="LC_nobreak"><span id="'.$context.'_recaptchaprivtxt">'.$privtext.'</span>&nbsp;'."\n".
                '<input type="'.$keyentry.'" id="'.$context.'_recaptchapriv" name="'.$context.'_recaptchapriv" value="'.                 '<input type="'.$keyentry.'" id="'.$context.'_recaptchapriv" name="'.$context.'_recaptchapriv" value="'.
                $currpriv.'" size="40" /></span></td></tr></table>'."\n".                 $currpriv.'" size="40" /></span><br />'.
                  '<span class="LC_nobreak"><span id="'.$context.'_recaptchavertxt">'.$vertext.'</span>&nbsp;'."\n".
                  '<input type="'.$keyentry.'" id="'.$context.'_recaptchaversion" name="'.$context.'_recaptchaversion" value="'.
                  $currver.'" size="3" /></span><br />'.
                  '</td></tr></table>'."\n".
                '</td></tr>';                 '</td></tr>';
     return $output;      return $output;
 }  }
Line 4442  sub print_usermodification { Line 6133  sub print_usermodification {
 sub print_defaults {  sub print_defaults {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my $rownum = 0;      my $rownum = 0;
     my ($datatable,$css_class);      my ($datatable,$css_class,$titles);
       unless ($position eq 'bottom') {
           $titles = &defaults_titles($dom);
       }
     if ($position eq 'top') {      if ($position eq 'top') {
         my @items = ('auth_def','auth_arg_def','lang_def','timezone_def',          my @items = ('auth_def','auth_arg_def','lang_def','timezone_def',
                      'datelocale_def','portal_def');                       'datelocale_def','portal_def');
Line 4455  sub print_defaults { Line 6149  sub print_defaults {
                 $defaults{$item} = $domdefaults{$item};                  $defaults{$item} = $domdefaults{$item};
             }              }
         }          }
         my $titles = &defaults_titles($dom);  
         foreach my $item (@items) {          foreach my $item (@items) {
             if ($rownum%2) {              if ($rownum%2) {
                 $css_class = '';                  $css_class = '';
Line 4490  sub print_defaults { Line 6183  sub print_defaults {
                 my $includeempty = 1;                  my $includeempty = 1;
                 $datatable .= &Apache::loncommon::select_datelocale($item,$defaults{$item},undef,$includeempty);                  $datatable .= &Apache::loncommon::select_datelocale($item,$defaults{$item},undef,$includeempty);
             } elsif ($item eq 'lang_def') {              } elsif ($item eq 'lang_def') {
                 my %langchoices = &get_languages_hash();                  my $includeempty = 1;
                 $langchoices{''} = 'No language preference';                  $datatable .= &Apache::loncommon::select_language($item,$defaults{$item},$includeempty);
                 %langchoices = &Apache::lonlocal::texthash(%langchoices);  
                 $datatable .= &Apache::loncommon::select_form($defaults{$item},$item,  
                                                               \%langchoices);  
             } else {              } else {
                 my $size;                  my $size;
                 if ($item eq 'portal_def') {                  if ($item eq 'portal_def') {
Line 4506  sub print_defaults { Line 6196  sub print_defaults {
             $datatable .= '</td></tr>';              $datatable .= '</td></tr>';
             $rownum ++;              $rownum ++;
         }          }
       } elsif ($position eq 'middle') {
           my @items = ('intauth_cost','intauth_check','intauth_switch');
           my %defaults;
           if (ref($settings) eq 'HASH') {
               %defaults = %{$settings};
               if ($defaults{'intauth_cost'} !~ /^\d+$/) {
                   $defaults{'intauth_cost'} = 10;
               }
               if ($defaults{'intauth_check'} !~ /^(0|1|2)$/) {
                   $defaults{'intauth_check'} = 0;
               }
               if ($defaults{'intauth_switch'} !~ /^(0|1|2)$/) {
                   $defaults{'intauth_switch'} = 0;
               }
           } else {
               %defaults = (
                             'intauth_cost'   => 10,
                             'intauth_check'  => 0,
                             'intauth_switch' => 0,
                           );
           }
           foreach my $item (@items) {
               if ($rownum%2) {
                   $css_class = '';
               } else {
                   $css_class = ' class="LC_odd_row" ';
               }
               $datatable .= '<tr'.$css_class.'>'.
                             '<td><span class="LC_nobreak">'.$titles->{$item}.
                             '</span></td><td class="LC_left_item" colspan="3">';
               if ($item eq 'intauth_switch') {
                   my @options = (0,1,2);
                   my %optiondesc = &Apache::lonlocal::texthash (
                                      0 => 'No',
                                      1 => 'Yes',
                                      2 => 'Yes, and copy existing passwd file to passwd.bak file',
                                    );
                   $datatable .= '<table width="100%">';
                   foreach my $option (@options) {
                       my $checked = ' ';
                       if ($defaults{$item} eq $option) {
                           $checked = ' checked="checked"';
                       }
                       $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.
                                     '<label><input type="radio" name="'.$item.
                                     '" value="'.$option.'"'.$checked.' />'.
                                     $optiondesc{$option}.'</label></span></td></tr>';
                   }
                   $datatable .= '</table>';
               } elsif ($item eq 'intauth_check') {
                   my @options = (0,1,2);
                   my %optiondesc = &Apache::lonlocal::texthash (
                                      0 => 'No',
                                      1 => 'Yes, allow login then update passwd file using default cost (if higher)',
                                      2 => 'Yes, disallow login if stored cost is less than domain default',
                                    );
                   $datatable .= '<table wisth="100%">';
                   foreach my $option (@options) {
                       my $checked = ' ';
                       my $onclick;
                       if ($defaults{$item} eq $option) {
                           $checked = ' checked="checked"';
                       }
                       if ($option == 2) {
                           $onclick = ' onclick="javascript:warnIntAuth(this);"';
                       }
                       $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.
                                     '<label><input type="radio" name="'.$item.
                                     '" value="'.$option.'"'.$checked.$onclick.' />'.
                                     $optiondesc{$option}.'</label></span></td></tr>';
                   }
                   $datatable .= '</table>';
               } else {
                   $datatable .= '<input type="text" name="'.$item.'" value="'.
                                 $defaults{$item}.'" size="3" onblur="javascript:warnIntAuth(this);" />'; 
               }
               $datatable .= '</td></tr>';
               $rownum ++;
           }
     } else {      } else {
         my (%defaults);          my %defaults;
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH') &&              if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH') &&
                 (ref($settings->{'inststatusguest'}) eq 'ARRAY')) {                  (ref($settings->{'inststatusguest'}) eq 'ARRAY')) {
Line 4563  sub print_defaults { Line 6332  sub print_defaults {
                     $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';                      $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                 }                  }
                 $datatable .= '</select>&nbsp;'.&mt('Internal ID:').                  $datatable .= '</select>&nbsp;'.&mt('Internal ID:').
                               '<input type="text" size="10" name="addinststatus" value="" /></span>'.                                '<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"><span class="LC_nobreak">'.
                               &mt('Name displayed:').                                &mt('Name displayed:').
Line 4602  sub defaults_titles { Line 6371  sub defaults_titles {
                    'timezone_def'  => 'Default timezone',                     'timezone_def'  => 'Default timezone',
                    'datelocale_def' => 'Default locale for dates',                     'datelocale_def' => 'Default locale for dates',
                    'portal_def'     => 'Portal/Default URL',                     'portal_def'     => 'Portal/Default URL',
                      'intauth_cost'   => 'Encryption cost for bcrypt (positive integer)',
                      'intauth_check'  => 'Check bcrypt cost if authenticated',
                      'intauth_switch' => 'Existing crypt-based switched to bcrypt on authentication',
                  );                   );
     if ($dom) {      if ($dom) {
         my $uprimary_id = &Apache::lonnet::domain($dom,'primary');          my $uprimary_id = &Apache::lonnet::domain($dom,'primary');
Line 4844  sub print_coursecategories { Line 6616  sub print_coursecategories {
         my $toggle_catscomm_dom = ' checked="checked" ';          my $toggle_catscomm_dom = ' checked="checked" ';
         my $can_catcomm_comm = ' ';          my $can_catcomm_comm = ' ';
         my $can_catcomm_dom = ' checked="checked" ';          my $can_catcomm_dom = ' checked="checked" ';
           my $toggle_catsplace_place = ' ';
           my $toggle_catsplace_dom = ' checked="checked" ';
           my $can_catplace_place = ' ';
           my $can_catplace_dom = ' checked="checked" ';
   
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if ($settings->{'togglecats'} eq 'crs') {              if ($settings->{'togglecats'} eq 'crs') {
Line 4862  sub print_coursecategories { Line 6638  sub print_coursecategories {
                 $can_catcomm_comm = $can_catcomm_dom;                  $can_catcomm_comm = $can_catcomm_dom;
                 $can_catcomm_dom = ' ';                  $can_catcomm_dom = ' ';
             }              }
               if ($settings->{'togglecatsplace'} eq 'place') {
                   $toggle_catsplace_place = $toggle_catsplace_dom;
                   $toggle_catsplace_dom = ' ';
               }
               if ($settings->{'categorizeplace'} eq 'place') {
                   $can_catplace_place = $can_catplace_dom;
                   $can_catplace_dom = ' ';
               }
         }          }
         my %title = &Apache::lonlocal::texthash (          my %title = &Apache::lonlocal::texthash (
                      togglecats     => 'Show/Hide a course in catalog',                       togglecats      => 'Show/Hide a course in catalog',
                      togglecatscomm => 'Show/Hide a community in catalog',                       togglecatscomm  => 'Show/Hide a community in catalog',
                      categorize     => 'Assign a category to a course',                       togglecatsplace => 'Show/Hide a placement test in catalog',
                      categorizecomm => 'Assign a category to a community',                       categorize      => 'Assign a category to a course',
                        categorizecomm  => 'Assign a category to a community',
                        categorizeplace => 'Assign a category to a placement test',
                     );                      );
         my %level = &Apache::lonlocal::texthash (          my %level = &Apache::lonlocal::texthash (
                      dom  => 'Set in Domain',                       dom   => 'Set in Domain',
                      crs  => 'Set in Course',                       crs   => 'Set in Course',
                      comm => 'Set in Community',                       comm  => 'Set in Community',
                        place => 'Set in Placement Test',
                     );                      );
         $datatable = '<tr class="LC_odd_row">'.          $datatable = '<tr class="LC_odd_row">'.
                   '<td>'.$title{'togglecats'}.'</td>'.                    '<td>'.$title{'togglecats'}.'</td>'.
Line 4902  sub print_coursecategories { Line 6689  sub print_coursecategories {
                   $can_catcomm_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.                    $can_catcomm_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.
                   '<label><input type="radio" name="categorizecomm"'.                    '<label><input type="radio" name="categorizecomm"'.
                   $can_catcomm_comm.'value="comm" />'.$level{'comm'}.'</label></span></td>'.                    $can_catcomm_comm.'value="comm" />'.$level{'comm'}.'</label></span></td>'.
                     '</tr><tr>'.
                     '<td>'.$title{'togglecatsplace'}.'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                     '<input type="radio" name="togglecatsplace"'.
                     $toggle_catsplace_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.
                     '<label><input type="radio" name="togglecatscomm"'.
                     $toggle_catsplace_place.' value="comm" />'.$level{'place'}.'</label></span></td>'.
                     '</tr><tr>'.
                     '<td>'.$title{'categorizeplace'}.'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak">'.
                     '<label><input type="radio" name="categorizeplace"'.
                     $can_catplace_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.
                     '<label><input type="radio" name="categorizeplace"'.
                     $can_catplace_place.'value="place" />'.$level{'place'}.'</label></span></td>'.
                   '</tr>';                    '</tr>';
         $$rowtotal += 4;          $$rowtotal += 6;
     } else {      } else {
         my $css_class;          my $css_class;
         my $itemcount = 1;          my $itemcount = 1;
Line 4928  sub print_coursecategories { Line 6729  sub print_coursecategories {
                     my %default_names = (                      my %default_names = (
                           instcode    => &mt('Official courses'),                            instcode    => &mt('Official courses'),
                           communities => &mt('Communities'),                            communities => &mt('Communities'),
                             placement   => &mt('Placement Tests'),
                     );                      );
   
                     if ((!grep(/^instcode$/,@{$cats[0]})) ||                       if ((!grep(/^instcode$/,@{$cats[0]})) || 
                         ($cathash->{'instcode::0'} eq '') ||                          ($cathash->{'instcode::0'} eq '') ||
                         (!grep(/^communities$/,@{$cats[0]})) ||                           (!grep(/^communities$/,@{$cats[0]})) || 
                         ($cathash->{'communities::0'} eq '')) {                          ($cathash->{'communities::0'} eq '') ||
                           (!grep(/^placement$/,@{$cats[0]})) ||
                           ($cathash->{'placement::0'} eq '')) {
                         $maxnum ++;                          $maxnum ++;
                     }                      }
                     my $lastidx;                      my $lastidx;
Line 4954  sub print_coursecategories { Line 6758  sub print_coursecategories {
                             $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';                              $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                         }                          }
                         $datatable .= '</select></span></td><td>';                          $datatable .= '</select></span></td><td>';
                         if ($parent eq 'instcode' || $parent eq 'communities') {                          if ($parent eq 'instcode' || $parent eq 'communities' || $parent eq 'placement') {
                             $datatable .=  '<span class="LC_nobreak">'                              $datatable .=  '<span class="LC_nobreak">'
                                            .$default_names{$parent}.'</span>';                                             .$default_names{$parent}.'</span>';
                             if ($parent eq 'instcode') {                              if ($parent eq 'instcode') {
Line 4977  sub print_coursecategories { Line 6781  sub print_coursecategories {
                             $datatable .= '<label><input type="radio" name="'                              $datatable .= '<label><input type="radio" name="'
                                           .$parent.'" value="0" />'                                            .$parent.'" value="0" />'
                                           .&mt('Do not display').'</label></span>';                                            .&mt('Do not display').'</label></span>';
                             if ($parent eq 'communities') {                              if (($parent eq 'communities') || ($parent eq 'placement')) {
                                 $datatable .= '</td></tr></table>';                                  $datatable .= '</td></tr></table>';
                             }                              }
                             $datatable .= '</td>';                              $datatable .= '</td>';
Line 5009  sub print_coursecategories { Line 6813  sub print_coursecategories {
                                   .'<input type="text" size="20" name="addcategory_name" value="" /></td>'                                    .'<input type="text" size="20" name="addcategory_name" value="" /></td>'
                                   .'</tr>'."\n";                                    .'</tr>'."\n";
                     $itemcount ++;                      $itemcount ++;
                     foreach my $default ('instcode','communities') {                      foreach my $default ('instcode','communities','placement') {
                         if ((!grep(/^\Q$default\E$/,@{$cats[0]})) || ($cathash->{$default.'::0'} eq '')) {                          if ((!grep(/^\Q$default\E$/,@{$cats[0]})) || ($cathash->{$default.'::0'} eq '')) {
                             $css_class = $itemcount%2?' class="LC_odd_row"':'';                              $css_class = $itemcount%2?' class="LC_odd_row"':'';
                             my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','$lastidx'".');"';                              my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','$lastidx'".');"';
Line 5098  sub print_serverstatuses { Line 6902  sub print_serverstatuses {
   
 sub serverstatus_pages {  sub serverstatus_pages {
     return ('userstatus','lonstatus','loncron','server-status','codeversions',      return ('userstatus','lonstatus','loncron','server-status','codeversions',
             'checksums','clusterstatus','metadata_keywords','metadata_harvest',              'checksums','clusterstatus','certstatus','metadata_keywords',
             'takeoffline','takeonline','showenv','toggledebug','ping','domconf',              'metadata_harvest','takeoffline','takeonline','showenv','toggledebug',
             'uniquecodes','diskusage');              'ping','domconf','uniquecodes','diskusage','coursecatalog');
 }  }
   
 sub defaults_javascript {  sub defaults_javascript {
     my ($settings) = @_;      my ($settings) = @_;
     my ($output,$jstext);       my $intauthcheck = &mt('Warning: disallowing login for an authenticated user if the stored cost is less than the default will require a password reset by/for the user.');
       my $intauthcost = &mt('Warning: bcrypt encryption cost for internal authentication must be an integer.');
       &js_escape(\$intauthcheck);
       &js_escape(\$intauthcost);
       my $intauthjs = <<"ENDSCRIPT";
   
   function warnIntAuth(field) {
       if (field.name == 'intauth_check') {
           if (field.value == '2') {
               alert('$intauthcheck');
           }
       }
       if (field.name == 'intauth_cost') {
           field.value.replace(/\s/g,'');
           if (field.value != '') {
               var regexdigit=/^\\d+\$/;
               if (!regexdigit.test(field.value)) {
                   alert('$intauthcost');
               }
           }
       }
       return;
   }
   
   ENDSCRIPT
   
       if (ref($settings) ne 'HASH') {
           return &Apache::lonhtmlcommon::scripttag($intauthjs);
       }
     if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {      if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {
         my $maxnum = scalar(@{$settings->{'inststatusorder'}});          my $maxnum = scalar(@{$settings->{'inststatusorder'}});
         if ($maxnum eq '') {          if ($maxnum eq '') {
             $maxnum = 0;              $maxnum = 0;
         }          }
         $maxnum ++;          $maxnum ++;
         $jstext = '    var inststatuses = Array('."'".join("','",@{$settings->{'inststatusorder'}})."'".');';            my $jstext = '    var inststatuses = Array('."'".join("','",@{$settings->{'inststatusorder'}})."'".');';  
         return <<"ENDSCRIPT";          return <<"ENDSCRIPT";
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
Line 5159  $jstext Line 6991  $jstext
     return;      return;
 }  }
   
   $intauthjs
   
 // ]]>  // ]]>
 </script>  </script>
   
 ENDSCRIPT  ENDSCRIPT
       } else {
           return &Apache::lonhtmlcommon::scripttag($intauthjs);
     }      }
 }  }
   
Line 5190  sub coursecategories_javascript { Line 7026  sub coursecategories_javascript {
     }      }
     my $instcode_reserved = &mt('The name: [_1] is a reserved category.','"instcode"');      my $instcode_reserved = &mt('The name: [_1] is a reserved category.','"instcode"');
     my $communities_reserved = &mt('The name: [_1] is a reserved category.','"communities"');      my $communities_reserved = &mt('The name: [_1] is a reserved category.','"communities"');
     my $choose_again = '\\n'.&mt('Please use a different name for the new top level category.');       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.'); 
       &js_escape(\$instcode_reserved);
       &js_escape(\$communities_reserved);
       &js_escape(\$placement_reserved);
       &js_escape(\$choose_again);
     $output = <<"ENDSCRIPT";      $output = <<"ENDSCRIPT";
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
Line 5259  function categoryCheck(form) { Line 7100  function categoryCheck(form) {
         alert('$communities_reserved\\n$choose_again');          alert('$communities_reserved\\n$choose_again');
         return false;          return false;
     }      }
       if (form.elements['addcategory_name'].value == 'placement') {
           alert('$placement_reserved\\n$choose_again');
           return false;
       }
     return true;      return true;
 }  }
   
Line 5275  sub initialize_categories { Line 7120  sub initialize_categories {
     my %default_names = (      my %default_names = (
                       instcode    => 'Official courses (with institutional codes)',                        instcode    => 'Official courses (with institutional codes)',
                       communities => 'Communities',                        communities => 'Communities',
                         placement   => 'Placement Tests',
                         );                          );
     my $select0 = ' selected="selected"';      my $select0 = ' selected="selected"';
     my $select1 = '';      my $select1 = '';
     foreach my $default ('instcode','communities') {      foreach my $default ('instcode','communities','placement') {
         $css_class = $itemcount%2?' class="LC_odd_row"':'';          $css_class = $itemcount%2?' class="LC_odd_row"':'';
         $chgstr = ' onchange="javascript:reorderCats(this.form,'."'',$default"."_pos','0'".');"';          $chgstr = ' onchange="javascript:reorderCats(this.form,'."'',$default"."_pos','0'".');"';
         if ($default eq 'communities') {          if (($default eq 'communities') || ($default eq 'placement')) {
             $select1 = $select0;              $select1 = $select0;
             $select0 = '';              $select0 = '';
         }          }
Line 5705  sub modify_login { Line 7551  sub modify_login {
     }      }
   
     my %servers = &Apache::lonnet::internet_dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my %domservers = &Apache::lonnet::get_servers($dom);
     my @loginvia_attribs = ('serverpath','custompath','exempt');      my @loginvia_attribs = ('serverpath','custompath','exempt');
     if (keys(%servers) > 1) {      if (keys(%servers) > 1) {
         foreach my $lonhost (keys(%servers)) {          foreach my $lonhost (keys(%servers)) {
Line 5747  sub modify_login { Line 7594  sub modify_login {
                             $changes{'loginvia'}{$lonhost} = 1;                              $changes{'loginvia'}{$lonhost} = 1;
                         }                          }
                         if ($item eq 'exempt') {                          if ($item eq 'exempt') {
                             $new =~ s/^\s+//;                              $new = &check_exempt_addresses($new);
                             $new =~ s/\s+$//;  
                             my @poss_ips = split(/\s*[,:]\s*/,$new);  
                             my @okips;  
                             foreach my $ip (@poss_ips) {  
                                 if ($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {  
                                     if (($1 <= 255) && ($2 <= 255) && ($3 <= 255) && ($4 <= 255)) {  
                                         push(@okips,$ip);   
                                     }  
                                 }  
                             }  
                             if (@okips > 0) {  
                                 $new = join(',',@okips);   
                             } else {  
                                 $new = '';   
                             }  
                         }                          }
                         $loginhash{login}{loginvia}{$lonhost}{$item} = $new;                          $loginhash{login}{loginvia}{$lonhost}{$item} = $new;
                     }                      }
Line 5858  sub modify_login { Line 7690  sub modify_login {
                         $errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';                          $errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';
                         if ((grep(/^\Q$lang\E$/,@currlangs)) &&                          if ((grep(/^\Q$lang\E$/,@currlangs)) &&
                             (!grep(/^\Q$lang\E$/,@delurls))) {                              (!grep(/^\Q$lang\E$/,@delurls))) {
   
                             $loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang};                              $loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang};
                         }                          }
                     }                      }
Line 5874  sub modify_login { Line 7705  sub modify_login {
             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';              $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
         }          }
     }      }
   
       my (%currheadtagurls,%currexempt,@newhosts,%newheadtagurls,%possexempt);
       if (ref($domconfig{'login'}) eq 'HASH') {
           if (ref($domconfig{'login'}{'headtag'}) eq 'HASH') {
               foreach my $lonhost (keys(%{$domconfig{'login'}{'headtag'}})) {
                   if ($domservers{$lonhost}) {
                       if (ref($domconfig{'login'}{'headtag'}{$lonhost}) eq 'HASH') {
                           $currheadtagurls{$lonhost} = $domconfig{'login'}{'headtag'}{$lonhost}{'url'};
                           $currexempt{$lonhost} = $domconfig{'login'}{'headtag'}{$lonhost}{'exempt'};
                       }
                   }
               }
           }
       }
       my @delheadtagurls = &Apache::loncommon::get_env_multiple('form.loginheadtag_del');
       foreach my $lonhost (sort(keys(%domservers))) {
           if (grep(/^\Q$lonhost\E$/,@delheadtagurls)) {
               $changes{'headtag'}{$lonhost} = 1;
           } else {
               if ($env{'form.loginheadtagexempt_'.$lonhost}) {
                   $possexempt{$lonhost} = &check_exempt_addresses($env{'form.loginheadtagexempt_'.$lonhost});
               }
               if ($env{'form.loginheadtag_'.$lonhost.'.filename'}) {
                   push(@newhosts,$lonhost);
               } elsif ($currheadtagurls{$lonhost}) {
                   $loginhash{'login'}{'headtag'}{$lonhost}{'url'} = $currheadtagurls{$lonhost};
                   if ($currexempt{$lonhost}) {
                       if ((!exists($possexempt{$lonhost})) || ($possexempt{$lonhost} ne $currexempt{$lonhost})) {
                           $changes{'headtag'}{$lonhost} = 1;
                       }
                   } elsif ($possexempt{$lonhost}) {
                       $changes{'headtag'}{$lonhost} = 1;
                   }
                   if ($possexempt{$lonhost}) {
                       $loginhash{'login'}{'headtag'}{$lonhost}{'exempt'} = $possexempt{$lonhost};
                   }
               }
           }
       }
       if (@newhosts) {
           my $error;
           my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
           if ($configuserok eq 'ok') {
               if ($switchserver) {
                   $error = &mt("Upload of custom markup is not permitted to this server: [_1]",$switchserver);
               } elsif ($author_ok eq 'ok') {
                   foreach my $lonhost (@newhosts) {
                       my $formelem = 'loginheadtag_'.$lonhost;
                       (my $result,$newheadtagurls{$lonhost}) = &publishlogo($r,'upload',$formelem,$dom,$confname,
                                                                             "login/headtag/$lonhost",'','',
                                                                             $env{'form.loginheadtag_'.$lonhost.'.filename'});
                       if ($result eq 'ok') {
                           $loginhash{'login'}{'headtag'}{$lonhost}{'url'} = $newheadtagurls{$lonhost};
                           $changes{'headtag'}{$lonhost} = 1;
                           if ($possexempt{$lonhost}) {
                               $loginhash{'login'}{'headtag'}{$lonhost}{'exempt'} = $possexempt{$lonhost};
                           }
                       } else {
                           my $puberror = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",
                                              $newheadtagurls{$lonhost},$result);
                           $errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';
                           if ((grep(/^\Q$lonhost\E$/,keys(%currheadtagurls))) &&
                               (!grep(/^\Q$lonhost\E$/,@delheadtagurls))) {
                               $loginhash{'login'}{'headtag'}{$lonhost} = $currheadtagurls{$lonhost};
                           }
                       }
                   }
               } else {
                   $error = &mt("Upload of custom markup file(s) failed because an author role could not be assigned to a Domain Configuration user ([_1]) in domain: [_2].  Error was: [_3].",$confname,$dom,$author_ok);
               }
           } else {
               $error = &mt("Upload of custom markup file(s) failed because a Domain Configuration user ([_1]) could not be created in domain: [_2].  Error was: [_3].",$confname,$dom,$configuserok);
           }
           if ($error) {
               &Apache::lonnet::logthis($error);
               $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
           }
       }
     &process_captcha('login',\%changes,$loginhash{'login'},$domconfig{'login'});      &process_captcha('login',\%changes,$loginhash{'login'},$domconfig{'login'});
   
     my $defaulthelpfile = '/adm/loginproblems.html';      my $defaulthelpfile = '/adm/loginproblems.html';
Line 5974  sub modify_login { Line 7883  sub modify_login {
                             }                              }
                         }                          }
                     }                      }
                   } elsif ($item eq 'headtag') {
                       if (ref($changes{$item}) eq 'HASH') {
                           foreach my $lonhost (sort(keys(%{$changes{$item}}))) {
                               if (grep(/^\Q$lonhost\E$/,@delheadtagurls)) {
                                   $resulttext .= '<li>'.&mt('custom markup file removed for [_1]',$domservers{$lonhost}).'</li>';
                               } elsif (ref($loginhash{'login'}{'headtag'}{$lonhost}) eq 'HASH') {
                                   $resulttext .= '<li><a href="'.
                                                  "javascript:void(open('$loginhash{'login'}{'headtag'}{$lonhost}{'url'}?inhibitmenu=yes','Custom_HeadTag',
                                                  'menubar=0,toolbar=1,scrollbars=1,width=600,height=500,resizable=yes'))".
                                                  '">'.&mt('custom markup').'</a> '.&mt('(for [_1])',$servers{$lonhost}).' ';
                                   if ($possexempt{$lonhost}) {
                                       $resulttext .= &mt('not included for client IP(s): [_1]',$possexempt{$lonhost});
                                   } else {
                                       $resulttext .= &mt('included for any client IP');
                                   }
                                   $resulttext .= '</li>';
                               }
                           }
                       }
                 } elsif ($item eq 'captcha') {                  } elsif ($item eq 'captcha') {
                     if (ref($loginhash{'login'}) eq 'HASH') {                      if (ref($loginhash{'login'}) eq 'HASH') {
                         my $chgtxt;                          my $chgtxt;
Line 6005  sub modify_login { Line 7933  sub modify_login {
                         if (!$privkey) {                          if (!$privkey) {
                             $chgtxt .= '<li>'.&mt('Private key deleted').'</li>';                              $chgtxt .= '<li>'.&mt('Private key deleted').'</li>';
                         } else {                          } else {
                             $chgtxt .= '<li>'.&mt('Private key set to [_1]',$pubkey).'</li>';                              $chgtxt .= '<li>'.&mt('Private key set to [_1]',$privkey).'</li>';
                         }                          }
                         $chgtxt .= '</ul>';                          $chgtxt .= '</ul>';
                         $resulttext .= '<li>'.$chgtxt.'</li>';                          $resulttext .= '<li>'.$chgtxt.'</li>';
                     }                      }
                   } elsif ($item eq 'recaptchaversion') {
                       if (ref($loginhash{'login'}) eq 'HASH') {
                           if ($loginhash{'login'}{'captcha'} eq 'recaptcha') {
                               $resulttext .= '<li>'.&mt('ReCAPTCHA for helpdesk form set to version [_1]',$loginhash{'login'}{'recaptchaversion'}).
                                              '</li>';
                           }
                       }
                 } else {                  } else {
                     $resulttext .= '<li>'.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'</li>';                      $resulttext .= '<li>'.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'</li>';
                 }                  }
Line 6029  sub modify_login { Line 7964  sub modify_login {
     return $resulttext;      return $resulttext;
 }  }
   
   sub check_exempt_addresses {
       my ($iplist) = @_;
       $iplist =~ s/^\s+//;
       $iplist =~ s/\s+$//;
       my @poss_ips = split(/\s*[,:]\s*/,$iplist);
       my (@okips,$new);
       foreach my $ip (@poss_ips) {
           if ($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
               if (($1 <= 255) && ($2 <= 255) && ($3 <= 255) && ($4 <= 255)) {
                   push(@okips,$ip);
               }
           }
       }
       if (@okips > 0) {
           $new = join(',',@okips);
       } else {
           $new = '';
       }
       return $new;
   }
   
 sub color_font_choices {  sub color_font_choices {
     my %choices =      my %choices =
         &Apache::lonlocal::texthash (          &Apache::lonlocal::texthash (
Line 6480  sub check_authorstatus { Line 8436  sub check_authorstatus {
   
 sub publishlogo {  sub publishlogo {
     my ($r,$action,$formname,$dom,$confname,$subdir,$thumbwidth,$thumbheight,$savefileas) = @_;      my ($r,$action,$formname,$dom,$confname,$subdir,$thumbwidth,$thumbheight,$savefileas) = @_;
     my ($output,$fname,$logourl);      my ($output,$fname,$logourl,$madethumb);
     if ($action eq 'upload') {      if ($action eq 'upload') {
         $fname=$env{'form.'.$formname.'.filename'};          $fname=$env{'form.'.$formname.'.filename'};
         chop($env{'form.'.$formname});          chop($env{'form.'.$formname});
Line 6608  $env{'user.name'}.':'.$env{'user.domain' Line 8564  $env{'user.name'}.':'.$env{'user.domain'
                                     $r->set_handlers('PerlCleanupHandler' => [\&notifysubscribed,@{$handlers}]);                                      $r->set_handlers('PerlCleanupHandler' => [\&notifysubscribed,@{$handlers}]);
                                     $registered_cleanup=1;                                      $registered_cleanup=1;
                                 }                                  }
                                   $madethumb = 1;
                             } else {                              } else {
                                 print $logfile "\nUnable to write ".$copyfile.                                  print $logfile "\nUnable to write ".$copyfile.
                                                ':'.$!."\n";                                                 ':'.$!."\n";
Line 6620  $env{'user.name'}.':'.$env{'user.domain' Line 8577  $env{'user.name'}.':'.$env{'user.domain'
             $output = $versionresult;              $output = $versionresult;
         }          }
     }      }
     return ($output,$logourl);      return ($output,$logourl,$madethumb);
 }  }
   
 sub logo_versioning {  sub logo_versioning {
Line 6774  sub modify_quotas { Line 8731  sub modify_quotas {
         $context = $action;          $context = $action;
     }      }
     if ($context eq 'requestcourses') {      if ($context eq 'requestcourses') {
         @usertools = ('official','unofficial','community','textbook');          @usertools = ('official','unofficial','community','textbook','placement');
         @options =('norequest','approval','validate','autolimit');          @options =('norequest','approval','validate','autolimit');
         %validations = &Apache::lonnet::auto_courserequest_checks($dom);          %validations = &Apache::lonnet::auto_courserequest_checks($dom);
         %titles = &courserequest_titles();          %titles = &courserequest_titles();
Line 6823  sub modify_quotas { Line 8780  sub modify_quotas {
         my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval');          my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval');
         @approvalnotify = sort(@approvalnotify);          @approvalnotify = sort(@approvalnotify);
         $confhash{'notify'}{'approval'} = join(',',@approvalnotify);          $confhash{'notify'}{'approval'} = join(',',@approvalnotify);
         my @crstypes = ('official','unofficial','community','textbook');          my @crstypes = ('official','unofficial','community','textbook','placement');
         my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');          my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');
         foreach my $type (@hasuniquecode) {          foreach my $type (@hasuniquecode) {
             if (grep(/^\Q$type\E$/,@crstypes)) {              if (grep(/^\Q$type\E$/,@crstypes)) {
                 $confhash{'uniquecode'}{$type} = 1;                  $confhash{'uniquecode'}{$type} = 1;
             }              }
         }          }
         my ($newbook,@allpos);          my (%newbook,%allpos);
         if ($context eq 'requestcourses') {          if ($context eq 'requestcourses') {
             if ($env{'form.addbook'}) {              foreach my $type ('textbooks','templates') {
                 if (($env{'form.addbook_cnum'} =~ /^$match_courseid$/) &&                  @{$allpos{$type}} = (); 
                     ($env{'form.addbook_cdom'} =~ /^$match_domain$/)) {                  my $invalid;
                     if (&Apache::lonnet::homeserver($env{'form.addbook_cnum'},                  if ($type eq 'textbooks') {
                                                     $env{'form.addbook_cdom'}) eq 'no_host') {                      $invalid = &mt('Invalid LON-CAPA course for textbook');
                         $errors .= '<li><span class="LC_error">'.&mt('Invalid LON-CAPA course for textbook').                  } else {
                                    '</span></li>';                      $invalid = &mt('Invalid LON-CAPA course for template');
                     } else {                  }
                         $newbook = $env{'form.addbook_cdom'}.'_'.$env{'form.addbook_cnum'};                  if ($env{'form.'.$type.'_addbook'}) {
                         my $position = $env{'form.addbook_pos'};                      if (($env{'form.'.$type.'_addbook_cnum'} =~ /^$match_courseid$/) &&
                         $position =~ s/\D+//g;                          ($env{'form.'.$type.'_addbook_cdom'} =~ /^$match_domain$/)) {
                         if ($position ne '') {                          if (&Apache::lonnet::homeserver($env{'form.'.$type.'_addbook_cnum'},
                             $allpos[$position] = $newbook;                                                          $env{'form.'.$type.'_addbook_cdom'}) eq 'no_host') {
                               $errors .= '<li><span class="LC_error">'.$invalid.'</span></li>';
                           } else {
                               $newbook{$type} = $env{'form.'.$type.'_addbook_cdom'}.'_'.$env{'form.'.$type.'_addbook_cnum'};
                               my $position = $env{'form.'.$type.'_addbook_pos'};
                               $position =~ s/\D+//g;
                               if ($position ne '') {
                                   $allpos{$type}[$position] = $newbook{$type};
                               }
                         }                          }
                       } else {
                           $errors .= '<li><span class="LC_error">'.$invalid.'</span></li>';
                     }                      }
                 } else {  
                     $errors .= '<li><span class="LC_error">'.&mt('Invalid LON-CAPA course for textbook').  
                                '</span></li>';  
                 }                  }
             }              } 
   
         }          }
         if (ref($domconfig{$action}) eq 'HASH') {          if (ref($domconfig{$action}) eq 'HASH') {
             if (ref($domconfig{$action}{'notify'}) eq 'HASH') {              if (ref($domconfig{$action}{'notify'}) eq 'HASH') {
Line 6885  sub modify_quotas { Line 8848  sub modify_quotas {
                 $changes{'uniquecode'} = 1;                  $changes{'uniquecode'} = 1;
             }              }
             if ($context eq 'requestcourses') {              if ($context eq 'requestcourses') {
                 if (ref($domconfig{$action}{'textbooks'}) eq 'HASH') {                  foreach my $type ('textbooks','templates') {
                     my %deletions;                      if (ref($domconfig{$action}{$type}) eq 'HASH') {
                     my @todelete = &Apache::loncommon::get_env_multiple('form.book_del');                          my %deletions;
                     if (@todelete) {                          my @todelete = &Apache::loncommon::get_env_multiple('form.'.$type.'_del');
                         map { $deletions{$_} = 1; } @todelete;                          if (@todelete) {
                     }                              map { $deletions{$_} = 1; } @todelete;
                     my %imgdeletions;                          }
                     my @todeleteimages = &Apache::loncommon::get_env_multiple('form.book_image_del');                          my %imgdeletions;
                     if (@todeleteimages) {                          my @todeleteimages = &Apache::loncommon::get_env_multiple('form.'.$type.'_image_del');
                         map { $imgdeletions{$_} = 1; } @todeleteimages;                          if (@todeleteimages) {
                     }                              map { $imgdeletions{$_} = 1; } @todeleteimages;
                     my $maxnum = $env{'form.book_maxnum'};                          }
                     for (my $i=0; $i<=$maxnum; $i++) {                          my $maxnum = $env{'form.'.$type.'_maxnum'};
                         my $key = $env{'form.book_id_'.$i};                          for (my $i=0; $i<=$maxnum; $i++) {
                         if (ref($domconfig{$action}{'textbooks'}{$key}) eq 'HASH') {                              my $itemid = $env{'form.'.$type.'_id_'.$i};
                             if ($deletions{$key}) {                              my ($key) = ($itemid =~ /^\Q$type\E_(\w+)$/); 
                                 if ($domconfig{$action}{'textbooks'}{$key}{'image'}) {                              if (ref($domconfig{$action}{$type}{$key}) eq 'HASH') {
                                   if ($deletions{$key}) {
                                       if ($domconfig{$action}{$type}{$key}{'image'}) {
                                           #FIXME need to obsolete item in RES space
                                       }
                                       next;
                                   } else {
                                       my $newpos = $env{'form.'.$itemid};
                                       $newpos =~ s/\D+//g;
                                       foreach my $item ('subject','title','publisher','author') {
                                           next if ((($item eq 'author') || ($item eq 'publisher')) &&
                                                    ($type eq 'templates'));
                                           $confhash{$type}{$key}{$item} = $env{'form.'.$type.'_'.$item.'_'.$i};
                                           if ($domconfig{$action}{$type}{$key}{$item} ne $confhash{$type}{$key}{$item}) {
                                               $changes{$type}{$key} = 1;
                                           }
                                       }
                                       $allpos{$type}[$newpos] = $key;
                                   }
                                   if ($imgdeletions{$key}) {
                                       $changes{$type}{$key} = 1;
                                     #FIXME need to obsolete item in RES space                                      #FIXME need to obsolete item in RES space
                                   } elsif ($env{'form.'.$type.'_image_'.$i.'.filename'}) {
                                       my ($cdom,$cnum) = split(/_/,$key);
                                       my ($imgurl,$error) = &process_textbook_image($r,$dom,$confname,$type.'_image_'.$i,
                                                                                     $cdom,$cnum,$type,$configuserok,
                                                                                     $switchserver,$author_ok);
                                       if ($imgurl) {
                                           $confhash{$type}{$key}{'image'} = $imgurl;
                                           $changes{$type}{$key} = 1; 
                                       }
                                       if ($error) {
                                           &Apache::lonnet::logthis($error);
                                           $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                                       } 
                                   } elsif ($domconfig{$action}{$type}{$key}{'image'}) {
                                       $confhash{$type}{$key}{'image'} = 
                                           $domconfig{$action}{$type}{$key}{'image'};
                                 }                                  }
                                 next;  
                             } else {  
                                 my $newpos = $env{'form.'.$key};  
                                 $newpos =~ s/\D+//g;  
                                 foreach my $item ('subject','title','author') {  
                                     $confhash{'textbooks'}{$key}{$item} = $env{'form.book_'.$item.'_'.$i};  
                                     if ($domconfig{$action}{'textbooks'}{$key}{$item} ne $confhash{'textbooks'}{$key}{$item}) {  
                                         $changes{'textbooks'}{$key} = 1;  
                                     }  
                                 }  
                                 $allpos[$newpos] = $key;  
                             }  
                             if ($imgdeletions{$key}) {  
                                 $changes{'textbooks'}{$key} = 1;  
                                 #FIXME need to obsolete item in RES space  
                             } elsif ($env{'form.book_image_'.$i.'.filename'}) {  
                                 my ($cdom,$cnum) = split(/_/,$key);  
                                 my ($imgurl,$error) = &process_textbook_image($r,$dom,$confname,'book_image_'.$i,  
                                                                               $cdom,$cnum,$configuserok,  
                                                                               $switchserver,$author_ok);  
                                 if ($imgurl) {  
                                     $confhash{'textbooks'}{$key}{'image'} = $imgurl;  
                                     $changes{'textbooks'}{$key} = 1;   
                                 }  
                                 if ($error) {  
                                     &Apache::lonnet::logthis($error);  
                                     $errors .= '<li><span class="LC_error">'.$error.'</span></li>';  
                                 }   
                             } elsif ($domconfig{$action}{'textbooks'}{$key}{'image'}) {  
                                 $confhash{'textbooks'}{$key}{'image'} =   
                                     $domconfig{$action}{'textbooks'}{$key}{'image'};  
                             }                              }
                         }                          }
                     }                      }
Line 6949  sub modify_quotas { Line 8917  sub modify_quotas {
             }              }
         }          }
         if ($context eq 'requestcourses') {          if ($context eq 'requestcourses') {
             if ($newbook) {              foreach my $type ('textbooks','templates') {
                 $changes{'textbooks'}{$newbook} = 1;                  if ($newbook{$type}) {
                 foreach my $item ('subject','title','author') {                      $changes{$type}{$newbook{$type}} = 1;
                     $env{'form.addbook_'.$item} =~ s/(`)/'/g;                      foreach my $item ('subject','title','publisher','author') {
                     if ($env{'form.addbook_'.$item}) {                          next if ((($item eq 'author') || ($item eq 'publisher')) &&
                         $confhash{'textbooks'}{$newbook}{$item} = $env{'form.addbook_'.$item};                                   ($type eq 'template'));
                     }                          $env{'form.'.$type.'_addbook_'.$item} =~ s/(`)/'/g;
                 }                          if ($env{'form.'.$type.'_addbook_'.$item}) {
                 if ($env{'form.addbook_image.filename'} ne '') {                              $confhash{$type}{$newbook{$type}}{$item} = $env{'form.'.$type.'_addbook_'.$item};
                     my ($cdom,$cnum) = split(/_/,$newbook);                          }
                     my ($imageurl,$error) =                      }
                         &process_textbook_image($r,$dom,$confname,'addbook_image',$cdom,$cnum,$configuserok,                      if ($type eq 'textbooks') {
                                                 $switchserver,$author_ok);                          if ($env{'form.'.$type.'_addbook_image.filename'} ne '') {
                     if ($imageurl) {                              my ($cdom,$cnum) = split(/_/,$newbook{$type});
                         $confhash{'textbooks'}{$newbook}{'image'} = $imageurl;                              my ($imageurl,$error) =
                     }                                  &process_textbook_image($r,$dom,$confname,$type.'_addbook_image',$cdom,$cnum,$type,
                     if ($error) {                                                          $configuserok,$switchserver,$author_ok);
                         &Apache::lonnet::logthis($error);                              if ($imageurl) {
                         $errors .= '<li><span class="LC_error">'.$error.'</span></li>';                                  $confhash{$type}{$newbook{$type}}{'image'} = $imageurl;
                               }
                               if ($error) {
                                   &Apache::lonnet::logthis($error);
                                   $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                               }
                           }
                     }                      }
                 }                  }
             }                  if (@{$allpos{$type}} > 0) {
             if (@allpos > 0) {                      my $idx = 0;
                 my $idx = 0;                      foreach my $item (@{$allpos{$type}}) {
                 foreach my $item (@allpos) {                          if ($item ne '') {
                     if ($item ne '') {                              $confhash{$type}{$item}{'order'} = $idx;
                         $confhash{'textbooks'}{$item}{'order'} = $idx;                              if (ref($domconfig{$action}) eq 'HASH') {
                         if (ref($domconfig{$action}) eq 'HASH') {                                  if (ref($domconfig{$action}{$type}) eq 'HASH') {
                             if (ref($domconfig{$action}{'textbooks'}) eq 'HASH') {                                      if (ref($domconfig{$action}{$type}{$item}) eq 'HASH') {
                                 if (ref($domconfig{$action}{'textbooks'}{$item}) eq 'HASH') {                                          if ($domconfig{$action}{$type}{$item}{'order'} ne $idx) {
                                     if ($domconfig{$action}{'textbooks'}{$item}{'order'} ne $idx) {                                              $changes{$type}{$item} = 1;
                                         $changes{'textbooks'}{$item} = 1;                                          }
                                     }                                      }
                                 }                                  }
                             }                              }
                               $idx ++;
                         }                          }
                         $idx ++;  
                     }                      }
                 }                  }
             }              }
Line 6997  sub modify_quotas { Line 8971  sub modify_quotas {
                         if (@{$confhash{'validation'}{$item}} > 0) {                          if (@{$confhash{'validation'}{$item}} > 0) {
                             @{$confhash{'validation'}{$item}} = sort(@{$confhash{'validation'}{$item}});                              @{$confhash{'validation'}{$item}} = sort(@{$confhash{'validation'}{$item}});
                         }                          }
                         if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {                          if (ref($domconfig{'requestcourses'}) eq 'HASH') {
                             if (ref($domconfig{'requestcourses'}{'validation'}{$item}) eq 'ARRAY') {                              if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
                                 @changed = &Apache::loncommon::compare_arrays($confhash{'validation'}{$item},                                  if (ref($domconfig{'requestcourses'}{'validation'}{$item}) eq 'ARRAY') {
                                                                               $domconfig{'requestcourses'}{'validation'}{$item});                                      @changed = &Apache::loncommon::compare_arrays($confhash{'validation'}{$item},
                                                                                     $domconfig{'requestcourses'}{'validation'}{$item});
                                   } else {
                                       @changed = @{$confhash{'validation'}{$item}};
                                   }
                             } else {                              } else {
                                 @changed = @{$confhash{'validation'}{$item}};                                  @changed = @{$confhash{'validation'}{$item}};
                             }                              }
Line 7021  sub modify_quotas { Line 8999  sub modify_quotas {
                                 $env{'form.requestcourses_validation_'.$item} =~ s/[\n\r\f]+/\s/gs;                                  $env{'form.requestcourses_validation_'.$item} =~ s/[\n\r\f]+/\s/gs;
                             }                              }
                         }                          }
                         if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {                          if (ref($domconfig{'requestcourses'}) eq 'HASH') {
                             if ($domconfig{'requestcourses'}{'validation'}{$item} ne $confhash{'validation'}{$item}) {                              if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
                                 $changes{'validation'}{$item} = $confhash{'validation'}{$item};                                  if ($domconfig{'requestcourses'}{'validation'}{$item} ne $confhash{'validation'}{$item}) {
                                       $changes{'validation'}{$item} = $confhash{'validation'}{$item};
                                   }
                               } else {
                                   if ($confhash{'validation'}{$item} ne '') {
                                       $changes{'validation'}{$item} = $confhash{'validation'}{$item};
                                   }
                             }                              }
                         } else {                          } else {
                             if ($confhash{'validation'}{$item} ne '') {                              if ($confhash{'validation'}{$item} ne '') {
Line 7035  sub modify_quotas { Line 9019  sub modify_quotas {
             }              }
             if ($env{'form.validationdc'}) {              if ($env{'form.validationdc'}) {
                 my $newval = $env{'form.validationdc'};                  my $newval = $env{'form.validationdc'};
                 my %domcoords = &get_active_dcs($dom);                  my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);
                 if (exists($domcoords{$newval})) {                  if (exists($domcoords{$newval})) {
                     $confhash{'validation'}{'dc'} = $newval;                      $confhash{'validation'}{'dc'} = $newval;
                 }                  }
             }              }
             if (ref($confhash{'validation'}) eq 'HASH') {              if (ref($confhash{'validation'}) eq 'HASH') {
                 if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {                  if (ref($domconfig{'requestcourses'}) eq 'HASH') {
                     if ($domconfig{'requestcourses'}{'validation'}{'dc'}) {                      if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
                         unless ($confhash{'validation'}{'dc'} eq $domconfig{'requestcourses'}{'validation'}{'dc'}) {                          if ($domconfig{'requestcourses'}{'validation'}{'dc'}) {
                             if ($confhash{'validation'}{'dc'} eq '') {                              unless ($confhash{'validation'}{'dc'} eq $domconfig{'requestcourses'}{'validation'}{'dc'}) {
                                 $changes{'validation'}{'dc'} = &mt('None');                                  if ($confhash{'validation'}{'dc'} eq '') {
                             } else {                                      $changes{'validation'}{'dc'} = &mt('None');
                                 $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};                                  } else {
                                       $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
                                   }
                             }                              }
                           } elsif ($confhash{'validation'}{'dc'} ne '') {
                               $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
                         }                          }
                     } elsif ($confhash{'validation'}{'dc'} ne '') {                      } elsif ($confhash{'validation'}{'dc'} ne '') {
                         $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};                          $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
Line 7056  sub modify_quotas { Line 9044  sub modify_quotas {
                 } elsif ($confhash{'validation'}{'dc'} ne '') {                  } elsif ($confhash{'validation'}{'dc'} ne '') {
                     $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};                      $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
                 }                  }
             } elsif (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {              } else {
                 if ($domconfig{'requestcourses'}{'validation'}{'dc'}) {                  if (ref($domconfig{'requestcourses'}) eq 'HASH') {
                     $changes{'validation'}{'dc'} = &mt('None');                      if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
                           if ($domconfig{'requestcourses'}{'validation'}{'dc'}) {
                               $changes{'validation'}{'dc'} = &mt('None');
                           }
                       }
                 }                  }
             }              }
         }          }
Line 7202  sub modify_quotas { Line 9194  sub modify_quotas {
         $domdefaults{'requestauthor'} = \%confhash;          $domdefaults{'requestauthor'} = \%confhash;
     } else {      } else {
         foreach my $key (keys(%confhash)) {          foreach my $key (keys(%confhash)) {
             unless (($context eq 'requestcourses') && ($key eq 'textbooks')) {              unless (($context eq 'requestcourses') && (($key eq 'textbooks') || ($key eq 'templates'))) {
                 $domdefaults{$key} = $confhash{$key};                  $domdefaults{$key} = $confhash{$key};
             }              }
         }          }
Line 7354  sub modify_quotas { Line 9346  sub modify_quotas {
                                        '</li>';                                         '</li>';
                     }                      }
                 }                  }
                 if (ref($changes{'textbooks'}) eq 'HASH') {                  foreach my $type ('textbooks','templates') {
                     $resulttext .= '<li>'.&mt('Available textbooks updated').'<ul>';                      if (ref($changes{$type}) eq 'HASH') {
                     foreach my $key (sort(keys(%{$changes{'textbooks'}}))) {                          $resulttext .= '<li>'.&mt("Available $type updated").'<ul>';
                         my %coursehash = &Apache::lonnet::coursedescription($key);                          foreach my $key (sort(keys(%{$changes{$type}}))) {
                         my $coursetitle = $coursehash{'description'};                              my %coursehash = &Apache::lonnet::coursedescription($key);
                         my $position = $confhash{'textbooks'}{$key}{'order'} + 1;                              my $coursetitle = $coursehash{'description'};
                         $resulttext .= '<li>';                              my $position = $confhash{$type}{$key}{'order'} + 1;
                         foreach my $item ('subject','title','author') {                              $resulttext .= '<li>';
                             my $name = $item.':';                              foreach my $item ('subject','title','publisher','author') {
                             $name =~ s/^(\w)/\U$1/;                                  next if ((($item eq 'author') || ($item eq 'publisher')) &&
                             $resulttext .= &mt($name).' '.$confhash{'textbooks'}{$key}{$item}.'<br />';                                           ($type eq 'templates'));
                         }                                  my $name = $item.':';
                         $resulttext .= ' '.&mt('Order: [_1]',$position).'<br />';                                  $name =~ s/^(\w)/\U$1/;
                         if ($confhash{'textbooks'}{$key}{'image'}) {                                  $resulttext .= &mt($name).' '.$confhash{$type}{$key}{$item}.'<br />';
                             $resulttext .= ' '.&mt('Image: [_1]',                              }
                                                '<img src="'.$confhash{'textbooks'}{$key}{'image'}.'"'.                              $resulttext .= ' '.&mt('Order: [_1]',$position).'<br />';
                                                ' alt="Textbook cover" />').'<br />';                              if ($type eq 'textbooks') {
                                   if ($confhash{$type}{$key}{'image'}) {
                                       $resulttext .= ' '.&mt('Image: [_1]',
                                                      '<img src="'.$confhash{$type}{$key}{'image'}.'"'.
                                                      ' alt="Textbook cover" />').'<br />';
                                   }
                               }
                               $resulttext .= ' '.&mt('LON-CAPA Course: [_1]',$coursetitle).'</li>';
                         }                          }
                         $resulttext .= ' '.&mt('LON-CAPA Course: [_1]',$coursetitle).'</li>';                          $resulttext .= '</ul></li>';
                     }                      }
                     $resulttext .= '</ul></li>';  
                 }                  }
                 if (ref($changes{'validation'}) eq 'HASH') {                  if (ref($changes{'validation'}) eq 'HASH') {
                     if ((ref($validationitemsref) eq 'ARRAY') && (ref($validationnamesref) eq 'HASH')) {                      if ((ref($validationitemsref) eq 'ARRAY') && (ref($validationnamesref) eq 'HASH')) {
Line 7422  sub modify_quotas { Line 9420  sub modify_quotas {
 }  }
   
 sub process_textbook_image {  sub process_textbook_image {
     my ($r,$dom,$confname,$caller,$cdom,$cnum,$configuserok,$switchserver,$author_ok) = @_;      my ($r,$dom,$confname,$caller,$cdom,$cnum,$type,$configuserok,$switchserver,$author_ok) = @_;
     my $filename = $env{'form.'.$caller.'.filename'};      my $filename = $env{'form.'.$caller.'.filename'};
     my ($error,$url);      my ($error,$url);
     my ($width,$height) = (50,50);      my ($width,$height) = (50,50);
Line 7433  sub process_textbook_image { Line 9431  sub process_textbook_image {
         } elsif ($author_ok eq 'ok') {          } elsif ($author_ok eq 'ok') {
             my ($result,$imageurl) =              my ($result,$imageurl) =
                 &publishlogo($r,'upload',$caller,$dom,$confname,                  &publishlogo($r,'upload',$caller,$dom,$confname,
                              "textbooks/$dom/$cnum/cover",$width,$height);                               "$type/$dom/$cnum/cover",$width,$height);
             if ($result eq 'ok') {              if ($result eq 'ok') {
                 $url = $imageurl;                  $url = $imageurl;
             } else {              } else {
Line 7448  sub process_textbook_image { Line 9446  sub process_textbook_image {
     return ($url,$error);      return ($url,$error);
 }  }
   
   sub modify_ltitools {
       my ($r,$dom,$action,$lastactref,%domconfig) = @_;
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
       my ($newid,@allpos,%changes,%confhash,$errors,$resulttext);
       my $confname = $dom.'-domainconfig';
       my $servadm = $r->dir_config('lonAdmEMail');
       my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
       my (%posslti,%possfield);
       my @courseroles = ('cc','in','ta','ep','st');
       my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner);
       map { $posslti{$_} = 1; } @ltiroles;
       my @allfields = ('fullname','firstname','lastname','email','user','roles');
       map { $possfield{$_} = 1; } @allfields;
       my %lt = &ltitools_names(); 
       if ($env{'form.ltitools_add'}) {
           my $title = $env{'form.ltitools_add_title'};
           $title =~ s/(`)/'/g;
           ($newid,my $error) = &get_ltitools_id($dom,$title);
           if ($newid) {
               my $position = $env{'form.ltitools_add_pos'};
               $position =~ s/\D+//g;
               if ($position ne '') {
                   $allpos[$position] = $newid;
               }
               $changes{$newid} = 1;
               foreach my $item ('title','url','key','secret') {
                   $env{'form.ltitools_add_'.$item} =~ s/(`)/'/g;
                   if ($env{'form.ltitools_add_'.$item}) {
                       $confhash{$newid}{$item} = $env{'form.ltitools_add_'.$item};
                   }
               }
               if ($env{'form.ltitools_add_version'} eq 'LTI-1p0') {
                   $confhash{$newid}{'version'} = $env{'form.ltitools_add_version'};
               }
               if ($env{'form.ltitools_add_msgtype'} eq 'basic-lti-launch-request') {
                   $confhash{$newid}{'msgtype'} = $env{'form.ltitools_add_msgtype'};
               }
               foreach my $item ('width','height') {
                   $env{'form.ltitools_add_'.$item} =~ s/^\s+//;
                   $env{'form.ltitools_add_'.$item} =~ s/\s+$//;
                   if ($env{'form.ltitools_add_'.$item} =~ /^\d+$/) {
                       $confhash{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item};
                   }
               }
               if ($env{'form.ltitools_add_target'} eq 'window') {
                   $confhash{$newid}{'display'}{'target'} = $env{'form.ltitools_add_target'};
               } else {
                   $confhash{$newid}{'display'}{'target'} = 'iframe';
               }
               foreach my $item ('passback','roster') {
                   if ($env{'form.ltitools_add_'.$item}) {
                       $confhash{$newid}{$item} = 1;
                   }
               }
               if ($env{'form.ltitools_add_image.filename'} ne '') {
                   my ($imageurl,$error) =
                       &process_ltitools_image($r,$dom,$confname,'ltitools_add_image',$dom,
                                               $configuserok,$switchserver,$author_ok);
                   if ($imageurl) {
                       $confhash{$newid}{'image'} = $imageurl;
                   }
                   if ($error) {
                       &Apache::lonnet::logthis($error);
                       $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                   }
               }
               my @fields = &Apache::loncommon::get_env_multiple('form.ltitools_add_fields');
               foreach my $field (@fields) {
                   if ($possfield{$field}) {
                       if ($field eq 'roles') {
                           foreach my $role (@courseroles) {
                               my $choice = $env{'form.ltitools_add_roles_'.$role};
                               if (($choice ne '') && ($posslti{$choice})) {
                                   $confhash{$newid}{'roles'}{$role} = $choice;
                                   if ($role eq 'cc') {
                                       $confhash{$newid}{'roles'}{'co'} = $choice; 
                                   }
                               }
                           }
                       } else {
                           $confhash{$newid}{'fields'}{$field} = 1;
                       }
                   }
               }
               my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig');
               foreach my $item (@courseconfig) {
                   $confhash{$newid}{'crsconf'}{$item} = 1;
               }
               if ($env{'form.ltitools_add_custom'}) {
                   my $name = $env{'form.ltitools_add_custom_name'};
                   my $value = $env{'form.ltitools_add_custom_value'};
                   $value =~ s/(`)/'/g;
                   $name =~ s/(`)/'/g;
                   $confhash{$newid}{'custom'}{$name} = $value;
               }
           } else {
               my $error = &mt('Failed to acquire unique ID for new external tool');   
               $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
           }
       }
       if (ref($domconfig{$action}) eq 'HASH') {
           my %deletions;
           my @todelete = &Apache::loncommon::get_env_multiple('form.ltitools_del');
           if (@todelete) {
               map { $deletions{$_} = 1; } @todelete;
           }
           my %customadds;
           my @newcustom = &Apache::loncommon::get_env_multiple('form.ltitools_customadd');
           if (@newcustom) {
               map { $customadds{$_} = 1; } @newcustom;
           } 
           my %imgdeletions;
           my @todeleteimages = &Apache::loncommon::get_env_multiple('form.ltitools_image_del');
           if (@todeleteimages) {
               map { $imgdeletions{$_} = 1; } @todeleteimages;
           }
           my $maxnum = $env{'form.ltitools_maxnum'};
           for (my $i=0; $i<=$maxnum; $i++) {
               my $itemid = $env{'form.ltitools_id_'.$i};
               if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
                   if ($deletions{$itemid}) {
                       if ($domconfig{$action}{$itemid}{'image'}) {
                           #FIXME need to obsolete item in RES space
                       }
                       $changes{$itemid} = $domconfig{$action}{$itemid}{'title'};
                       next;
                   } else {
                       my $newpos = $env{'form.ltitools_'.$itemid};
                       $newpos =~ s/\D+//g;
                       foreach my $item ('title','url','key','secret') {
                           $confhash{$itemid}{$item} = $env{'form.ltitools_'.$item.'_'.$i};
                           if ($domconfig{$action}{$itemid}{$item} ne $confhash{$itemid}{$item}) {
                               $changes{$itemid} = 1;
                           }
                       }
                       if ($env{'form.ltitools_version_'.$i} eq 'LTI-1p0') {
                           $confhash{$itemid}{'version'} = $env{'form.ltitools_version_'.$i};
                       }
                       if ($env{'form.ltitools_msgtype_'.$i} eq 'basic-lti-launch-request') {
                           $confhash{$itemid}{'msgtype'} = $env{'form.ltitools_msgtype_'.$i};
                       }
                       foreach my $size ('width','height') {
                           $env{'form.ltitools_'.$size.'_'.$i} =~ s/^\s+//;
                           $env{'form.ltitools_'.$size.'_'.$i} =~ s/\s+$//;
                           if ($env{'form.ltitools_'.$size.'_'.$i} =~ /^\d+$/) {
                               $confhash{$itemid}{'display'}{$size} = $env{'form.ltitools_'.$size.'_'.$i};
                               if (ref($domconfig{$action}{$itemid}{'display'}) eq 'HASH') {
                                   if ($domconfig{$action}{$itemid}{'display'}{$size} ne $confhash{$itemid}{'display'}{$size}) {
                                       $changes{$itemid} = 1;
                                   }
                               } else {
                                   $changes{$itemid} = 1;
                               }
                           }
                       }
                       if ($env{'form.ltitools_target_'.$i} eq 'window') {
                           $confhash{$itemid}{'display'}{'target'} = $env{'form.ltitools_target_'.$i};
                       } else {
                           $confhash{$itemid}{'display'}{'target'} = 'iframe';
                       }
                       if (ref($domconfig{$action}{$itemid}{'display'}) eq 'HASH') {
                           if ($domconfig{$action}{$itemid}{'display'}{'target'} ne $confhash{$itemid}{'display'}{'target'}) {
                               $changes{$itemid} = 1;
                           }
                       } else {
                           $changes{$itemid} = 1;
                       }
                       foreach my $extra ('passback','roster') {
                           if ($env{'form.ltitools_'.$extra.'_'.$i}) {
                               $confhash{$itemid}{$extra} = 1;
                           }
                           if ($domconfig{$action}{$itemid}{$extra} ne $confhash{$itemid}{$extra}) {
                               $changes{$itemid} = 1;
                           }
                       }
                       my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig_'.$i);
                       foreach my $item ('label','title','target') {
                           if (grep(/^\Q$item\E$/,@courseconfig)) {
                               $confhash{$itemid}{'crsconf'}{$item} = 1;
                               if (ref($domconfig{$action}{$itemid}{'crsconf'}) eq 'HASH') {
                                   if ($domconfig{$action}{$itemid}{'crsconf'}{$item} ne $confhash{$itemid}{'crsconf'}{$item}) {
                                       $changes{$itemid} = 1;
                                   }
                               } else {
                                   $changes{$itemid} = 1;
                               }
                           }
                       }
                       my @fields = &Apache::loncommon::get_env_multiple('form.ltitools_fields_'.$i);
                       foreach my $field (@fields) {
                           if ($possfield{$field}) {
                               if ($field eq 'roles') {
                                   foreach my $role (@courseroles) {
                                       my $choice = $env{'form.ltitools_roles_'.$role.'_'.$i};
                                       if (($choice ne '') && ($posslti{$choice})) {
                                           $confhash{$itemid}{'roles'}{$role} = $choice;
                                           if ($role eq 'cc') {
                                               $confhash{$itemid}{'roles'}{'co'} = $choice;
                                           }
                                       }
                                       if (ref($domconfig{$action}{$itemid}{'roles'}) eq 'HASH') {
                                           if ($domconfig{$action}{$itemid}{'roles'}{$role} ne $confhash{$itemid}{'roles'}{$role}) {
                                               $changes{$itemid} = 1;
                                           }
                                       } elsif ($confhash{$itemid}{'roles'}{$role}) {
                                           $changes{$itemid} = 1;
                                       }
                                   }
                               } else {
                                   $confhash{$itemid}{'fields'}{$field} = 1;
                                   if (ref($domconfig{$action}{$itemid}{'fields'}) eq 'HASH') {
                                       if ($domconfig{$action}{$itemid}{'fields'}{$field} ne $confhash{$itemid}{'fields'}{$field}) {
                                           $changes{$itemid} = 1;
                                       }
                                   } else {
                                       $changes{$itemid} = 1;
                                   }
                               }
                           }
                       }
                       $allpos[$newpos] = $itemid;
                   }
                   if ($imgdeletions{$itemid}) {
                       $changes{$itemid} = 1;
                       #FIXME need to obsolete item in RES space
                   } elsif ($env{'form.ltitools_image_'.$i.'.filename'}) {
                       my ($imgurl,$error) = &process_ltitools_image($r,$dom,$confname,'ltitools_image_'.$i,
                                                                    $itemid,$configuserok,$switchserver,
                                                                    $author_ok);
                       if ($imgurl) {
                           $confhash{$itemid}{'image'} = $imgurl;
                           $changes{$itemid} = 1;
                       }
                       if ($error) {
                           &Apache::lonnet::logthis($error);
                           $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                       }
                   } elsif ($domconfig{$action}{$itemid}{'image'}) {
                       $confhash{$itemid}{'image'} =
                          $domconfig{$action}{$itemid}{'image'};
                   }
                   if ($customadds{$i}) {
                       my $name = $env{'form.ltitools_custom_name_'.$i};
                       $name =~ s/(`)/'/g;
                       $name =~ s/^\s+//;
                       $name =~ s/\s+$//;
                       my $value = $env{'form.ltitools_custom_value_'.$i};
                       $value =~ s/(`)/'/g;
                       $value =~ s/^\s+//;
                       $value =~ s/\s+$//;
                       if ($name ne '') {
                           $confhash{$itemid}{'custom'}{$name} = $value;
                           $changes{$itemid} = 1;
                       }
                   }
                   my %customdels;
                   my @customdeletions = &Apache::loncommon::get_env_multiple('form.ltitools_customdel_'.$i); 
                   if (@customdeletions) {
                       $changes{$itemid} = 1;
                   }
                   map { $customdels{$_} = 1; } @customdeletions;
                   if (ref($domconfig{$action}{$itemid}{'custom'}) eq 'HASH') {
                       foreach my $key (keys(%{$domconfig{$action}{$itemid}{'custom'}})) {
                           unless ($customdels{$key}) {
                               if ($env{'form.ltitools_customval_'.$key.'_'.$i} ne '') {
                                   $confhash{$itemid}{'custom'}{$key} = $env{'form.ltitools_customval_'.$key.'_'.$i}; 
                               }
                               if ($domconfig{$action}{$itemid}{'custom'}{$key} ne $env{'form.ltitools_customval_'.$key.'_'.$i}) {
                                   $changes{$itemid} = 1;
                               }
                           }
                       }
                   }
                   unless ($changes{$itemid}) {
                       foreach my $key (keys(%{$domconfig{$action}{$itemid}})) {
                           if (ref($domconfig{$action}{$itemid}{$key}) eq 'HASH') {
                               if (ref($confhash{$itemid}{$key}) eq 'HASH') {
                                   foreach my $innerkey (keys(%{$domconfig{$action}{$itemid}{$key}})) {
                                       unless (exists($confhash{$itemid}{$key}{$innerkey})) {
                                           $changes{$itemid} = 1;
                                           last;
                                       }
                                   }
                               } elsif (keys(%{$domconfig{$action}{$itemid}{$key}}) > 0) {
                                   $changes{$itemid} = 1;
                               }
                           }
                           last if ($changes{$itemid});
                       }
                   }
               }
           }
       }
       if (@allpos > 0) {
           my $idx = 0;
           foreach my $itemid (@allpos) {
               if ($itemid ne '') {
                   $confhash{$itemid}{'order'} = $idx;
                   if (ref($domconfig{$action}) eq 'HASH') {
                       if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
                           if ($domconfig{$action}{$itemid}{'order'} ne $idx) {
                               $changes{$itemid} = 1;
                           }
                       }
                   }
                   $idx ++;
               }
           }
       }
       my %ltitoolshash = (
                             $action => { %confhash }
                          );
       my $putresult = &Apache::lonnet::put_dom('configuration',\%ltitoolshash,
                                                $dom);
       if ($putresult eq 'ok') {
           if (keys(%changes) > 0) {
               my $cachetime = 24*60*60;
               &Apache::lonnet::do_cache_new('ltitools',$dom,\%confhash,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'ltitools'} = 1;
               }
               $resulttext = &mt('Changes made:').'<ul>';
               my %bynum;
               foreach my $itemid (sort(keys(%changes))) {
                   my $position = $confhash{$itemid}{'order'};
                   $bynum{$position} = $itemid;
               }
               foreach my $pos (sort { $a <=> $b } keys(%bynum)) {
                   my $itemid = $bynum{$pos}; 
                   if (ref($confhash{$itemid}) ne 'HASH') {
                       $resulttext .= '<li>'.&mt('Deleted: [_1]',$changes{$itemid}).'</li>';
                   } else {
                       $resulttext .= '<li><b>'.$confhash{$itemid}{'title'}.'</b>';
                       if ($confhash{$itemid}{'image'}) {
                           $resulttext .= '&nbsp;'.
                                          '<img src="'.$confhash{$itemid}{'image'}.'"'.
                                          ' alt="'.&mt('Tool Provider icon').'" />';
                       }
                       $resulttext .= '</li><ul>';
                       my $position = $pos + 1;
                       $resulttext .= '<li>'.&mt('Order: [_1]',$position).'</li>';
                       foreach my $item ('version','msgtype','url','key') {
                           if ($confhash{$itemid}{$item} ne '') {
                               $resulttext .= '<li>'.$lt{$item}.':&nbsp;'.$confhash{$itemid}{$item}.'</li>';
                           }
                       }
                       if ($confhash{$itemid}{'secret'} ne '') {
                           $resulttext .= '<li>'.$lt{'secret'}.':&nbsp;';
                           my $num = length($confhash{$itemid}{'secret'});
                           $resulttext .= ('*'x$num).'</li>';
                       }
                       $resulttext .= '<li>'.&mt('Configurable in course:');
                       my @possconfig = ('label','title','target');
                       my $numconfig = 0; 
                       if (ref($confhash{$itemid}{'crsconf'}) eq 'HASH') { 
                           foreach my $item (@possconfig) {
                               if ($confhash{$itemid}{'crsconf'}{$item}) {
                                   $numconfig ++;
                                   $resulttext .= ' '.$lt{'crs'.$item};
                               }
                           }
                       }
                       if (!$numconfig) {
                           $resulttext .= &mt('None');
                       }
                       $resulttext .= '</li>';
                       foreach my $item ('passback','roster') {
                           $resulttext .= '<li>'.$lt{$item}.'&nbsp;';
                           if ($confhash{$itemid}{$item}) {
                               $resulttext .= &mt('Yes');
                           } else {
                               $resulttext .= &mt('No');
                           }
                           $resulttext .= '</li>';
                       }
                       if (ref($confhash{$itemid}{'display'}) eq 'HASH') {
                           my $displaylist;
                           if ($confhash{$itemid}{'display'}{'target'}) {
                               $displaylist = &mt('Display target').':&nbsp;'.
                                              $confhash{$itemid}{'display'}{'target'}.',';
                           }
                           foreach my $size ('width','height') { 
                               if ($confhash{$itemid}{'display'}{$size}) {
                                   $displaylist .= ('&nbsp;'x2).$lt{$size}.':&nbsp;'.
                                                   $confhash{$itemid}{'display'}{$size}.',';
                               }
                           }
                           if ($displaylist) {
                               $displaylist =~ s/,$//;
                               $resulttext .= '<li>'.$displaylist.'</li>';
                           }
                       } 
                       if (ref($confhash{$itemid}{'fields'}) eq 'HASH') {
                           my $fieldlist;
                           foreach my $field (@allfields) {
                               if ($confhash{$itemid}{'fields'}{$field}) {
                                   $fieldlist .= ('&nbsp;'x2).$lt{$field}.',';
                               }
                           }
                           if ($fieldlist) {
                               $fieldlist =~ s/,$//;
                               $resulttext .= '<li>'.&mt('Data sent').':'.$fieldlist.'</li>';
                           }
                       }
                       if (ref($confhash{$itemid}{'roles'}) eq 'HASH') {
                           my $rolemaps;
                           foreach my $role (@courseroles) {
                               if ($confhash{$itemid}{'roles'}{$role}) {
                                   $rolemaps .= ('&nbsp;'x2).&Apache::lonnet::plaintext($role,'Course').'='.
                                                $confhash{$itemid}{'roles'}{$role}.',';
                               }
                           }
                           if ($rolemaps) {
                               $rolemaps =~ s/,$//; 
                               $resulttext .= '<li>'.&mt('Role mapping:').$rolemaps.'</li>';
                           }
                       }
                       if (ref($confhash{$itemid}{'custom'}) eq 'HASH') {
                           my $customlist;
                           if (keys(%{$confhash{$itemid}{'custom'}})) {
                               foreach my $key (sort(keys(%{$confhash{$itemid}{'custom'}}))) {
                                   $customlist .= $key.':'.$confhash{$itemid}{'custom'}{$key}.('&nbsp;'x2);
                               } 
                           }
                           if ($customlist) {
                               $resulttext .= '<li>'.&mt('Custom items').':'.$customlist.'</li>';
                           }
                       } 
                       $resulttext .= '</ul></li>';
                   }
               }
               $resulttext .= '</ul>';
           } else {
               $resulttext = &mt('No changes made.');
           }
       } else {
           $errors .= '<li><span class="LC_error">'.&mt('Failed to save changes').'</span></li>';
       }
       if ($errors) {
           $resulttext .= &mt('The following errors occurred: ').'<ul>'.
                          $errors.'</ul>';
       }
       return $resulttext;
   }
   
   sub process_ltitools_image {
       my ($r,$dom,$confname,$caller,$itemid,$configuserok,$switchserver,$author_ok) = @_;
       my $filename = $env{'form.'.$caller.'.filename'};
       my ($error,$url);
       my ($width,$height) = (21,21);
       if ($configuserok eq 'ok') {
           if ($switchserver) {
               $error = &mt('Upload of Tool Provider (LTI) icon is not permitted to this server: [_1]',
                            $switchserver);
           } elsif ($author_ok eq 'ok') {
               my ($result,$imageurl,$madethumb) =
                   &publishlogo($r,'upload',$caller,$dom,$confname,
                                "ltitools/$itemid/icon",$width,$height);
               if ($result eq 'ok') {
                   if ($madethumb) {
                       my ($path,$imagefile) = ($imageurl =~ m{^(.+)/([^/]+)$});
                       my $imagethumb = "$path/tn-".$imagefile;
                       $url = $imagethumb;
                   } else {
                       $url = $imageurl;
                   }
               } else {
                   $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$result);
               }
           } else {
               $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3].  Error was: [_4].",$filename,$confname,$dom,$author_ok);
           }
       } else {
           $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3].  Error was: [_4].",$filename,$confname,$dom,$configuserok);
       }
       return ($url,$error);
   }
   
   sub get_ltitools_id {
       my ($cdom,$title) = @_;
       # get lock on ltitools db
       my $lockhash = {
                         lock => $env{'user.name'}.
                                 ':'.$env{'user.domain'},
                      };
       my $tries = 0;
       my $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
       my ($id,$error);
    
       while (($gotlock ne 'ok') && ($tries<10)) {
           $tries ++;
           sleep (0.1);
           $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
       }
       if ($gotlock eq 'ok') {
           my %currids = &Apache::lonnet::dump_dom('ltitools',$cdom);
           if ($currids{'lock'}) {
               delete($currids{'lock'});
               if (keys(%currids)) {
                   my @curr = sort { $a <=> $b } keys(%currids);
                   if ($curr[-1] =~ /^\d+$/) {
                       $id = 1 + $curr[-1];
                   }
               } else {
                   $id = 1;
               }
               if ($id) {
                   unless (&Apache::lonnet::newput_dom('ltitools',{ $id => $title },$cdom) eq 'ok') {
                       $error = 'nostore';
                   }
               } else {
                   $error = 'nonumber';
               }
           }
           my $dellockoutcome = &Apache::lonnet::del_dom('ltitools',['lock'],$cdom);
       } else {
           $error = 'nolock';
       }
       return ($id,$error);
   }
   
 sub modify_autoenroll {  sub modify_autoenroll {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,%changes);      my ($resulttext,%changes);
Line 7460  sub modify_autoenroll { Line 9979  sub modify_autoenroll {
     my $autorun = &Apache::lonnet::auto_run(undef,$dom),      my $autorun = &Apache::lonnet::auto_run(undef,$dom),
     my %title = ( run => 'Auto-enrollment active',      my %title = ( run => 'Auto-enrollment active',
                   sender => 'Sender for notification messages',                    sender => 'Sender for notification messages',
                   coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)');                    coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)',
                     failsafe => 'Failsafe for no drops if institutional data missing for a section');
     my @offon = ('off','on');      my @offon = ('off','on');
     my $sender_uname = $env{'form.sender_uname'};      my $sender_uname = $env{'form.sender_uname'};
     my $sender_domain = $env{'form.sender_domain'};      my $sender_domain = $env{'form.sender_domain'};
Line 7470  sub modify_autoenroll { Line 9990  sub modify_autoenroll {
         $sender_domain = '';          $sender_domain = '';
     }      }
     my $coowners = $env{'form.autoassign_coowners'};      my $coowners = $env{'form.autoassign_coowners'};
       my $failsafe = $env{'form.autoenroll_failsafe'};
       $failsafe =~ s{^\s+|\s+$}{}g;
       if ($failsafe =~ /\D/) {
           undef($failsafe);
       }
     my %autoenrollhash =  (      my %autoenrollhash =  (
                        autoenroll => { 'run' => $env{'form.autoenroll_run'},                         autoenroll => { 'run' => $env{'form.autoenroll_run'},
                                        'sender_uname' => $sender_uname,                                         'sender_uname' => $sender_uname,
                                        'sender_domain' => $sender_domain,                                         'sender_domain' => $sender_domain,
                                        'co-owners' => $coowners,                                         'co-owners' => $coowners,
                                          'autofailsafe' => $failsafe,
                                 }                                  }
                      );                       );
     my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,
Line 7501  sub modify_autoenroll { Line 10027  sub modify_autoenroll {
             }              }
         } elsif ($coowners) {          } elsif ($coowners) {
             $changes{'coowners'} = 1;              $changes{'coowners'} = 1;
         }                }
           if ($currautoenroll{'autofailsafe'} ne $failsafe) {
               $changes{'autofailsafe'} = 1;
           }
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if ($changes{'run'}) {              if ($changes{'run'}) {
Line 7521  sub modify_autoenroll { Line 10050  sub modify_autoenroll {
                     $lastactref->{'domainconfig'} = 1;                      $lastactref->{'domainconfig'} = 1;
                 }                  }
             }              }
               if ($changes{'autofailsafe'}) {
                   if ($failsafe ne '') {
                       $resulttext .= '<li>'.&mt("$title{'failsafe'} set to [_1]",$failsafe).'</li>';
                   } else {
                       $resulttext .= '<li>'.&mt("$title{'failsafe'} deleted");
                   }
                   &Apache::lonnet::get_domain_defaults($dom,1);
                   if (ref($lastactref) eq 'HASH') {
                       $lastactref->{'domdefaults'} = 1;
                   }
               }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
             $resulttext = &mt('No changes made to auto-enrollment settings');              $resulttext = &mt('No changes made to auto-enrollment settings');
Line 7736  sub modify_autocreate { Line 10276  sub modify_autocreate {
         $newvals{$item} = 0 if ($newvals{$item} eq '');          $newvals{$item} = 0 if ($newvals{$item} eq '');
     }      }
     $newvals{'xmldc'} = $env{'form.autocreate_xmldc'};      $newvals{'xmldc'} = $env{'form.autocreate_xmldc'};
     my %domcoords = &get_active_dcs($dom);      my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);
     unless (exists($domcoords{$newvals{'xmldc'}})) {      unless (exists($domcoords{$newvals{'xmldc'}})) {
         $newvals{'xmldc'} = '';          $newvals{'xmldc'} = '';
     }       } 
Line 7793  sub modify_autocreate { Line 10333  sub modify_autocreate {
 }  }
   
 sub modify_directorysrch {  sub modify_directorysrch {
     my ($dom,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,%changes);      my ($resulttext,%changes);
     my %currdirsrch;      my %currdirsrch;
     if (ref($domconfig{'directorysrch'}) eq 'HASH') {      if (ref($domconfig{'directorysrch'}) eq 'HASH') {
Line 7801  sub modify_directorysrch { Line 10341  sub modify_directorysrch {
             $currdirsrch{$key} = $domconfig{'directorysrch'}{$key};              $currdirsrch{$key} = $domconfig{'directorysrch'}{$key};
         }          }
     }      }
     my %title = ( available => 'Directory search available',      my %title = ( available => 'Institutional directory search available',
                   localonly => 'Other domains can search',                    localonly => 'Other domains can search institution',
                     lcavailable => 'LON-CAPA directory search available',
                     lclocalonly => 'Other domains can search LON-CAPA domain',
                   searchby => 'Search types',                    searchby => 'Search types',
                   searchtypes => 'Search latitude');                    searchtypes => 'Search latitude');
     my @offon = ('off','on');      my @offon = ('off','on');
Line 7876  sub modify_directorysrch { Line 10418  sub modify_directorysrch {
     my %dirsrch_hash =  (      my %dirsrch_hash =  (
             directorysrch => { available => $env{'form.dirsrch_available'},              directorysrch => { available => $env{'form.dirsrch_available'},
                                cansearch => \@cansearch,                                 cansearch => \@cansearch,
                                localonly => $env{'form.dirsrch_localonly'},                                 localonly => $env{'form.dirsrch_instlocalonly'},
                                  lclocalonly => $env{'form.dirsrch_domlocalonly'},
                                  lcavailable => $env{'form.dirsrch_domavailable'},
                                searchby => \@searchby,                                 searchby => \@searchby,
                                searchtypes => \@searchtypes,                                 searchtypes => \@searchtypes,
                              }                               }
Line 7893  sub modify_directorysrch { Line 10437  sub modify_directorysrch {
                 $changes{'available'} = 1;                  $changes{'available'} = 1;
             }              }
         }          }
           if (exists($currdirsrch{'lcavailable'})) {
               if ($currdirsrch{'lcavailable'} ne $env{'form.dirsrch_domavailable'}) {
                   $changes{'lcavailable'} = 1;
               }
           } else {
               if ($env{'form.dirsrch_lcavailable'} eq '1') {
                   $changes{'lcavailable'} = 1;
               }
           }
         if (exists($currdirsrch{'localonly'})) {          if (exists($currdirsrch{'localonly'})) {
              if ($currdirsrch{'localonly'} ne $env{'form.dirsrch_localonly'}) {              if ($currdirsrch{'localonly'} ne $env{'form.dirsrch_instlocalonly'}) {
                  $changes{'localonly'} = 1;                  $changes{'localonly'} = 1;
              }              }
         } else {          } else {
             if ($env{'form.dirsrch_localonly'} eq '1') {              if ($env{'form.dirsrch_instlocalonly'} eq '1') {
                 $changes{'localonly'} = 1;                  $changes{'localonly'} = 1;
             }              }
         }          }
           if (exists($currdirsrch{'lclocalonly'})) {
               if ($currdirsrch{'lclocalonly'} ne $env{'form.dirsrch_domlocalonly'}) {
                   $changes{'lclocalonly'} = 1;
               }
           } else {
               if ($env{'form.dirsrch_domlocalonly'} eq '1') {
                   $changes{'lclocalonly'} = 1;
               }
           }
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if ($changes{'available'}) {              if ($changes{'available'}) {
                 $resulttext .= '<li>'.&mt("$title{'available'} set to: $offon[$env{'form.dirsrch_available'}]").'</li>';                  $resulttext .= '<li>'.&mt("$title{'available'} set to: $offon[$env{'form.dirsrch_available'}]").'</li>';
             }              }
               if ($changes{'lcavailable'}) {
                   $resulttext .= '<li>'.&mt("$title{'lcavailable'} set to: $offon[$env{'form.dirsrch_domavailable'}]").'</li>';
               }
             if ($changes{'localonly'}) {              if ($changes{'localonly'}) {
                 $resulttext .= '<li>'.&mt("$title{'localonly'} set to: $otherdoms[$env{'form.dirsrch_localonly'}]").'</li>';                  $resulttext .= '<li>'.&mt("$title{'localonly'} set to: $otherdoms[$env{'form.dirsrch_instlocalonly'}]").'</li>';
               }
               if ($changes{'lclocalonly'}) {
                   $resulttext .= '<li>'.&mt("$title{'lclocalonly'} set to: $otherdoms[$env{'form.dirsrch_domlocalonly'}]").'</li>';
             }              }
   
             if (ref($changes{'cansearch'}) eq 'ARRAY') {              if (ref($changes{'cansearch'}) eq 'ARRAY') {
                 my $chgtext;                  my $chgtext;
                 if (ref($usertypes) eq 'HASH') {                  if (ref($usertypes) eq 'HASH') {
Line 7960  sub modify_directorysrch { Line 10527  sub modify_directorysrch {
                 $resulttext .= '<li>'.&mt($title{'searchtypes'}.' set to: "[_1]"',$chgtext).'</li>';                  $resulttext .= '<li>'.&mt($title{'searchtypes'}.' set to: "[_1]"',$chgtext).'</li>';
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
               &Apache::lonnet::do_cache_new('directorysrch',$dom,$dirsrch_hash{'directorysrch'},3600);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'directorysrch'} = 1;
               }
         } else {          } else {
             $resulttext = &mt('No changes made to institution directory search settings');              $resulttext = &mt('No changes made to directory search settings');
         }          }
     } else {      } else {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
Line 7978  sub modify_contacts { Line 10549  sub modify_contacts {
             $currsetting{$key} = $domconfig{'contacts'}{$key};              $currsetting{$key} = $domconfig{'contacts'}{$key};
         }          }
     }      }
     my (%others,%to,%bcc);      my (%others,%to,%bcc,%includestr,%includeloc);
     my @contacts = ('supportemail','adminemail');      my @contacts = ('supportemail','adminemail');
     my @mailings = ('errormail','packagesmail','helpdeskmail','lonstatusmail',      my @mailings = ('errormail','packagesmail','helpdeskmail','otherdomsmail',
                     'requestsmail','updatesmail','idconflictsmail');                      'lonstatusmail','requestsmail','updatesmail','idconflictsmail');
     my @toggles = ('reporterrors','reportupdates');      my @toggles = ('reporterrors','reportupdates');
       my ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();
     foreach my $type (@mailings) {      foreach my $type (@mailings) {
         @{$newsetting{$type}} =           @{$newsetting{$type}} = 
             &Apache::loncommon::get_env_multiple('form.'.$type);              &Apache::loncommon::get_env_multiple('form.'.$type);
Line 7992  sub modify_contacts { Line 10564  sub modify_contacts {
             } else {              } else {
                 $contacts_hash{contacts}{$type}{$item} = 0;                  $contacts_hash{contacts}{$type}{$item} = 0;
             }              }
         }            }
         $others{$type} = $env{'form.'.$type.'_others'};          $others{$type} = $env{'form.'.$type.'_others'};
         $contacts_hash{contacts}{$type}{'others'} = $others{$type};          $contacts_hash{contacts}{$type}{'others'} = $others{$type};
         if ($type eq 'helpdeskmail') {          if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
             $bcc{$type} = $env{'form.'.$type.'_bcc'};              $bcc{$type} = $env{'form.'.$type.'_bcc'};
             $contacts_hash{contacts}{$type}{'bcc'} = $bcc{$type};              $contacts_hash{contacts}{$type}{'bcc'} = $bcc{$type};
               if (($env{'form.'.$type.'_includestr'} ne '') && ($env{'form.'.$type.'_includeloc'} =~ /^s|b$/)) {
                   $includestr{$type} = $env{'form.'.$type.'_includestr'};
                   $includeloc{$type} = $env{'form.'.$type.'_includeloc'};
                   $contacts_hash{contacts}{$type}{'include'} = $includeloc{$type}.':'.&escape($includestr{$type});
               }
         }          }
     }      }
     foreach my $item (@contacts) {      foreach my $item (@contacts) {
Line 8009  sub modify_contacts { Line 10586  sub modify_contacts {
             $contacts_hash{'contacts'}{$item} = $env{'form.'.$item};              $contacts_hash{'contacts'}{$item} = $env{'form.'.$item};
         }          }
     }      }
       if ((ref($fields) eq 'ARRAY') && (ref($possoptions) eq 'HASH')) {
           foreach my $field (@{$fields}) {
               if (ref($possoptions->{$field}) eq 'ARRAY') {
                   my $value = $env{'form.helpform_'.$field};
                   $value =~ s/^\s+|\s+$//g;
                   if (grep(/^\Q$value\E$/,@{$possoptions->{$field}})) {
                       $contacts_hash{contacts}{'helpform'}{$field} = $value;
                       if ($field eq 'screenshot') {
                           $env{'form.helpform_maxsize'} =~ s/^\s+|\s+$//g;
                           if ($env{'form.helpform_maxsize'} =~ /^\d+\.?\d*$/) {
                               $contacts_hash{contacts}{'helpform'}{'maxsize'} = $env{'form.helpform_maxsize'};
                           }
                       }
                   }
               }
           }
       }
     if (keys(%currsetting) > 0) {      if (keys(%currsetting) > 0) {
         foreach my $item (@contacts) {          foreach my $item (@contacts) {
             if ($to{$item} ne $currsetting{$item}) {              if ($to{$item} ne $currsetting{$item}) {
Line 8028  sub modify_contacts { Line 10622  sub modify_contacts {
             if ($others{$type} ne $currsetting{$type}{'others'}) {              if ($others{$type} ne $currsetting{$type}{'others'}) {
                 push(@{$changes{$type}},'others');                  push(@{$changes{$type}},'others');
             }              }
             if ($type eq 'helpdeskmail') {                 if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                 if ($bcc{$type} ne $currsetting{$type}{'bcc'}) {                  if ($bcc{$type} ne $currsetting{$type}{'bcc'}) {
                     push(@{$changes{$type}},'bcc');                       push(@{$changes{$type}},'bcc'); 
                 }                  }
                   my ($currloc,$currstr) = split(/:/,$currsetting{$type}{'include'},2);
                   if (($includeloc{$type} ne $currloc) || (&escape($includestr{$type}) ne $currstr)) {
                       push(@{$changes{$type}},'include');
                   }
               }
           }
           if (ref($fields) eq 'ARRAY') {
               if (ref($currsetting{'helpform'}) eq 'HASH') {
                   foreach my $field (@{$fields}) {
                       if ($currsetting{'helpform'}{$field} ne $contacts_hash{'contacts'}{'helpform'}{$field}) {
                           push(@{$changes{'helpform'}},$field);
                       }
                       if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {
                           if ($currsetting{'helpform'}{'maxsize'} ne $contacts_hash{'contacts'}{'helpform'}{'maxsize'}) {
                               push(@{$changes{'helpform'}},'maxsize');
                           }
                       }
                   }
               } else {
                   foreach my $field (@{$fields}) {
                       if ($contacts_hash{'contacts'}{'helpform'}{$field} ne 'yes') {
                           push(@{$changes{'helpform'}},$field);
                       }
                       if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {
                           if ($contacts_hash{'contacts'}{'helpform'}{'maxsize'} != 1) {
                               push(@{$changes{'helpform'}},'maxsize');
                           }
                       }
                   }
             }              }
         }          }
     } else {      } else {
Line 8041  sub modify_contacts { Line 10664  sub modify_contacts {
         $default{'errormail'} = 'adminemail';          $default{'errormail'} = 'adminemail';
         $default{'packagesmail'} = 'adminemail';          $default{'packagesmail'} = 'adminemail';
         $default{'helpdeskmail'} = 'supportemail';          $default{'helpdeskmail'} = 'supportemail';
           $default{'otherdomsmail'} = 'supportemail';
         $default{'lonstatusmail'} = 'adminemail';          $default{'lonstatusmail'} = 'adminemail';
         $default{'requestsmail'} = 'adminemail';          $default{'requestsmail'} = 'adminemail';
         $default{'updatesmail'} = 'adminemail';          $default{'updatesmail'} = 'adminemail';
         foreach my $item (@contacts) {          foreach my $item (@contacts) {
            if ($to{$item} ne $default{$item}) {             if ($to{$item} ne $default{$item}) {
               $changes{$item} = 1;                 $changes{$item} = 1;
            }             }
         }          }
         foreach my $type (@mailings) {          foreach my $type (@mailings) {
             if ((@{$newsetting{$type}} != 1) || ($newsetting{$type}[0] ne $default{$type})) {              if ((@{$newsetting{$type}} != 1) || ($newsetting{$type}[0] ne $default{$type})) {
                  
                 push(@{$changes{$type}},@{$newsetting{$type}});                  push(@{$changes{$type}},@{$newsetting{$type}});
             }              }
             if ($others{$type} ne '') {              if ($others{$type} ne '') {
                 push(@{$changes{$type}},'others');                  push(@{$changes{$type}},'others');
             }              }
             if ($type eq 'helpdeskmail') {              if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                 if ($bcc{$type} ne '') {                  if ($bcc{$type} ne '') {
                     push(@{$changes{$type}},'bcc');                      push(@{$changes{$type}},'bcc');
                 }                  }
                   if (($includeloc{$type} =~ /^b|s$/) && ($includestr{$type} ne '')) {
                       push(@{$changes{$type}},'include');
                   }
               }
           }
           if (ref($fields) eq 'ARRAY') {
               foreach my $field (@{$fields}) {
                   if ($contacts_hash{'contacts'}{'helpform'}{$field} ne 'yes') {
                       push(@{$changes{'helpform'}},$field);
                   }
                   if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {
                       if ($contacts_hash{'contacts'}{'helpform'}{'maxsize'} != 1) {
                           push(@{$changes{'helpform'}},'maxsize');
                       }
                   }
             }              }
         }          }
     }      }
Line 8092  sub modify_contacts { Line 10730  sub modify_contacts {
             }              }
             foreach my $type (@mailings) {              foreach my $type (@mailings) {
                 if (ref($changes{$type}) eq 'ARRAY') {                  if (ref($changes{$type}) eq 'ARRAY') {
                     $resulttext .= '<li>'.$titles->{$type}.': ';                      if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                           $resulttext .= '<li>'.$titles->{$type}.' -- '.&mt('sent to').': ';
                       } else {
                           $resulttext .= '<li>'.$titles->{$type}.': ';
                       }
                     my @text;                      my @text;
                     foreach my $item (@{$newsetting{$type}}) {                      foreach my $item (@{$newsetting{$type}}) {
                         push(@text,$short_titles->{$item});                          push(@text,$short_titles->{$item});
Line 8100  sub modify_contacts { Line 10742  sub modify_contacts {
                     if ($others{$type} ne '') {                      if ($others{$type} ne '') {
                         push(@text,$others{$type});                          push(@text,$others{$type});
                     }                      }
                     $resulttext .= '<span class="LC_cusr_emph">'.                      if (@text) {
                                    join(', ',@text).'</span>';                          $resulttext .= '<span class="LC_cusr_emph">'.
                     if ($type eq 'helpdeskmail') {                                         join(', ',@text).'</span>';
                       }
                       if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                         if ($bcc{$type} ne '') {                          if ($bcc{$type} ne '') {
                             $resulttext .= '&nbsp;'.&mt('with Bcc to').': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';                              my $bcctext;
                               if (@text) {
                                   $bcctext = '&nbsp;'.&mt('with Bcc to');
                               } else {
                                   $bcctext = '(Bcc)';
                               }
                               $resulttext .= $bcctext.': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';
                           } elsif (!@text) {
                               $resulttext .= &mt('No one');
                           }   
                           if ($includestr{$type} ne '') {
                               if ($includeloc{$type} eq 'b') {
                                   $resulttext .= '<br />'.&mt('Text automatically added to e-mail body:').' '.$includestr{$type};
                               } elsif ($includeloc{$type} eq 's') {
                                   $resulttext .= '<br />'.&mt('Text automatically added to e-mail subject:').' '.$includestr{$type};
                               }
                         }                          }
                       } elsif (!@text) {
                           $resulttext .= &mt('No recipients');
                     }                      }
                     $resulttext .= '</li>';                      $resulttext .= '</li>';
                 }                  }
Line 8127  sub modify_contacts { Line 10788  sub modify_contacts {
                                         &mt('LON-CAPA core group - MSU'),600,500)).                                          &mt('LON-CAPA core group - MSU'),600,500)).
                                 '</li>';                                  '</li>';
             }              }
               if ((ref($changes{'helpform'}) eq 'ARRAY') && (ref($fields) eq 'ARRAY')) {
                   my (@optional,@required,@unused,$maxsizechg);
                   foreach my $field (@{$changes{'helpform'}}) {
                       if ($field eq 'maxsize') {
                           $maxsizechg = 1;
                           next;
                       }
                       if ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'yes') {
                           push(@optional,$field);
                       } elsif ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'no') {
                           push(@unused,$field);
                       } elsif ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'req') {
                           push(@required,$field);
                       }
                   }
                   if (@optional) {
                       $resulttext .= '<li>'.
                                      &mt('Help form fields changed to "Optional": [_1].',
                                          '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @optional)).'</span>'.
                                      '</li>';
                   }
                   if (@required) {
                       $resulttext .= '<li>'.
                                      &mt('Help form fields changed to "Required": [_1].',
                                          '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @required)).'</span>'.
                                      '</li>';
                   }
                   if (@unused) {
                       $resulttext .= '<li>'.
                                      &mt('Help form fields changed to "Not shown": [_1].',
                                          '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @unused)).'</span>'.
                                      '</li>';
                   }
                   if ($maxsizechg) {
                       $resulttext .= '<li>'.
                                      &mt('Max size for file uploaded to help form by logged-in user set to [_1] MB.',
                                          $contacts_hash{'contacts'}{'helpform'}{'maxsize'}).
                                      '</li>';
   
                   }
               }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
             $resulttext = &mt('No changes made to contact information');              $resulttext = &mt('No changes made to contacts and form settings');
         }          }
     } else {      } else {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
Line 8148  sub modify_usercreation { Line 10850  sub modify_usercreation {
                 if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {                  if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {
                     foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {                      foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
                         if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||                          if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||
                             ($item eq 'captcha') || ($item eq 'recaptchakeys')) {                              ($item eq 'captcha') || ($item eq 'recaptchakeys') ||
                               ($item eq 'recaptchaversion')) {
                             $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};                              $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
                         } else {                          } else {
                             $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};                              $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
Line 8372  sub modify_selfcreation { Line 11075  sub modify_selfcreation {
                     foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {                      foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
                         if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||                          if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||
                             ($item eq 'captcha') || ($item eq 'recaptchakeys') ||                               ($item eq 'captcha') || ($item eq 'recaptchakeys') || 
                               ($item eq 'recaptchaversion') ||
                             ($item eq 'emailusername') || ($item eq 'notify') ||                              ($item eq 'emailusername') || ($item eq 'notify') ||
                             ($item eq 'selfcreateprocessing') || ($item eq 'shibenv')) {                              ($item eq 'selfcreateprocessing') || ($item eq 'shibenv')) {
                             $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};                              $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
Line 8450  sub modify_selfcreation { Line 11154  sub modify_selfcreation {
 # value set to one), if self-creation with e-mail address permitted, where $type is user type: faculty, staff, student etc.  # value set to one), if self-creation with e-mail address permitted, where $type is user type: faculty, staff, student etc.
 #  #
   
     if ($env{'form.cancreate_email'} eq 'email') {      if ($env{'form.cancreate_email'}) {
         push(@contexts,'emailusername');          push(@contexts,'emailusername');
         if (ref($types) eq 'ARRAY') {          if (ref($types) eq 'ARRAY') {
             foreach my $type (@{$types}) {              foreach my $type (@{$types}) {
Line 8701  sub modify_selfcreation { Line 11405  sub modify_selfcreation {
 #  #
     $save_usercreate{'cancreate'}{'captcha'} = $savecaptcha{'captcha'};      $save_usercreate{'cancreate'}{'captcha'} = $savecaptcha{'captcha'};
     $save_usercreate{'cancreate'}{'recaptchakeys'} = $savecaptcha{'recaptchakeys'};      $save_usercreate{'cancreate'}{'recaptchakeys'} = $savecaptcha{'recaptchakeys'};
       $save_usercreate{'cancreate'}{'recaptchaversion'} = $savecaptcha{'recaptchaversion'};
     $save_usercreate{'cancreate'}{'selfcreate'} = $cancreate{'selfcreate'};      $save_usercreate{'cancreate'}{'selfcreate'} = $cancreate{'selfcreate'};
     if (ref($cancreate{'notify'}) eq 'HASH') {      if (ref($cancreate{'notify'}) eq 'HASH') {
         $save_usercreate{'cancreate'}{'notify'} = $cancreate{'notify'};          $save_usercreate{'cancreate'}{'notify'} = $cancreate{'notify'};
Line 8862  sub modify_selfcreation { Line 11567  sub modify_selfcreation {
                             $chgtext .= '<li>'.&mt('Private key set to [_1]',$pubkey).'</li>';                              $chgtext .= '<li>'.&mt('Private key set to [_1]',$pubkey).'</li>';
                         }                          }
                         $chgtext .= '</ul>';                          $chgtext .= '</ul>';
                       } elsif ($type eq 'recaptchaversion') {
                           if ($savecaptcha{'captcha'} eq 'recaptcha') {
                               $chgtext .= &mt('ReCAPTCHA set to version [_1]',$savecaptcha{$type});
                           }
                     } elsif ($type eq 'emailusername') {                      } elsif ($type eq 'emailusername') {
                         if (ref($cancreate{'emailusername'}) eq 'HASH') {                          if (ref($cancreate{'emailusername'}) eq 'HASH') {
                             if (ref($types) eq 'ARRAY') {                              if (ref($types) eq 'ARRAY') {
                                 foreach my $type (@{$types}) {                                  foreach my $type (@{$types}) {
                                     if (ref($cancreate{'emailusername'}{$type}) eq 'HASH') {                                      if (ref($cancreate{'emailusername'}{$type}) eq 'HASH') {
                                         if (keys(%{$cancreate{'emailusername'}{$type}}) > 0) {                                          if (keys(%{$cancreate{'emailusername'}{$type}}) > 0) {
                                             $chgtext .= &mt('When self-creating account with e-mail as username, the following information will be provided by [_1]:',$usertypes->{$type}).                                              $chgtext .= &mt('When self-creating account with e-mail as username, the following information will be provided by [_1]:',"'$usertypes->{$type}'").
                                                     '<ul>';                                                      '<ul>';
                                             foreach my $field (@{$infofields}) {                                              foreach my $field (@{$infofields}) {
                                                 if ($cancreate{'emailusername'}{$type}{$field}) {                                                  if ($cancreate{'emailusername'}{$type}{$field}) {
                                                     $chgtext .= '<li>'.$infotitles->{$field}.'</li>';                                                      $chgtext .= '<li>'.$infotitles->{$field}.'</li>';
                                                 }                                                  }
                                             }                                              }
                                               $chgtext .= '</ul>';
                                           } else {
                                               $chgtext .= &mt('When self creating account with e-mail as username, no information besides e-mail address will be provided by [_1].',"'$usertypes->{$type}'").'<br />';
                                         }                                          }
                                         $chgtext .= '</ul>';  
                                     } else {                                      } else {
                                         $chgtext .= &mt('When self creating account with e-mail as username, no information besides e-mail address will be provided by [_1].',$usertypes->{$type}).'<br />';                                          $chgtext .= &mt('When self creating account with e-mail as username, no information besides e-mail address will be provided by [_1].',"'$usertypes->{$type}'").'<br />';
                                     }                                      }
                                 }                                  }
                             }                              }
Line 8980  sub process_captcha { Line 11691  sub process_captcha {
             $changes->{'captcha'} = 1;              $changes->{'captcha'} = 1;
         }          }
     }      }
     my ($newpub,$newpriv,$currpub,$currpriv);      my ($newpub,$newpriv,$currpub,$currpriv,$newversion,$currversion);
     if ($newsettings->{'captcha'} eq 'recaptcha') {      if ($newsettings->{'captcha'} eq 'recaptcha') {
         $newpub = $env{'form.'.$container.'_recaptchapub'};          $newpub = $env{'form.'.$container.'_recaptchapub'};
         $newpriv = $env{'form.'.$container.'_recaptchapriv'};          $newpriv = $env{'form.'.$container.'_recaptchapriv'};
         $newpub =~ s/\W//g;          $newpub =~ s/[^\w\-]//g;
         $newpriv =~ s/\W//g;          $newpriv =~ s/[^\w\-]//g;
         $newsettings->{'recaptchakeys'} = {          $newsettings->{'recaptchakeys'} = {
                                              public  => $newpub,                                               public  => $newpub,
                                              private => $newpriv,                                               private => $newpriv,
                                           };                                            };
           $newversion = $env{'form.'.$container.'_recaptchaversion'};
           $newversion =~ s/\D//g;
           if ($newversion ne '2') {
               $newversion = 1;
           }
           $newsettings->{'recaptchaversion'} = $newversion;
     }      }
     if (ref($current->{'recaptchakeys'}) eq 'HASH') {      if (ref($current->{'recaptchakeys'}) eq 'HASH') {
         $currpub = $current->{'recaptchakeys'}{'public'};          $currpub = $current->{'recaptchakeys'}{'public'};
Line 9001  sub process_captcha { Line 11718  sub process_captcha {
                                               }                                                }
         }          }
     }      }
       if ($current->{'captcha'} eq 'recaptcha') {
           $currversion = $current->{'recaptchaversion'};
           if ($currversion ne '2') {
               $currversion = 1;
           }
       }
       if ($currversion ne $newversion) {
           if ($container eq 'cancreate') {
               if (ref($changes->{'cancreate'}) eq 'ARRAY') {
                   push(@{$changes->{'cancreate'}},'recaptchaversion');
               } elsif (!defined($changes->{'cancreate'})) {
                   $changes->{'cancreate'} = ['recaptchaversion'];
               }
           } else {
               $changes->{'recaptchaversion'} = 1;
           }
       }
     if (($newpub ne $currpub) || ($newpriv ne $currpriv)) {      if (($newpub ne $currpub) || ($newpriv ne $currpriv)) {
         if ($container eq 'cancreate') {          if ($container eq 'cancreate') {
             if (ref($changes->{'cancreate'}) eq 'ARRAY') {              if (ref($changes->{'cancreate'}) eq 'ARRAY') {
Line 9122  sub modify_defaults { Line 11856  sub modify_defaults {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors);      my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors);
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
     my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def','portal_def');      my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def',
                    'portal_def','intauth_cost','intauth_check','intauth_switch');
     my @authtypes = ('internal','krb4','krb5','localauth');      my @authtypes = ('internal','krb4','krb5','localauth');
     foreach my $item (@items) {      foreach my $item (@items) {
         $newvalues{$item} = $env{'form.'.$item};          $newvalues{$item} = $env{'form.'.$item};
Line 9164  sub modify_defaults { Line 11899  sub modify_defaults {
                     push(@errors,$item);                      push(@errors,$item);
                 }                  }
             }              }
           } elsif ($item eq 'intauth_cost') {
               if ($newvalues{$item} ne '') {
                   if ($newvalues{$item} =~ /\D/) {
                       push(@errors,$item);
                   }
               }
           } elsif ($item eq 'intauth_check') {
               if ($newvalues{$item} ne '') {
                   unless ($newvalues{$item} =~ /^(0|1|2)$/) {
                       push(@errors,$item);
                   }
               }
           } elsif ($item eq 'intauth_switch') {
               if ($newvalues{$item} ne '') {
                   unless ($newvalues{$item} =~ /^(0|1|2)$/) {
                       push(@errors,$item);
                   }
               }
         }          }
         if (grep(/^\Q$item\E$/,@errors)) {          if (grep(/^\Q$item\E$/,@errors)) {
             $newvalues{$item} = $domdefaults{$item};              $newvalues{$item} = $domdefaults{$item};
Line 9318  sub modify_defaults { Line 12071  sub modify_defaults {
                                           localauth  => 'loc',                                            localauth  => 'loc',
                         );                          );
                         $value = $authnames{$shortauth{$value}};                          $value = $authnames{$shortauth{$value}};
                       } elsif ($item eq 'intauth_switch') {
                           my %optiondesc = &Apache::lonlocal::texthash (
                                               0 => 'No',
                                               1 => 'Yes',
                                               2 => 'Yes, and copy existing passwd file to passwd.bak file',
                                            );
                           if ($value =~ /^(0|1|2)$/) {
                               $value = $optiondesc{$value};
                           } else {
                               $value = &mt('none -- defaults to No');
                           }
                       } elsif ($item eq 'intauth_check') {
                           my %optiondesc = &Apache::lonlocal::texthash (
                                                0 => 'No',
                                                1 => 'Yes, allow login then update passwd file using default cost (if higher)',
                                                2 => 'Yes, disallow login if stored cost is less than domain default',
                                            );
                           if ($value =~ /^(0|1|2)$/) {
                               $value = $optiondesc{$value};
                           } else {
                               $value = &mt('none -- defaults to No');
                           }
                     }                      }
                     $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$item},$value).'</li>';                      $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$item},$value).'</li>';
                     $mailmsgtext .= "$title->{$item} set to $value\n";                        $mailmsgtext .= "$title->{$item} set to $value\n";  
Line 9466  sub modify_coursecategories { Line 12241  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 9480  sub modify_coursecategories { Line 12264  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 9502  sub modify_coursecategories { Line 12290  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 9564  sub modify_coursecategories { Line 12355  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 9685  sub modify_coursecategories { Line 12490  sub modify_coursecategories {
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
             if ($changes{'unauth'} || $changes{'auth'}) {              if ($changes{'unauth'} || $changes{'auth'}) {
                 &Apache::loncommon::devalidate_domconfig_cache($dom);                  my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
                   if ($changes{'auth'}) {
                       $domdefaults{'catauth'} = $domconfig{'coursecategories'}{'auth'};
                   }
                   if ($changes{'unauth'}) {
                       $domdefaults{'catunauth'} = $domconfig{'coursecategories'}{'unauth'};
                   }
                   my $cachetime = 24*60*60;
                   &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
                 if (ref($lastactref) eq 'HASH') {                  if (ref($lastactref) eq 'HASH') {
                     $lastactref->{'domainconfig'} = 1;                      $lastactref->{'domdefaults'} = 1;
                 }                  }
             }              }
         } else {          } else {
Line 9825  sub modify_serverstatuses { Line 12638  sub modify_serverstatuses {
 }  }
   
 sub modify_helpsettings {  sub modify_helpsettings {
     my ($r,$dom,$confname,%domconfig) = @_;      my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
     my ($resulttext,$errors,%changes,%helphash);      my ($resulttext,$errors,%changes,%helphash);
     my %defaultchecked = ('submitbugs' => 'on');      my %defaultchecked = ('submitbugs' => 'on');
     my @offon = ('off','on');      my @offon = ('off','on');
     my @toggles = ('submitbugs');      my @toggles = ('submitbugs');
       my %current = ('submitbugs' => '',
                      'adhoc'      => {},
                     );
     if (ref($domconfig{'helpsettings'}) eq 'HASH') {      if (ref($domconfig{'helpsettings'}) eq 'HASH') {
         foreach my $item (@toggles) {          %current = %{$domconfig{'helpsettings'}};
             if ($defaultchecked{$item} eq 'on') {       }
                 if ($domconfig{'helpsettings'}{$item} eq '') {      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
                     if ($env{'form.'.$item} eq '0') {      foreach my $item (@toggles) {
                         $changes{$item} = 1;          if ($defaultchecked{$item} eq 'on') { 
                     }              if ($current{$item} eq '') {
                 } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {                  if ($env{'form.'.$item} eq '0') {
                     $changes{$item} = 1;                      $changes{$item} = 1;
                 }                  }
             } elsif ($defaultchecked{$item} eq 'off') {              } elsif ($current{$item} ne $env{'form.'.$item}) {
                 if ($domconfig{'helpsettings'}{$item} eq '') {                  $changes{$item} = 1;
                     if ($env{'form.'.$item} eq '1') {              }
                         $changes{$item} = 1;          } elsif ($defaultchecked{$item} eq 'off') {
                     }              if ($current{$item} eq '') {
                 } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {                  if ($env{'form.'.$item} eq '1') {
                     $changes{$item} = 1;                      $changes{$item} = 1;
                 }                  }
               } elsif ($current{$item} ne $env{'form.'.$item}) {
                   $changes{$item} = 1;
             }              }
             if (($env{'form.'.$item} eq '0') || ($env{'form.'.$item} eq '1')) {          }
                 $helphash{'helpsettings'}{$item} = $env{'form.'.$item};          if (($env{'form.'.$item} eq '0') || ($env{'form.'.$item} eq '1')) {
               $helphash{'helpsettings'}{$item} = $env{'form.'.$item};
           }
       }
       my $maxnum = $env{'form.helproles_maxnum'};
       my $confname = $dom.'-domainconfig';
       my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');
       my (@allpos,%newsettings,%changedprivs,$newrole);
       my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
       my @accesstypes = ('all','dh','da','none','status','inc','exc');
       my %domhelpdesk = &Apache::lonnet::get_active_domroles($dom,['dh','da']);
       my %lt = &Apache::lonlocal::texthash(
                       s      => 'system',
                       d      => 'domain',
                       order  => 'Display order',
                       access => 'Role usage',
                       all    => 'All with domain helpdesk or helpdesk assistant role',
                       dh     => 'All with domain helpdesk role',
                       da     => 'All with domain helpdesk assistant role',
                       none   => 'None',
                       status => 'Determined based on institutional status',
                       inc    => 'Include all, but exclude specific personnel',
                       exc    => 'Exclude all, but include specific personnel',
       );
       for (my $num=0; $num<=$maxnum; $num++) {
           my ($prefix,$identifier,$rolename,%curr);
           if ($num == $maxnum) {
               next unless ($env{'form.newcusthelp'} == $maxnum);
               $identifier = 'custhelp'.$num;
               $prefix = 'helproles_'.$num;
               $rolename = $env{'form.custhelpname'.$num};
               $rolename=~s/[^A-Za-z0-9]//gs;
               next if ($rolename eq '');
               next if (exists($existing{'rolesdef_'.$rolename}));
               my %newprivs = &Apache::lonuserutils::custom_role_update($rolename,$identifier);
               my $result = &Apache::lonnet::definerole($rolename,$newprivs{'s'},$newprivs{'d'},
                                                        $newprivs{'c'},$confname,$dom);
               if ($result ne 'ok') {
                   $errors .= '<li><span class="LC_error">'.
                              &mt('An error occurred storing the new custom role: [_1]',
                              $result).'</span></li>';
                   next;
               } else {
                   $changedprivs{$rolename} = \%newprivs;
                   $newrole = $rolename;
               }
           } else {
               $prefix = 'helproles_'.$num;
               $rolename = $env{'form.'.$prefix};
               next if ($rolename eq '');
               next unless (exists($existing{'rolesdef_'.$rolename}));
               $identifier = 'custhelp'.$num;
               my %newprivs = &Apache::lonuserutils::custom_role_update($rolename,$identifier);
               my %currprivs;
               ($currprivs{'s'},$currprivs{'d'},$currprivs{'c'}) =
                   split(/\_/,$existing{'rolesdef_'.$rolename});
               foreach my $level ('c','d','s') {
                   if ($newprivs{$level} ne $currprivs{$level}) {
                       my $result = &Apache::lonnet::definerole($rolename,$newprivs{'s'},$newprivs{'d'},
                                                                $newprivs{'c'},$confname,$dom);
                       if ($result ne 'ok') {
                           $errors .= '<li><span class="LC_error">'.
                                      &mt('An error occurred storing privileges for existing role [_1]: [_2]',
                                          $rolename,$result).'</span></li>';
                       } else {
                           $changedprivs{$rolename} = \%newprivs;
                       }
                       last;
                   }
               }
               if (ref($current{'adhoc'}) eq 'HASH') {
                   if (ref($current{'adhoc'}{$rolename}) eq 'HASH') {
                       %curr = %{$current{'adhoc'}{$rolename}};
                   }
               }
           }
           my $newpos = $env{'form.'.$prefix.'_pos'};
           $newpos =~ s/\D+//g;
           $allpos[$newpos] = $rolename;
           my $newdesc = $env{'form.'.$prefix.'_desc'};
           $helphash{'helpsettings'}{'adhoc'}{$rolename}{'desc'} = $newdesc;
           if ($curr{'desc'}) {
               if ($curr{'desc'} ne $newdesc) {
                   $changes{'customrole'}{$rolename}{'desc'} = 1;
                   $newsettings{$rolename}{'desc'} = $newdesc;
               }
           } elsif ($newdesc ne '') {
               $changes{'customrole'}{$rolename}{'desc'} = 1;
               $newsettings{$rolename}{'desc'} = $newdesc;
           }
           my $access = $env{'form.'.$prefix.'_access'};
           if (grep(/^\Q$access\E$/,@accesstypes)) {
               $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'} = $access;
               if ($access eq 'status') {
                   my @statuses = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_status');
                   if (scalar(@statuses) == 0) {
                       $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'} = 'none';
                   } else {
                       my (@shownstatus,$numtypes);
                       $helphash{'helpsettings'}{'adhoc'}{$rolename}{$access} = [];
                       if (ref($types) eq 'ARRAY') {
                           $numtypes = scalar(@{$types});
                           foreach my $type (sort(@statuses)) {
                               if ($type eq 'default') {
                                   push(@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}},$type);
                               } elsif (grep(/^\Q$type\E$/,@{$types})) {
                                   push(@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}},$type);
                                   push(@shownstatus,$usertypes->{$type});
                               }
                           }
                       }
                       if (grep(/^default$/,@statuses)) {
                           push(@shownstatus,$othertitle);
                       }
                       if (scalar(@shownstatus) == 1+$numtypes) {
                           $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'} = 'all';
                           delete($helphash{'helpsettings'}{'adhoc'}{$rolename}{'status'});
                       } else {
                           $newsettings{$rolename}{'status'} = join(' '.&mt('or').' ',@shownstatus);
                           if (ref($curr{'status'}) eq 'ARRAY') {
                               my @diffs = &Apache::loncommon::compare_arrays($helphash{'helpsettings'}{'adhoc'}{$rolename}{$access},$curr{$access});
                               if (@diffs) {
                                   $changes{'customrole'}{$rolename}{$access} = 1;
                               }
                           } elsif (@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}}) {
                               $changes{'customrole'}{$rolename}{$access} = 1;
                           }
                       }
                   }
               } elsif (($access eq 'inc') || ($access eq 'exc')) {
                   my @personnel = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_staff_'.$access);
                   my @newspecstaff;
                   $helphash{'helpsettings'}{'adhoc'}{$rolename}{$access} = [];
                   foreach my $person (sort(@personnel)) {
                       if ($domhelpdesk{$person}) {
                           push(@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}},$person);
                       }
                   }
                   if (ref($curr{$access}) eq 'ARRAY') {
                       my @diffs = &Apache::loncommon::compare_arrays($helphash{'helpsettings'}{'adhoc'}{$rolename}{$access},$curr{$access});
                       if (@diffs) {
                           $changes{'customrole'}{$rolename}{$access} = 1;
                       }
                   } elsif (@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}}) {
                       $changes{'customrole'}{$rolename}{$access} = 1;
                   }
                   foreach my $person (@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}}) {
                       my ($uname,$udom) = split(/:/,$person);
                           push(@newspecstaff,&Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$udom,'lastname'),$uname,$udom));
                   }
                   $newsettings{$rolename}{$access} = join(', ',sort(@newspecstaff));
               }
           } else {
               $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'}= 'all';
           }
           unless ($curr{'access'} eq $access) {
               $changes{'customrole'}{$rolename}{'access'} = 1;
               $newsettings{$rolename}{'access'} = $lt{$helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'}};
           }
       }
       if (@allpos > 0) {
           my $idx = 0;
           foreach my $rolename (@allpos) {
               if ($rolename ne '') {
                   $helphash{'helpsettings'}{'adhoc'}{$rolename}{'order'} = $idx;
                   if (ref($current{'adhoc'}) eq 'HASH') {
                       if (ref($current{'adhoc'}{$rolename}) eq 'HASH') {
                           if ($current{'adhoc'}{$rolename}{'order'} ne $idx) {
                               $changes{'customrole'}{$rolename}{'order'} = 1;
                               $newsettings{$rolename}{'order'} = $idx+1;
                           }
                       }
                   }
                   $idx ++;
             }              }
         }          }
     }      }
Line 9858  sub modify_helpsettings { Line 12849  sub modify_helpsettings {
     if (keys(%changes) > 0) {      if (keys(%changes) > 0) {
         $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom);          $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom);
         if ($putresult eq 'ok') {          if ($putresult eq 'ok') {
             $resulttext = &mt('Changes made:').'<ul>';              if (ref($helphash{'helpsettings'}) eq 'HASH') {
                   $domdefaults{'submitbugs'} = $helphash{'helpsettings'}{'submitbugs'};
                   if (ref($helphash{'helpsettings'}{'adhoc'}) eq 'HASH') {
                       $domdefaults{'adhocroles'} = $helphash{'helpsettings'}{'adhoc'};
                   }
               }
               my $cachetime = 24*60*60;
               &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
               }
           } else {
               $errors .= '<li><span class="LC_error">'.
                          &mt('An error occurred storing the settings: [_1]',
                              $putresult).'</span></li>';
           }
       }
       if ((keys(%changes) && ($putresult eq 'ok')) || (keys(%changedprivs))) {
           $resulttext = &mt('Changes made:').'<ul>';
           my (%shownprivs,@levelorder);
           @levelorder = ('c','d','s');
           if ((keys(%changes)) && ($putresult eq 'ok')) {
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
                 if ($item eq 'submitbugs') {                  if ($item eq 'submitbugs') {
                     $resulttext .= '<li>'.&mt('Display link to: [_1] set to "'.$offon[$env{'form.'.$item}].'".',                      $resulttext .= '<li>'.&mt('Display link to: [_1] set to "'.$offon[$env{'form.'.$item}].'".',
                                               &Apache::loncommon::modal_link('http://bugs.loncapa.org',                                                &Apache::loncommon::modal_link('http://bugs.loncapa.org',
                                               &mt('LON-CAPA bug tracker'),600,500)).'</li>';                                                &mt('LON-CAPA bug tracker'),600,500)).'</li>';
                   } elsif ($item eq 'customrole') {
                       if (ref($changes{'customrole'}) eq 'HASH') {
                           my @keyorder = ('order','desc','access','status','exc','inc');
                           my %keytext = &Apache::lonlocal::texthash(
                                                                      order  => 'Order',
                                                                      desc   => 'Role description',
                                                                      access => 'Role usage',
                                                                      status => 'Allowed instituional types',
                                                                      exc    => 'Allowed personnel',
                                                                      inc    => 'Disallowed personnel',
                           );
                           foreach my $role (sort(keys(%{$changes{'customrole'}}))) {
                               if (ref($changes{'customrole'}{$role}) eq 'HASH') {
                                   if ($role eq $newrole) {
                                       $resulttext .= '<li>'.&mt('New custom role added: [_1]',
                                                                 $role).'<ul>';
                                   } else {
                                       $resulttext .= '<li>'.&mt('Existing custom role modified: [_1]',
                                                                 $role).'<ul>';
                                   }
                                   foreach my $key (@keyorder) {
                                       if ($changes{'customrole'}{$role}{$key}) {
                                           $resulttext .= '<li>'.&mt("[_1] set to: [_2]",
                                                                     $keytext{$key},$newsettings{$role}{$key}).
                                                          '</li>';
                                       }
                                   }
                                   if (ref($changedprivs{$role}) eq 'HASH') {
                                       $shownprivs{$role} = 1;
                                       $resulttext .= '<li>'.&mt('Privileges set to :').'<ul>';
                                       foreach my $level (@levelorder) {
                                           foreach my $item (split(/\:/,$changedprivs{$role}{$level})) {
                                               next if ($item eq '');
                                               my ($priv) = split(/\&/,$item,2);
                                               if (&Apache::lonnet::plaintext($priv)) {
                                                   $resulttext .= '<li>'.&Apache::lonnet::plaintext($priv);
                                                   unless ($level eq 'c') {
                                                       $resulttext .= ' ('.$lt{$level}.')';
                                                   }
                                                   $resulttext .= '</li>';
                                               }
                                           }
                                       }
                                       $resulttext .= '</ul>';
                                   }
                                   $resulttext .= '</ul></li>';
                               }
                           }
                       }
                   }
               }
           }
           if (keys(%changedprivs)) {
               foreach my $role (sort(keys(%changedprivs))) {
                   unless ($shownprivs{$role}) {
                       $resulttext .= '<li>'.&mt('Existing custom role modified: [_1]',
                                                 $role).'<ul>'.
                                      '<li>'.&mt('Privileges set to :').'<ul>';
                       foreach my $level (@levelorder) {
                           foreach my $item (split(/\:/,$changedprivs{$role}{$level})) {
                               next if ($item eq '');
                               my ($priv) = split(/\&/,$item,2);
                               if (&Apache::lonnet::plaintext($priv)) {
                                   $resulttext .= '<li>'.&Apache::lonnet::plaintext($priv);
                                   unless ($level eq 'c') {
                                       $resulttext .= ' ('.$lt{$level}.')';
                                   }
                                   $resulttext .= '</li>';
                               }
                           }
                       }
                       $resulttext .= '</ul></li></ul></li>';
                 }                  }
             }              }
             $resulttext .= '</ul>';  
         } else {  
             $resulttext = &mt('No changes made to help settings');  
             $errors .= '<li><span class="LC_error">'.  
                        &mt('An error occurred storing the settings: [_1]',  
                            $putresult).'</span></li>';  
         }          }
           $resulttext .= '</ul>';
       } else {
           $resulttext = &mt('No changes made to help settings');
     }      }
     if ($errors) {      if ($errors) {
         $resulttext .= '<br />'.&mt('The following errors occurred: ').'<ul>'.          $resulttext .= '<br />'.&mt('The following errors occurred: ').'<ul>'.
                        $errors.'</ul>';                                      $errors.'</ul>';
     }      }
     return $resulttext;      return $resulttext;
 }  }
Line 9884  sub modify_helpsettings { Line 12965  sub modify_helpsettings {
 sub modify_coursedefaults {  sub modify_coursedefaults {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,$errors,%changes,%defaultshash);      my ($resulttext,$errors,%changes,%defaultshash);
     my %defaultchecked = ('canuse_pdfforms' => 'off');      my %defaultchecked = (
     my @toggles = ('canuse_pdfforms');                             'canuse_pdfforms' => 'off',
                              'uselcmath'       => 'on',
                              'usejsme'         => 'on'
                            );
       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');                     'uploadquota_community','uploadquota_textbook','uploadquota_placement',
     my @types = ('official','unofficial','community','textbook');                     'mysqltables_official','mysqltables_unofficial','mysqltables_community',
                      'mysqltables_textbook','mysqltables_placement');
       my @types = ('official','unofficial','community','textbook','placement');
     my %staticdefaults = (      my %staticdefaults = (
                            anonsurvey_threshold => 10,                             anonsurvey_threshold => 10,
                            uploadquota          => 500,                             uploadquota          => 500,
                              postsubmit           => 60,
                              mysqltables          => 172800,
                          );                           );
   
     $defaultshash{'coursedefaults'} = {};      $defaultshash{'coursedefaults'} = {};
Line 9932  sub modify_coursedefaults { Line 13021  sub modify_coursedefaults {
                 }                  }
                 $defaultshash{'coursedefaults'}{$item} = $newdef;                  $defaultshash{'coursedefaults'}{$item} = $newdef;
             } else {              } else {
                 my ($type) = ($item =~ /^\Quploadquota_\E(\w+)$/);                  my ($setting,$type) = ($item =~ /^(uploadquota|mysqltables)_(\w+)$/);
                 if (ref($domconfig{'coursedefaults'}{'uploadquota'}) eq 'HASH') {                  if (ref($domconfig{'coursedefaults'}{$setting}) eq 'HASH') {
                     $currdef = $domconfig{'coursedefaults'}{'uploadquota'}{$type};                      $currdef = $domconfig{'coursedefaults'}{$setting}{$type};
                 }                  }
                 $newdef =~ s/[^\w.\-]//g;                  $newdef =~ s/[^\w.\-]//g;
                 $defaultshash{'coursedefaults'}{'uploadquota'}{$type} = $newdef;                  $defaultshash{'coursedefaults'}{$setting}{$type} = $newdef;
             }              }
             if ($currdef ne $newdef) {              if ($currdef ne $newdef) {
                 my $staticdef;                  my $staticdef;
Line 9945  sub modify_coursedefaults { Line 13034  sub modify_coursedefaults {
                     unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) {                      unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) {
                         $changes{$item} = 1;                          $changes{$item} = 1;
                     }                      }
                 } else {                  } elsif ($item =~ /^(uploadquota|mysqltables)_/) {
                     unless (($currdef eq '') && ($newdef == $staticdefaults{'uploadquota'})) {                      my $setting = $1;
                         $changes{'uploadquota'} = 1;                      unless (($currdef eq '') && ($newdef == $staticdefaults{$setting})) {
                           $changes{$setting} = 1;
                     }                      }
                 }                  }
             }              }
         }          }
           my $currclone = $domconfig{'coursedefaults'}{'canclone'};
         my $officialcreds = $env{'form.official_credits'};          my @currclonecode;
         $officialcreds =~ s/[^\d.]+//g;          if (ref($currclone) eq 'HASH') {
         my $unofficialcreds = $env{'form.unofficial_credits'};              if (ref($currclone->{'instcode'}) eq 'ARRAY') {
         $unofficialcreds =~ s/[^\d.]+//g;                  @currclonecode = @{$currclone->{'instcode'}};
         my $textbookcreds = $env{'form.textbook_credits'};              }
         $textbookcreds =~ s/[^\d.]+//g;          }
         if (ref($domconfig{'coursedefaults'}{'coursecredits'} ne 'HASH') &&          my $newclone;
                 ($env{'form.coursecredits'} eq '1')) {          if ($env{'form.canclone'} =~ /^(none|domain|instcode)$/) {
                 $changes{'coursecredits'} = 1;              $newclone = $env{'form.canclone'};
           }
           if ($newclone eq 'instcode') {
               my @newcodes = &Apache::loncommon::get_env_multiple('form.clonecode');
               my (%codedefaults,@code_order,@clonecode);
               &Apache::lonnet::auto_instcode_defaults($dom,\%codedefaults,
                                                       \@code_order);
               foreach my $item (@code_order) {
                   if (grep(/^\Q$item\E$/,@newcodes)) {
                       push(@clonecode,$item);
                   }
               }
               if (@clonecode) {
                   $defaultshash{'coursedefaults'}{'canclone'} = { $newclone => \@clonecode };
                   my @diffs = &Apache::loncommon::compare_arrays(\@currclonecode,\@clonecode);
                   if (@diffs) {
                       $changes{'canclone'} = 1;
                   }
               } else {
                   $newclone eq '';
               }
           } elsif ($newclone ne '') {
               $defaultshash{'coursedefaults'}{'canclone'} = $newclone;
           }
           if ($newclone ne $currclone) {
               $changes{'canclone'} = 1;
           }
           my %credits;
           foreach my $type (@types) {
               unless ($type eq 'community') {
                   $credits{$type} = $env{'form.'.$type.'_credits'};
                   $credits{$type} =~ s/[^\d.]+//g;
               }
           }
           if ((ref($domconfig{'coursedefaults'}{'coursecredits'}) ne 'HASH') &&
               ($env{'form.coursecredits'} eq '1')) {
               $changes{'coursecredits'} = 1;
               foreach my $type (keys(%credits)) {
                   $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type};
               }
         } else {          } else {
             if (($domconfig{'coursedefaults'}{'coursecredits'}{'official'} ne $officialcreds)  ||              if ($env{'form.coursecredits'} eq '1') {
                 ($domconfig{'coursedefaults'}{'coursecredits'}{'unofficial'} ne $unofficialcreds) ||                  foreach my $type (@types) {
                 ($domconfig{'coursedefaults'}{'coursecredits'}{'textbook'} ne $textbookcreds)) {                      unless ($type eq 'community') {
                 $changes{'coursecredits'} = 1;                          if ($domconfig{'coursedefaults'}{'coursecredits'}{$type} ne $credits{$type}) {
                               $changes{'coursecredits'} = 1;
                           }
                           $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type};
                       }
                   }
               } elsif (ref($domconfig{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
                   foreach my $type (@types) {
                       unless ($type eq 'community') {
                           if ($domconfig{'coursedefaults'}{'coursecredits'}{$type}) {
                               $changes{'coursecredits'} = 1;
                               last;
                           }
                       }
                   }
             }              }
         }          }
         $defaultshash{'coursedefaults'}{'coursecredits'} = {          if ($env{'form.postsubmit'} eq '1') {
             official   => $officialcreds,              $defaultshash{'coursedefaults'}{'postsubmit'}{'client'} = 'on';
             unofficial => $unofficialcreds,              my %currtimeout;
             textbook   => $textbookcreds,              if (ref($domconfig{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
                   if ($domconfig{'coursedefaults'}{'postsubmit'}{'client'} eq 'off') {
                       $changes{'postsubmit'} = 1;
                   }
                   if (ref($domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {
                       %currtimeout = %{$domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}};
                   }
               } else {
                   $changes{'postsubmit'} = 1;
               }
               foreach my $type (@types) {
                   my $timeout = $env{'form.'.$type.'_timeout'};
                   $timeout =~ s/\D//g;
                   if ($timeout == $staticdefaults{'postsubmit'}) {
                       $timeout = '';
                   } elsif (($timeout eq '') || ($timeout =~ /^0+$/)) {
                       $timeout = '0';
                   }
                   unless ($timeout eq '') {
                       $defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}{$type} = $timeout;
                   }
                   if (exists($currtimeout{$type})) {
                       if ($timeout ne $currtimeout{$type}) {
                           $changes{'postsubmit'} = 1;
                       }
                   } elsif ($timeout ne '') {
                       $changes{'postsubmit'} = 1;
                   }
               }
           } else {
               $defaultshash{'coursedefaults'}{'postsubmit'}{'client'} = 'off';
               if (ref($domconfig{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
                   if ($domconfig{'coursedefaults'}{'postsubmit'}{'client'} eq 'on') {
                       $changes{'postsubmit'} = 1;
                   }
               } else {
                   $changes{'postsubmit'} = 1;
               }
         }          }
     }      }
     my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
Line 9980  sub modify_coursedefaults { Line 13160  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{'canuse_pdfforms'}) || ($changes{'coursecredits'}) ||               if (($changes{'canuse_pdfforms'}) || ($changes{'uploadquota'}) || ($changes{'postsubmit'}) ||
                 ($changes{'uploadquota'})) {                   ($changes{'coursecredits'}) || ($changes{'uselcmath'}) || ($changes{'usejsme'}) ||
                 if ($changes{'canuse_pdfforms'}) {                  ($changes{'canclone'}) || ($changes{'mysqltables'})) {
                     $domdefaults{'canuse_pdfforms'}=$defaultshash{'coursedefaults'}{'canuse_pdfforms'};                  foreach my $item ('canuse_pdfforms','uselcmath','usejsme') { 
                       if ($changes{$item}) {
                           $domdefaults{$item}=$defaultshash{'coursedefaults'}{$item};
                       }
                 }                  }
                 if ($changes{'coursecredits'}) {                  if ($changes{'coursecredits'}) {
                     if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {                      if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
                         $domdefaults{'officialcredits'} =                          foreach my $type (keys(%{$defaultshash{'coursedefaults'}{'coursecredits'}})) {
                             $defaultshash{'coursedefaults'}{'coursecredits'}{'official'};                              $domdefaults{$type.'credits'} =
                         $domdefaults{'unofficialcredits'} =                                  $defaultshash{'coursedefaults'}{'coursecredits'}{$type};
                             $defaultshash{'coursedefaults'}{'coursecredits'}{'unofficial'};                          }
                         $domdefaults{'textbookcredits'} =                      }
                             $domdefaults{'coursedefaults'}{'coursecredits'}{'textbook'};                  }
                   if ($changes{'postsubmit'}) {
                       if (ref($defaultshash{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
                           $domdefaults{'postsubmit'} = $defaultshash{'coursedefaults'}{'postsubmit'}{'client'};
                           if (ref($defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {
                               foreach my $type (keys(%{$defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}})) {
                                   $domdefaults{$type.'postsubtimeout'} =
                                       $defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}{$type};
                               }
                           }
                     }                      }
                 }                  }
                 if ($changes{'uploadquota'}) {                  if ($changes{'uploadquota'}) {
Line 10002  sub modify_coursedefaults { Line 13194  sub modify_coursedefaults {
                         }                          }
                     }                      }
                 }                  }
                   if ($changes{'canclone'}) {
                       if (ref($defaultshash{'coursedefaults'}{'canclone'}) eq 'HASH') {
                           if (ref($defaultshash{'coursedefaults'}{'canclone'}{'instcode'}) eq 'ARRAY') {
                               my @clonecodes = @{$defaultshash{'coursedefaults'}{'canclone'}{'instcode'}};
                               if (@clonecodes) {
                                   $domdefaults{'canclone'} = join('+',@clonecodes);
                               }
                           }
                       } else {
                           $domdefaults{'canclone'}=$defaultshash{'coursedefaults'}{'canclone'};
                       }
                   }
                 my $cachetime = 24*60*60;                  my $cachetime = 24*60*60;
                 &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);                  &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
                 if (ref($lastactref) eq 'HASH') {                  if (ref($lastactref) eq 'HASH') {
Line 10016  sub modify_coursedefaults { Line 13220  sub modify_coursedefaults {
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('Course/Community users can create/upload PDF forms set to "off"').'</li>';                          $resulttext .= '<li>'.&mt('Course/Community users can create/upload PDF forms set to "off"').'</li>';
                     }                      }
                   } elsif ($item eq 'uselcmath') {
                       if ($env{'form.'.$item} eq '1') {
                           $resulttext .= '<li>'.&mt('Math preview uses LON-CAPA previewer (javascript), if supported by browser.').'</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('Math preview uses DragMath (Java), if supported by client OS.').'</li>';
                       }
                   } elsif ($item eq 'usejsme') {
                       if ($env{'form.'.$item} eq '1') {
                           $resulttext .= '<li>'.&mt('Molecule editor uses JSME (HTML5), if supported by browser.').'</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('Molecule editor uses JME (Java), if supported by client OS.').'</li>';
                       }
                 } elsif ($item eq 'anonsurvey_threshold') {                  } elsif ($item eq 'anonsurvey_threshold') {
                     $resulttext .= '<li>'.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'</li>';                      $resulttext .= '<li>'.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'</li>';
                 } elsif ($item eq 'uploadquota') {                  } elsif ($item eq 'uploadquota') {
Line 10024  sub modify_coursedefaults { Line 13240  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>';
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('Default quota for content uploaded via Course Editor remains default: [_1] MB',$staticdefaults{'uploadquota'}).'</li>';                          $resulttext .= '<li>'.&mt('Default quota for content uploaded via Course Editor remains default: [_1] MB',$staticdefaults{'uploadquota'}).'</li>';
                     }                      }
                   } elsif ($item eq 'mysqltables') {
                       if (ref($defaultshash{'coursedefaults'}{'mysqltables'}) eq 'HASH') {
                           $resulttext .= '<li>'.&mt('Lifetime of "Temporary" MySQL tables (student performance data) on homeserver').'<ul>'.
                                          '<li>'.&mt('Official courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'official'}.'</b>').'</li>'.
                                          '<li>'.&mt('Unofficial courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'unofficial'}.'</b>').'</li>'.
                                          '<li>'.&mt('Textbook courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'textbook'}.'</b>').'</li>'.
                                          '<li>'.&mt('Placement tests: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'placement'}.'</b>').'</li>'.
                                          '<li>'.&mt('Communities: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'community'}.'</b>').'</li>'.
                                          '</ul>'.
                                          '</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('Lifetime of "Temporary" MySQL tables (student performance data) on homeserver remains default: [_1] s',$staticdefaults{'uploadquota'}).'</li>';
                       }
                   } elsif ($item eq 'postsubmit') {
                       if ($domdefaults{'postsubmit'} eq 'off') {
                           $resulttext .= '<li>'.&mt('Submit button(s) remain enabled on page after student makes submission.');
                       } else {
                           $resulttext .= '<li>'.&mt('Submit button(s) disabled on page after student makes submission').'; ';
                           if (ref($defaultshash{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
                               $resulttext .= &mt('durations:').'<ul>';
                               foreach my $type (@types) {
                                   $resulttext .= '<li>';
                                   my $timeout;
                                   if (ref($defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {
                                       $timeout = $defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}{$type};
                                   }
                                   my $display;
                                   if ($timeout eq '0') {
                                       $display = &mt('unlimited');
                                   } elsif ($timeout eq '') {
                                       $display = &mt('[quant,_1,second] (default)',$staticdefaults{'postsubmit'});
                                   } else {
                                       $display = &mt('[quant,_1,second]',$timeout);
                                   }
                                   if ($type eq 'community') {
                                       $resulttext .= &mt('Communities');
                                   } elsif ($type eq 'official') {
                                       $resulttext .= &mt('Official courses');
                                   } elsif ($type eq 'unofficial') {
                                       $resulttext .= &mt('Unofficial courses');
                                   } elsif ($type eq 'textbook') {
                                       $resulttext .= &mt('Textbook courses');
                                   } elsif ($type eq 'placement') {
                                       $resulttext .= &mt('Placement tests');
                                   }
                                   $resulttext .= ' -- '.$display.'</li>';
                               }
                               $resulttext .= '</ul>';
                           }
                           $resulttext .= '</li>';
                       }
                 } elsif ($item eq 'coursecredits') {                  } elsif ($item eq 'coursecredits') {
                     if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {                      if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
                         if (($domdefaults{'officialcredits'} eq '') &&                          if (($domdefaults{'officialcredits'} eq '') &&
Line 10048  sub modify_coursedefaults { Line 13315  sub modify_coursedefaults {
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('Student credits not in use for courses in this domain').'</li>';                          $resulttext .= '<li>'.&mt('Student credits not in use for courses in this domain').'</li>';
                     }                      }
                   } elsif ($item eq 'canclone') {
                       if (ref($defaultshash{'coursedefaults'}{'canclone'}) eq 'HASH') {
                           if (ref($defaultshash{'coursedefaults'}{'canclone'}{'instcode'}) eq 'ARRAY') {
                               my $clonecodes = join(' '.&mt('and').' ',@{$defaultshash{'coursedefaults'}{'canclone'}{'instcode'}});
                               $resulttext .= '<li>'.&mt('By default, official courses can be cloned from existing courses with the same: [_1]','<b>'.$clonecodes.'</b>').'</li>';
                           }
                       } elsif ($defaultshash{'coursedefaults'}{'canclone'} eq 'domain') {
                           $resulttext .= '<li>'.&mt('By default, a course requester can clone any course from his/her domain.').'</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('By default, only course owner and coordinators may clone a course.').'</li>';
                       }
                 }                  }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
Line 10064  sub modify_coursedefaults { Line 13342  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 10311  sub modify_usersessions { Line 13589  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 10466  sub modify_usersessions { Line 13744  sub modify_usersessions {
             $changes{'spares'}{$lonhost} = \%spareschg;              $changes{'spares'}{$lonhost} = \%spareschg;
         }          }
     }      }
       $defaultshash{'usersessions'}{'offloadnow'} = {};
       my @offloadnow = &Apache::loncommon::get_env_multiple('form.offloadnow');
       my @okoffload;
       if (@offloadnow) {
           foreach my $server (@offloadnow) {
               if (&Apache::lonnet::hostname($server) ne '') {
                   unless (grep(/^\Q$server\E$/,@okoffload)) {
                       push(@okoffload,$server);
                   }
               }
           }
           if (@okoffload) {
               foreach my $lonhost (@okoffload) {
                   $defaultshash{'usersessions'}{'offloadnow'}{$lonhost} = 1;
               }
           }
       }
     if (ref($domconfig{'usersessions'}) eq 'HASH') {      if (ref($domconfig{'usersessions'}) eq 'HASH') {
         if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') {          if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') {
             if (ref($changes{'spares'}) eq 'HASH') {              if (ref($changes{'spares'}) eq 'HASH') {
Line 10477  sub modify_usersessions { Line 13771  sub modify_usersessions {
         } else {          } else {
             $savespares = 1;              $savespares = 1;
         }          }
           if (ref($domconfig{'usersessions'}{'offloadnow'}) eq 'HASH') {
               foreach my $lonhost (keys(%{$domconfig{'usersessions'}{'offloadnow'}})) {
                   unless ($defaultshash{'usersessions'}{'offloadnow'}{$lonhost}) {
                       $changes{'offloadnow'} = 1;
                       last;
                   }
               }
               unless ($changes{'offloadnow'}) {
                   foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{'offloadnow'}})) {
                       unless ($domconfig{'usersessions'}{'offloadnow'}{$lonhost}) {
                           $changes{'offloadnow'} = 1;
                           last;
                       }
                   }
               }
           } elsif (@okoffload) {
               $changes{'offloadnow'} = 1;
           }
       } elsif (@okoffload) {
           $changes{'offloadnow'} = 1;
     }      }
   
     my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');      my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');
     if ((keys(%changes) > 0) || ($savespares)) {      if ((keys(%changes) > 0) || ($savespares)) {
         my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,          my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
Line 10491  sub modify_usersessions { Line 13804  sub modify_usersessions {
                 if (ref($defaultshash{'usersessions'}{'hosted'}) eq 'HASH') {                  if (ref($defaultshash{'usersessions'}{'hosted'}) eq 'HASH') {
                     $domdefaults{'hostedsessions'} = $defaultshash{'usersessions'}{'hosted'};                      $domdefaults{'hostedsessions'} = $defaultshash{'usersessions'}{'hosted'};
                 }                  }
                   if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
                       $domdefaults{'offloadnow'} = $defaultshash{'usersessions'}{'offloadnow'};
                   }
             }              }
             my $cachetime = 24*60*60;              my $cachetime = 24*60*60;
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);              &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               &Apache::lonnet::do_cache_new('usersessions',$dom,$defaultshash{'usersessions'},3600);
             if (ref($lastactref) eq 'HASH') {              if (ref($lastactref) eq 'HASH') {
                 $lastactref->{'domdefaults'} = 1;                  $lastactref->{'domdefaults'} = 1;
                   $lastactref->{'usersessions'} = 1;
             }              }
             if (keys(%changes) > 0) {              if (keys(%changes) > 0) {
                 my %lt = &usersession_titles();                  my %lt = &usersession_titles();
Line 10559  sub modify_usersessions { Line 13877  sub modify_usersessions {
                         $resulttext .= '</ul>';                          $resulttext .= '</ul>';
                     }                      }
                 }                  }
                   if ($changes{'offloadnow'}) {
                       if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
                           if (keys(%{$defaultshash{'usersessions'}{'offloadnow'}}) > 0) {
                               $resulttext .= '<li>'.&mt('Switch active users on next access, for server(s):').'<ul>';
                               foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadnow'}}))) {
                                   $resulttext .= '<li>'.$lonhost.'</li>';
                               }
                               $resulttext .= '</ul>';
                           } else {
                               $resulttext .= '<li>'.&mt('No servers now set to switch active users on next access.');
                           }
                       } else {
                           $resulttext .= '<li>'.&mt('No servers now set to switch active users on next access.').'</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_ssl {
       my ($dom,$lastactref,%domconfig) = @_;
       my (%by_ip,%by_location,@intdoms,@instdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
       my @locations = sort(keys(%by_location));
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my (%defaultshash,%changes);
       my $action = 'ssl';
       my @prefixes = ('connto','connfrom','replication');
       foreach my $prefix (@prefixes) {
           $defaultshash{$action}{$prefix} = {};
       }
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
       my $resulttext;
       my %iphost = &Apache::lonnet::get_iphost();
       my @reptypes = ('certreq','nocertreq');
       my @connecttypes = ('dom','intdom','other');
       my %types = (
                     connto      => \@connecttypes,
                     connfrom    => \@connecttypes,
                     replication => \@reptypes,
                   );
       foreach my $prefix (sort(keys(%types))) {
           foreach my $type (@{$types{$prefix}}) {
               if (($prefix eq 'connto') || ($prefix eq 'connfrom')) {
                   my $value = 'yes';
                   if ($env{'form.'.$prefix.'_'.$type} =~ /^(no|req)$/) {
                       $value = $env{'form.'.$prefix.'_'.$type};
                   }
                   if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
                       if ($domconfig{$action}{$prefix}{$type} ne '') {
                           if ($value ne $domconfig{$action}{$prefix}{$type}) {
                               $changes{$prefix}{$type} = 1;
                           }
                           $defaultshash{$action}{$prefix}{$type} = $value;
                       } else {
                           $defaultshash{$action}{$prefix}{$type} = $value;
                           $changes{$prefix}{$type} = 1;
                       }
                   } else {
                       $defaultshash{$action}{$prefix}{$type} = $value;
                       $changes{$prefix}{$type} = 1;
                   }
                   if (($type eq 'dom') && (keys(%servers) == 1)) {
                       delete($changes{$prefix}{$type});
                   } elsif (($type eq 'intdom') && (@instdoms == 1)) {
                       delete($changes{$prefix}{$type});
                   } elsif (($type eq 'other') && (keys(%by_location) == 0)) { 
                       delete($changes{$prefix}{$type});
                   }
               } elsif ($prefix eq 'replication') {
                   if (@locations > 0) {
                       my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
                       my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
                       my @okvals;
                       foreach my $val (@vals) {
                           if ($val =~ /:/) {
                               my @items = split(/:/,$val);
                               foreach my $item (@items) {
                                   if (ref($by_location{$item}) eq 'ARRAY') {
                                       push(@okvals,$item);
                                   }
                               }
                           } 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;
                           }
                       }
                   }
               }
           }
       }
       my $nochgmsg = &mt('No changes made to LON-CAPA SSL settings');
       if (keys(%changes) > 0) {
           my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                                    $dom);
           if ($putresult eq 'ok') {
               if (ref($defaultshash{$action}) eq 'HASH') {
                   if (ref($defaultshash{$action}{'replication'}) eq 'HASH') {
                       $domdefaults{'replication'} = $defaultshash{$action}{'replication'};
                   }
                   if (ref($defaultshash{$action}{'connto'}) eq 'HASH') {
                       $domdefaults{'connto'} = $domconfig{$action}{'connto'};
                   }
                   if (ref($defaultshash{$action}{'connfrom'}) eq 'HASH') {
                       $domdefaults{'connfrom'} = $domconfig{$action}{'connfrom'};
                   }
               }
               my $cachetime = 24*60*60;
               &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
               }
               if (keys(%changes) > 0) {
                   my %titles = &ssl_titles();
                   $resulttext = &mt('Changes made:').'<ul>';
                   foreach my $prefix (@prefixes) {
                       if (ref($changes{$prefix}) eq 'HASH') {
                           $resulttext .= '<li>'.$titles{$prefix}.'<ul>';
                           foreach my $type (@{$types{$prefix}}) {
                               if (defined($changes{$prefix}{$type})) {
                                   my $newvalue;
                                   if (ref($defaultshash{$action}) eq 'HASH') {
                                       if (ref($defaultshash{$action}{$prefix})) {
                                           if (($prefix eq 'connto') || ($prefix eq 'connfrom')) {
                                               $newvalue = $titles{$defaultshash{$action}{$prefix}{$type}};
                                           } elsif (ref($defaultshash{$action}{$prefix}{$type}) eq 'ARRAY') {
                                               if (@{$defaultshash{$action}{$prefix}{$type}} > 0) {
                                                   $newvalue = join(', ',@{$defaultshash{$action}{$prefix}{$type}});
                                               }
                                           }
                                       }
                                       if ($newvalue eq '') {
                                           $resulttext .= '<li>'.&mt('[_1] set to: none',$titles{$type}).'</li>';
                                       } else {
                                           $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$titles{$type},$newvalue).'</li>';
                                       }
                                   }
                               }
                           }
                           $resulttext .= '</ul>';
                       }
                   }
               } else {
                   $resulttext = $nochgmsg;
               }
           } else {
               $resulttext = '<span class="LC_error">'.
                             &mt('An error occurred: [_1]',$putresult).'</span>';
           }
       } else {
           $resulttext = $nochgmsg;
       }
       return $resulttext;
   }
   
   sub modify_trust {
       my ($dom,$lastactref,%domconfig) = @_;
       my (%by_ip,%by_location,@intdoms,@instdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
       my @locations = sort(keys(%by_location));
       my @prefixes = qw(content shared enroll othcoau coaurem domroles catalog reqcrs msg);
       my @types = ('exc','inc');
       my (%defaultshash,%changes);
       foreach my $prefix (@prefixes) {
           $defaultshash{'trust'}{$prefix} = {};
       }
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
       my $resulttext;
       foreach my $prefix (@prefixes) {
           foreach my $type (@types) {
               my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
               my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
               my @okvals;
               foreach my $val (@vals) {
                   if ($val =~ /:/) {
                       my @items = split(/:/,$val);
                       foreach my $item (@items) {
                           if (ref($by_location{$item}) eq 'ARRAY') {
                               push(@okvals,$item);
                           }
                       }
                   } else {
                       if (ref($by_location{$val}) eq 'ARRAY') {
                           push(@okvals,$val);
                       }
                   }
               }
               @okvals = sort(@okvals);
               if (ref($domconfig{'trust'}) eq 'HASH') {
                   if (ref($domconfig{'trust'}{$prefix}) eq 'HASH') {
                       if (ref($domconfig{'trust'}{$prefix}{$type}) eq 'ARRAY') {
                           if ($inuse == 0) {
                               $changes{$prefix}{$type} = 1;
                           } else {
                               $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                               my @changed = &Apache::loncommon::compare_arrays($domconfig{'trust'}{$prefix}{$type},$defaultshash{'trust'}{$prefix}{$type});
                               if (@changed > 0) {
                                   $changes{$prefix}{$type} = 1;
                               }
                           }
                       } else {
                           if ($inuse == 1) {
                               $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                               $changes{$prefix}{$type} = 1;
                           }
                       }
                   } else {
                       if ($inuse == 1) {
                           $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                           $changes{$prefix}{$type} = 1;
                       }
                   }
               } else {
                   if ($inuse == 1) {
                       $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                       $changes{$prefix}{$type} = 1;
                   }
               }
           }
       }
       my $nochgmsg = &mt('No changes made to trust settings.');
       if (keys(%changes) > 0) {
           my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                                    $dom);
           if ($putresult eq 'ok') {
               if (ref($defaultshash{'trust'}) eq 'HASH') {
                   foreach my $prefix (@prefixes) {
                       if (ref($defaultshash{'trust'}{$prefix}) eq 'HASH') {
                           $domdefaults{'trust'.$prefix} = $defaultshash{'trust'}{$prefix};
                       }
                   }
               }
               my $cachetime = 24*60*60;
               &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
               }
               if (keys(%changes) > 0) {
                   my %lt = &trust_titles();
                   $resulttext = &mt('Changes made:').'<ul>';
                   foreach my $prefix (@prefixes) {
                       if (ref($changes{$prefix}) eq 'HASH') {
                           $resulttext .= '<li>'.$lt{$prefix}.'<ul>';
                           foreach my $type (@types) {
                               if (defined($changes{$prefix}{$type})) {
                                   my $newvalue;
                                   if (ref($defaultshash{'trust'}) eq 'HASH') {
                                       if (ref($defaultshash{'trust'}{$prefix})) {
                                           if (ref($defaultshash{'trust'}{$prefix}{$type}) eq 'ARRAY') {
                                               if (@{$defaultshash{'trust'}{$prefix}{$type}} > 0) {
                                                   $newvalue = join(', ',@{$defaultshash{'trust'}{$prefix}{$type}});
                                               }
                                           }
                                       }
                                   }
                                   if ($newvalue eq '') {
                                       $resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';
                                   } else {
                                       $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';
                                   }
                               }
                           }
                           $resulttext .= '</ul>';
                       }
                   }
                 $resulttext .= '</ul>';                  $resulttext .= '</ul>';
             } else {              } else {
                 $resulttext = $nochgmsg;                  $resulttext = $nochgmsg;
Line 10580  sub modify_loadbalancing { Line 14205  sub modify_loadbalancing {
     my ($othertitle,$usertypes,$types) =      my ($othertitle,$usertypes,$types) =
         &Apache::loncommon::sorted_inst_types($dom);          &Apache::loncommon::sorted_inst_types($dom);
     my %servers = &Apache::lonnet::internet_dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my %libraryservers = &Apache::lonnet::get_servers($dom,'library');
     my @sparestypes = ('primary','default');      my @sparestypes = ('primary','default');
     my %typetitles = &sparestype_titles();      my %typetitles = &sparestype_titles();
     my $resulttext;      my $resulttext;
Line 10632  sub modify_loadbalancing { Line 14258  sub modify_loadbalancing {
                         push(@offloadto,$target);                          push(@offloadto,$target);
                     }                      }
                 }                  }
                 $defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto;  
             }              }
               if ($env{'form.loadbalancing_target_'.$i.'_hosthere'} eq $sparetype) {
                   unless(grep(/^\Q$balancer\E$/,@offloadto)) {
                       push(@offloadto,$balancer);
                   }
               }
               $defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto;
         }          }
         if (ref($currtargets{$balancer}) eq 'HASH') {          if (ref($currtargets{$balancer}) eq 'HASH') {
             foreach my $sparetype (@sparestypes) {              foreach my $sparetype (@sparestypes) {
Line 10671  sub modify_loadbalancing { Line 14302  sub modify_loadbalancing {
                     $rule = $env{'form.loadbalancing_rules_'.$i.'_'.$type};                      $rule = $env{'form.loadbalancing_rules_'.$i.'_'.$type};
                 }                  }
                 if ($rule eq 'specific') {                  if ($rule eq 'specific') {
                     $rule = $env{'form.loadbalancing_singleserver_'.$i.'_'.$type};                      my $specifiedhost = $env{'form.loadbalancing_singleserver_'.$i.'_'.$type};
                       if (exists($servers{$specifiedhost})) {
                           $rule = $specifiedhost;
                       }
                 }                  }
                 $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type} = $rule;                  $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type} = $rule;
                 if (ref($currrules{$balancer}) eq 'HASH') {                  if (ref($currrules{$balancer}) eq 'HASH') {
Line 10693  sub modify_loadbalancing { Line 14327  sub modify_loadbalancing {
                                                  \%defaultshash,$dom);                                                   \%defaultshash,$dom);
         if ($putresult eq 'ok') {          if ($putresult eq 'ok') {
             if (keys(%changes) > 0) {              if (keys(%changes) > 0) {
                   my %toupdate;
                 if (ref($changes{'delete'}) eq 'ARRAY') {                  if (ref($changes{'delete'}) eq 'ARRAY') {
                     foreach my $balancer (sort(@{$changes{'delete'}})) {                      foreach my $balancer (sort(@{$changes{'delete'}})) {
                         $resulttext .= '<li>'.&mt('Load Balancing discontinued for: [_1]',$balancer).'</li>';                          $resulttext .= '<li>'.&mt('Load Balancing discontinued for: [_1]',$balancer).'</li>';
                         my $cachekey = &escape('loadbalancing').':'.&escape($dom);                          $toupdate{$balancer} = 1;
                         &Apache::lonnet::remote_devalidate_cache($balancer,[$cachekey]);  
                     }                      }
                 }                  }
                 if (ref($changes{'add'}) eq 'ARRAY') {                  if (ref($changes{'add'}) eq 'ARRAY') {
                     foreach my $balancer (sort(@{$changes{'add'}})) {                      foreach my $balancer (sort(@{$changes{'add'}})) {
                         $resulttext .= '<li>'.&mt('Load Balancing enabled for: [_1]',$balancer);                          $resulttext .= '<li>'.&mt('Load Balancing enabled for: [_1]',$balancer);
                           $toupdate{$balancer} = 1;
                     }                      }
                 }                  }
                 if (ref($changes{'curr'}) eq 'HASH') {                  if (ref($changes{'curr'}) eq 'HASH') {
                     foreach my $balancer (sort(keys(%{$changes{'curr'}}))) {                      foreach my $balancer (sort(keys(%{$changes{'curr'}}))) {
                           $toupdate{$balancer} = 1;
                         if (ref($changes{'curr'}{$balancer}) eq 'HASH') {                          if (ref($changes{'curr'}{$balancer}) eq 'HASH') {
                             if ($changes{'curr'}{$balancer}{'targets'}) {                              if ($changes{'curr'}{$balancer}{'targets'}) {
                                 my %offloadstr;                                  my %offloadstr;
Line 10743  sub modify_loadbalancing { Line 14379  sub modify_loadbalancing {
                                         if ($rule eq '') {                                          if ($rule eq '') {
                                             $balancetext =  $ruletitles{'default'};                                              $balancetext =  $ruletitles{'default'};
                                         } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer') ||                                          } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer') ||
                                                  ($rule eq 'balancer') || ($rule eq 'offloadedto')) {                                                   ($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) {
                                             $balancetext =  $ruletitles{$rule};                                              if (($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) {
                                                   foreach my $sparetype (@sparestypes) {
                                                       if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
                                                           map { $toupdate{$_} = 1; } (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}});
                                                       }
                                                   }
                                                   foreach my $item (@{$alltypes}) {
                                                       next if ($item =~  /^_LC_ipchange/);
                                                       my $hasrule = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$item};
                                                       if ($hasrule eq 'homeserver') {
                                                           map { $toupdate{$_} = 1; } (keys(%libraryservers));
                                                       } else {
                                                           unless (($hasrule eq 'default') || ($hasrule eq 'none') || ($hasrule eq 'externalbalancer')) {
                                                               if ($servers{$hasrule}) {
                                                                   $toupdate{$hasrule} = 1;
                                                               }
                                                           }
                                                       }
                                                   }
                                                   if (($rule eq 'balancer') || ($rule eq 'offloadedto')) {
                                                       $balancetext =  $ruletitles{$rule};
                                                   } else {
                                                       my $receiver = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type};
                                                       $balancetext = $ruletitles{'particular'}.' '.$receiver;
                                                       if ($receiver) {
                                                           $toupdate{$receiver};
                                                       }
                                                   }
                                               } else {
                                                   $balancetext =  $ruletitles{$rule};
                                               }
                                         } else {                                          } else {
                                             $balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type});                                              $balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type});
                                         }                                          }
Line 10753  sub modify_loadbalancing { Line 14419  sub modify_loadbalancing {
                                 }                                  }
                             }                              }
                         }                          }
                         my $cachekey = &escape('loadbalancing').':'.&escape($dom);                          if (keys(%toupdate)) {
                         &Apache::lonnet::remote_devalidate_cache($balancer,[$cachekey]);                              my %thismachine;
                               my $updatedhere;
                               my $cachetime = 60*60*24;
                               map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
                               foreach my $lonhost (keys(%toupdate)) {
                                   if ($thismachine{$lonhost}) {
                                       unless ($updatedhere) {
                                           &Apache::lonnet::do_cache_new('loadbalancing',$dom,
                                                                         $defaultshash{'loadbalancing'},
                                                                         $cachetime);
                                           $updatedhere = 1;
                                       }
                                   } else {
                                       my $cachekey = &escape('loadbalancing').':'.&escape($dom);
                                       &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
                                   }
                               }
                           }
                     }                      }
                 }                  }
                 if ($resulttext ne '') {                  if ($resulttext ne '') {
Line 10815  sub recurse_cat_deletes { Line 14498  sub recurse_cat_deletes {
     return;      return;
 }  }
   
 sub get_active_dcs {  
     my ($dom) = @_;  
     my $now = time;  
     my %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc'],$now,$now);  
     my %domcoords;  
     my $numdcs = 0;  
     foreach my $server (keys(%dompersonnel)) {  
         foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {  
             my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user);  
             $domcoords{$uname.':'.$udom} = $dompersonnel{$server}{$user};  
         }  
     }  
     return %domcoords;  
 }  
   
 sub active_dc_picker {  sub active_dc_picker {
     my ($dom,$numinrow,$inputtype,$name,%currhash) = @_;      my ($dom,$numinrow,$inputtype,$name,%currhash) = @_;
     my %domcoords = &get_active_dcs($dom);      my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);
     my @domcoord = keys(%domcoords);      my @domcoord = keys(%domcoords);
     if (keys(%currhash)) {      if (keys(%currhash)) {
         foreach my $dc (keys(%currhash)) {          foreach my $dc (keys(%currhash)) {
Line 10895  sub active_dc_picker { Line 14563  sub active_dc_picker {
         my ($dcname,$dcdom) = split(':',$domcoord[0]);          my ($dcname,$dcdom) = split(':',$domcoord[0]);
         my $user = &Apache::loncommon::plainname($dcname,$dcdom);          my $user = &Apache::loncommon::plainname($dcname,$dcdom);
         if ($inputtype eq 'radio') {          if ($inputtype eq 'radio') {
             $table .= '<input type="hidden" name="'.$name.'" value="'.$domcoord[0].'" />'.$user;              $table = '<input type="hidden" name="'.$name.'" value="'.$domcoord[0].'" />'.$user;
             if ($user ne $dcname.':'.$dcdom) {              if ($user ne $dcname.':'.$dcdom) {
                 $table .=  ' ('.$dcname.':'.$dcdom.')';                  $table .=  ' ('.$dcname.':'.$dcdom.')';
             }              }
Line 10904  sub active_dc_picker { Line 14572  sub active_dc_picker {
             if (exists($currhash{$domcoord[0]})) {              if (exists($currhash{$domcoord[0]})) {
                 $check = ' checked="checked"';                  $check = ' checked="checked"';
             }              }
             $table .= '<span class="LC_nobreak"><label>'.              $table = '<span class="LC_nobreak"><label>'.
                       '<input type="checkbox" name="'.$name.'" '.                       '<input type="checkbox" name="'.$name.'" '.
                       'value="'.$domcoord[0].'"'.$check.' />'.$user;                       'value="'.$domcoord[0].'"'.$check.' />'.$user;
             if ($user ne $dcname.':'.$dcdom) {              if ($user ne $dcname.':'.$dcdom) {
                 $table .=  ' ('.$dcname.':'.$dcdom.')';                  $table .=  ' ('.$dcname.':'.$dcdom.')';
             }              }
Line 11396  function updateCaptcha(caller,context) { Line 15064  function updateCaptcha(caller,context) {
     var pubitem;      var pubitem;
     var privtext;      var privtext;
     var pubtext;      var pubtext;
       var versionitem;
       var versiontext;
     if (document.getElementById(context+'_recaptchapub')) {      if (document.getElementById(context+'_recaptchapub')) {
         pubitem = document.getElementById(context+'_recaptchapub');          pubitem = document.getElementById(context+'_recaptchapub');
     } else {      } else {
Line 11416  function updateCaptcha(caller,context) { Line 15086  function updateCaptcha(caller,context) {
     } else {      } else {
         return;          return;
     }      }
       if (document.getElementById(context+'_recaptchaversion')) {
           versionitem = document.getElementById(context+'_recaptchaversion');
       } else {
           return;
       }
       if (document.getElementById(context+'_recaptchavertxt')) {
           versiontext = document.getElementById(context+'_recaptchavertxt');
       } else {
           return;
       }
     if (caller.checked) {      if (caller.checked) {
         if (caller.value == 'recaptcha') {          if (caller.value == 'recaptcha') {
             pubitem.type = 'text';              pubitem.type = 'text';
Line 11424  function updateCaptcha(caller,context) { Line 15104  function updateCaptcha(caller,context) {
             privitem.size = '40';              privitem.size = '40';
             pubtext.innerHTML = "$lt{'pub'}";              pubtext.innerHTML = "$lt{'pub'}";
             privtext.innerHTML = "$lt{'priv'}";              privtext.innerHTML = "$lt{'priv'}";
               versionitem.type = 'text';
               versionitem.size = '3';
               versiontext.innerHTML = "$lt{'ver'}";
         } else {          } else {
             pubitem.type = 'hidden';              pubitem.type = 'hidden';
             privitem.type = 'hidden';              privitem.type = 'hidden';
               versionitem.type = 'hidden';
             pubtext.innerHTML = '';              pubtext.innerHTML = '';
             privtext.innerHTML = '';              privtext.innerHTML = '';
               versiontext.innerHTML = '';
         }          }
     }      }
     return;      return;
Line 11451  function toggleDisplay(domForm,caller) { Line 15136  function toggleDisplay(domForm,caller) {
     if (document.getElementById(caller)) {      if (document.getElementById(caller)) {
         var divitem = document.getElementById(caller);          var divitem = document.getElementById(caller);
         var optionsElement = domForm.coursecredits;          var optionsElement = domForm.coursecredits;
           var checkval = 1;
           var dispval = 'block';
         if (caller == 'emailoptions') {          if (caller == 'emailoptions') {
             optionsElement = domForm.cancreate_email;               optionsElement = domForm.cancreate_email; 
         }          }
           if (caller == 'studentsubmission') {
               optionsElement = domForm.postsubmit;
           }
           if (caller == 'cloneinstcode') {
               optionsElement = domForm.canclone;
               checkval = 'instcode';
           }
         if (optionsElement.length) {          if (optionsElement.length) {
             var currval;              var currval;
             for (var i=0; i<optionsElement.length; i++) {              for (var i=0; i<optionsElement.length; i++) {
Line 11461  function toggleDisplay(domForm,caller) { Line 15155  function toggleDisplay(domForm,caller) {
                    currval = optionsElement[i].value;                     currval = optionsElement[i].value;
                 }                  }
             }              }
             if (currval == 1) {              if (currval == checkval) {
                 divitem.style.display = 'block';                  divitem.style.display = dispval;
             } else {              } else {
                 divitem.style.display = 'none';                  divitem.style.display = 'none';
             }              }
Line 11485  sub captcha_phrases { Line 15179  sub captcha_phrases {
                  original  => 'original (CAPTCHA)',                   original  => 'original (CAPTCHA)',
                  recaptcha => 'successor (ReCAPTCHA)',                   recaptcha => 'successor (ReCAPTCHA)',
                  notused   => 'unused',                   notused   => 'unused',
                    ver => 'ReCAPTCHA version (1 or 2)',
     );      );
 }  }
   
Line 11494  sub devalidate_remote_domconfs { Line 15189  sub devalidate_remote_domconfs {
     my %servers = &Apache::lonnet::internet_dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
     my %thismachine;      my %thismachine;
     map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();      map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
     my @posscached = ('domainconfig','domdefaults');      my @posscached = ('domainconfig','domdefaults','ltitools','usersessions','directorysrch');
     if (keys(%servers) > 1) {      if (keys(%servers)) {
         foreach my $server (keys(%servers)) {          foreach my $server (keys(%servers)) {
             next if ($thismachine{$server});              next if ($thismachine{$server});
             my @cached;              my @cached;

Removed from v.1.241  
changed lines
  Added in v.1.295


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