Diff for /loncom/interface/domainprefs.pm between versions 1.160.6.118.2.12 and 1.284

version 1.160.6.118.2.12, 2023/01/23 17:40:19 version 1.284, 2016/12/05 00:51:53
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 104  $datatable  - HTML containing form eleme Line 103  $datatable  - HTML containing form eleme
   
 In the case of course requests, radio buttons are displayed for each institutional  In the case of course requests, radio buttons are displayed for each institutional
 affiliate type (and also default, and _LC_adv) for each of the course types   affiliate type (and also default, and _LC_adv) for each of the course types 
 (official, unofficial, community, and textbook).  In each case the radio buttons   (official, unofficial, community, textbook, and placement).  
 allow the selection of one of four values:  In each case the radio buttons allow the selection of one of four values:  
   
 0, approval, validate, autolimit=N (where N is blank, or a positive integer).  0, approval, validate, autolimit=N (where N is blank, or a positive integer).
 which have the following effects:  which have the following effects:
Line 170  use Apache::loncoursequeueadmin(); Line 169  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 Net::CIDR;  use Time::HiRes qw( sleep );
   
 my $registered_cleanup;  my $registered_cleanup;
 my $modified_urls;  my $modified_urls;
Line 218  sub handler { Line 218  sub handler {
                 'serverstatuses','requestcourses','helpsettings',                  'serverstatuses','requestcourses','helpsettings',
                 'coursedefaults','usersessions','loadbalancing',                  'coursedefaults','usersessions','loadbalancing',
                 'requestauthor','selfenrollment','inststatus',                  'requestauthor','selfenrollment','inststatus',
                 'passwords','ltitools','ltisec','wafproxy','ipaccess'],$dom);                  'ltitools','ssl','trust'],$dom);
     my %encconfig =      my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
         &Apache::lonnet::get_dom('encconfig',['ltitools','linkprot'],$dom,undef,1);                         'autoupdate','autocreate','directorysrch','contacts',
     if (ref($domconfig{'ltitools'}) eq 'HASH') {                         'usercreation','selfcreation','usermodification','scantron',
         if (ref($encconfig{'ltitools'}) eq 'HASH') {                         'requestcourses','requestauthor','coursecategories',
             foreach my $id (keys(%{$domconfig{'ltitools'}})) {  
                 if (ref($domconfig{'ltitools'}{$id}) eq 'HASH') {  
                     foreach my $item ('key','secret') {  
                         $domconfig{'ltitools'}{$id}{$item} = $encconfig{'ltitools'}{$id}{$item};  
                     }  
                 }  
             }  
         }  
     }  
     if (ref($domconfig{'ltisec'}) eq 'HASH') {  
         if (ref($domconfig{'ltisec'}{'linkprot'}) eq 'HASH') {  
             if (ref($encconfig{'linkprot'}) eq 'HASH') {  
                 foreach my $id (keys(%{$domconfig{'ltisec'}{'linkprot'}})) {  
                     unless ($id =~ /^\d+$/) {  
                         delete($domconfig{'ltisec'}{'linkprot'}{$id});  
                     }  
                     if ((ref($domconfig{'ltisec'}{'linkprot'}{$id}) eq 'HASH') &&  
                         (ref($encconfig{'linkprot'}{$id}) eq 'HASH')) {  
                         foreach my $item ('key','secret') {  
                             $domconfig{'ltisec'}{'linkprot'}{$id}{$item} = $encconfig{'linkprot'}{$id}{$item};  
                         }  
                     }  
                 }  
             }  
         }  
     }  
     my @prefs_order = ('rolecolors','login','ipaccess','defaults','wafproxy','passwords',  
                        'quotas','autoenroll','autoupdate','autocreate','directorysrch',  
                        'contacts','usercreation','selfcreation','usermodification',  
                        'scantron','requestcourses','requestauthor','coursecategories',  
                        'serverstatuses','helpsettings','coursedefaults',                         'serverstatuses','helpsettings','coursedefaults',
                        'ltitools','selfenrollment','usersessions','lti');                         '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 285  sub handler { Line 255  sub handler {
                                  {col1 => 'Log-in Help',                                   {col1 => 'Log-in Help',
                                   col2 => 'Value'},                                    col2 => 'Value'},
                                  {col1 => 'Custom HTML in document head',                                   {col1 => 'Custom HTML in document head',
                                   col2 => 'Value'},                                    col2 => 'Value'}],
                                  {col1 => 'SSO',  
                                   col2 => 'Dual login: SSO and non-SSO options'},  
                                 ],  
                       print => \&print_login,                        print => \&print_login,
                       modify => \&modify_login,                        modify => \&modify_login,
                     },                      },
Line 298  sub handler { Line 265  sub handler {
                       header => [{col1 => 'Setting',                        header => [{col1 => 'Setting',
                                   col2 => 'Value'},                                    col2 => 'Value'},
                                  {col1 => 'Institutional user types',                                   {col1 => 'Institutional user types',
                                   col2 => 'Name displayed'},                                    col2 => 'Assignable to e-mail usernames'}],
                                  {col1 => 'Mapping for missing usernames via standard log-in',  
                                   col2 => 'Rules in use'}],  
                       print => \&print_defaults,                        print => \&print_defaults,
                       modify => \&modify_defaults,                        modify => \&modify_defaults,
                     },                      },
         'wafproxy' =>  
                     { text => 'Web Application Firewall/Reverse Proxy',  
                       help => 'Domain_Configuration_WAF_Proxy',  
                       header => [{col1 => 'Domain(s)',  
                                   col2 => 'Servers and WAF/Reverse Proxy alias(es)',  
                                  },  
                                  {col1 => 'Domain(s)',  
                                   col2 => 'WAF Configuration',}],  
                       print => \&print_wafproxy,  
                       modify => \&modify_wafproxy,  
                     },  
         'passwords' =>  
                     { text => 'Passwords (Internal authentication)',  
                       help => 'Domain_Configuration_Passwords',  
                       header => [{col1 => 'Resetting Forgotten Password',  
                                   col2 => 'Settings'},  
                                  {col1 => 'Encryption of Stored Passwords (Internal Auth)',  
                                   col2 => 'Settings'},  
                                  {col1 => 'Rules for LON-CAPA Passwords',  
                                   col2 => 'Settings'},  
                                  {col1 => 'Course Owner Changing Student Passwords',  
                                   col2 => 'Settings'}],  
                       print => \&print_passwords,  
                       modify => \&modify_passwords,  
                     },  
         'quotas' =>           'quotas' => 
                     { text => 'Blogs, personal pages/timezones, webDAV/quotas, portfolio',                      { text => 'Blogs, personal web pages, webDAV/quotas, portfolios',
                       help => 'Domain_Configuration_Quotas',                        help => 'Domain_Configuration_Quotas',
                       header => [{col1 => 'User affiliation',                        header => [{col1 => 'User affiliation',
                                   col2 => 'Available tools',                                    col2 => 'Available tools',
Line 377  sub handler { Line 317  sub handler {
                     modify => \&modify_directorysrch,                      modify => \&modify_directorysrch,
                   },                    },
         'contacts' =>          'contacts' =>
                   { text => 'E-mail addresses and helpform',                    { text => 'Contact Information',
                     help => 'Domain_Configuration_Contact_Info',                      help => 'Domain_Configuration_Contact_Info',
                     header => [{col1 => 'Default e-mail addresses',                      header => [{col1 => 'Setting',
                                 col2 => 'Value',},                                  col2 => 'Value',}],
                                {col1 => 'Recipient(s) for notifications',  
                                 col2 => 'Value',},  
                                {col1 => 'Nightly status check e-mail',  
                                 col2 => 'Settings',},  
                                {col1 => 'Ask helpdesk form settings',  
                                 col2 => 'Value',},],  
                     print => \&print_contacts,                      print => \&print_contacts,
                     modify => \&modify_contacts,                      modify => \&modify_contacts,
                   },                    },
Line 409  sub handler { Line 343  sub handler {
                                 col2 => 'Enabled?'},                                  col2 => 'Enabled?'},
                                {col1 => 'Institutional user type (login/SSO self-creation)',                                 {col1 => 'Institutional user type (login/SSO self-creation)',
                                 col2 => 'Information user can enter'},                                  col2 => 'Information user can enter'},
                                {col1 => 'Self-creation with e-mail verification',                                 {col1 => 'Self-creation with e-mail as username',
                                 col2 => 'Settings'}],                                  col2 => 'Settings'}],
                     print => \&print_selfcreation,                      print => \&print_selfcreation,
                     modify => \&modify_selfcreation,                      modify => \&modify_selfcreation,
Line 425  sub handler { Line 359  sub handler {
                     modify => \&modify_usermodification,                      modify => \&modify_usermodification,
                   },                    },
         'scantron' =>          'scantron' =>
                   { text => 'Bubblesheet format',                    { text => 'Bubblesheet format file',
                     help => 'Domain_Configuration_Scantron_Format',                      help => 'Domain_Configuration_Scantron_Format',
                     header => [ {col1 => 'Bubblesheet format file',                      header => [ {col1 => 'Item',
                                  col2 => ''},                                   col2 => '',
                                 {col1 => 'Bubblesheet data upload formats',                                }],
                                  col2 => 'Settings'}],  
                     print => \&print_scantron,                      print => \&print_scantron,
                     modify => \&modify_scantron,                      modify => \&modify_scantron,
                   },                    },
Line 515  sub handler { Line 448  sub handler {
                   print => \&print_selfenrollment,                    print => \&print_selfenrollment,
                   modify => \&modify_selfenrollment,                    modify => \&modify_selfenrollment,
                  },                   },
           'privacy' => 
                    {text   => 'User Privacy',
                     help   => 'Domain_Configuration_User_Privacy',
                     header => [{col1 => 'Setting',
                                 col2 => 'Value',}],
                     print => \&print_privacy,
                     modify => \&modify_privacy,
                    },
         'usersessions' =>          'usersessions' =>
                  {text  => 'User session hosting/offloading',                   {text  => 'User session hosting/offloading',
                   help  => 'Domain_Configuration_User_Sessions',                    help  => 'Domain_Configuration_User_Sessions',
Line 538  sub handler { Line 479  sub handler {
                   print => \&print_loadbalancing,                    print => \&print_loadbalancing,
                   modify => \&modify_loadbalancing,                    modify => \&modify_loadbalancing,
                  },                   },
         'ltitools' =>          'ltitools' => 
                  {text => 'External Tools (LTI)',                   {text => 'External Tools (LTI)',
                   help => 'Domain_Configuration_LTI_Tools',                    help => 'Domain_configuration_LTI_Tools',
                   header => [{col1 => 'Setting',                    header => [{col1 => 'Setting',
                               col2 => 'Value',}],                                col2 => 'Value',}],
                   print => \&print_ltitools,                    print => \&print_ltitools,
                   modify => \&modify_ltitools,                    modify => \&modify_ltitools,
                  },                   },
           'lti' =>          'ssl' =>
                  {text => 'LTI Link Protection and LTI Consumers',                   {text  => 'LON-CAPA Network (SSL)',
                   help => 'Domain_Configuration_LTI_Provider',                    help  => 'Domain_Configuration_Network_SSL',
                   header => [{col1 => 'Encryption of shared secrets',                    header => [{col1 => 'Server',
                               col2 => 'Settings'},                                col2 => 'Certificate Status'},
                              {col1 => 'Rules for shared secrets',                               {col1 => 'Connections to other servers',
                               col2 => 'Settings'},                                col2 => 'Rules'},
                              {col1 => 'Link Protectors',                               {col1 => "Replicating domain's published content",
                               col2 => 'Settings'},],                                col2 => 'Rules'}],
                   print => \&print_lti,                    print => \&print_ssl,
                   modify => \&modify_lti,                    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,
                  },                   },
          'ipaccess' =>  
                        {text => 'IP-based access control',  
                         help => 'Domain_Configuration_IP_Access',  
                         header => [{col1 => 'Setting',  
                                     col2 => 'Value'},],  
                         print  => \&print_ipaccess,  
                         modify => \&modify_ipaccess,  
                        },  
     );      );
     if (keys(%servers) > 1) {      if (keys(%servers) > 1) {
         $prefs{'login'}  = { text   => 'Log-in page options',          $prefs{'login'}  = { text   => 'Log-in page options',
Line 573  sub handler { Line 530  sub handler {
                             header => [{col1 => 'Log-in Service',                              header => [{col1 => 'Log-in Service',
                                         col2 => 'Server Setting',},                                          col2 => 'Server Setting',},
                                        {col1 => 'Log-in Page Items',                                         {col1 => 'Log-in Page Items',
                                         col2 => 'Settings'},                                          col2 => ''},
                                        {col1 => 'Log-in Help',                                         {col1 => 'Log-in Help',
                                         col2 => 'Value'},                                          col2 => 'Value'},
                                        {col1 => 'Custom HTML in document head',                                         {col1 => 'Custom HTML in document head',
                                         col2 => 'Value'},                                          col2 => 'Value'}],
                                        {col1 => 'SSO',  
                                         col2 => 'Dual login: SSO and non-SSO options'},  
                                       ],  
                             print => \&print_login,                              print => \&print_login,
                             modify => \&modify_login,                              modify => \&modify_login,
                            };                             };
Line 621  $javascript_validations Line 575  $javascript_validations
 </script>  </script>
 $coursebrowserjs  $coursebrowserjs
 END  END
         } elsif (grep(/^ipaccess$/,@actions)) {  
             $js .= &Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'});  
         }  
         if (grep(/^selfcreation$/,@actions)) {  
             $js .= &selfcreate_javascript();  
         }  
         if (grep(/^contacts$/,@actions)) {  
             $js .= &contacts_javascript();  
         }  
         if (grep(/^scantron$/,@actions)) {  
             $js .= &scantron_javascript();  
         }          }
         &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);          &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);
     } else {      } else {
Line 722  sub process_changes { Line 665  sub process_changes {
     } elsif ($action eq 'autocreate') {      } elsif ($action eq 'autocreate') {
         $output = &modify_autocreate($dom,%domconfig);          $output = &modify_autocreate($dom,%domconfig);
     } elsif ($action eq 'directorysrch') {      } elsif ($action eq 'directorysrch') {
         $output = &modify_directorysrch($dom,$lastactref,%domconfig);          $output = &modify_directorysrch($dom,%domconfig);
     } elsif ($action eq 'usercreation') {      } elsif ($action eq 'usercreation') {
         $output = &modify_usercreation($dom,%domconfig);          $output = &modify_usercreation($dom,%domconfig);
     } elsif ($action eq 'selfcreation') {      } elsif ($action eq 'selfcreation') {
         $output = &modify_selfcreation($dom,$lastactref,%domconfig);          $output = &modify_selfcreation($dom,%domconfig);
     } elsif ($action eq 'usermodification') {      } elsif ($action eq 'usermodification') {
         $output = &modify_usermodification($dom,%domconfig);          $output = &modify_usermodification($dom,%domconfig);
     } elsif ($action eq 'contacts') {      } elsif ($action eq 'contacts') {
Line 744  sub process_changes { Line 687  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,$lastactref,%domconfig);          $output = &modify_helpsettings($r,$dom,$confname,%domconfig);
     } elsif ($action eq 'coursedefaults') {      } elsif ($action eq 'coursedefaults') {
         $output = &modify_coursedefaults($dom,$lastactref,%domconfig);          $output = &modify_coursedefaults($dom,$lastactref,%domconfig);
     } elsif ($action eq 'selfenrollment') {      } elsif ($action eq 'selfenrollment') {
Line 753  sub process_changes { Line 696  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 'lti') {  
         $output = &modify_lti($r,$dom,$action,$lastactref,%domconfig);  
     } elsif ($action eq 'passwords') {  
         $output = &modify_passwords($r,$dom,$confname,$lastactref,%domconfig);  
     } elsif ($action eq 'ltitools') {      } elsif ($action eq 'ltitools') {
         $output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig);          $output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig);
     } elsif ($action eq 'wafproxy') {      } elsif ($action eq 'ssl') {
         $output = &modify_wafproxy($dom,$action,$lastactref,%domconfig);          $output = &modify_ssl($dom,$lastactref,%domconfig);
     } elsif ($action eq 'ipaccess') {      } elsif ($action eq 'trust') {
         $output = &modify_ipaccess($dom,$lastactref,%domconfig);          $output = &modify_trust($dom,$lastactref,%domconfig);
     }      }
     return $output;      return $output;
 }  }
Line 775  sub print_config_box { Line 714  sub print_config_box {
         $output = &coursecategories_javascript($settings);          $output = &coursecategories_javascript($settings);
     } elsif ($action eq 'defaults') {      } elsif ($action eq 'defaults') {
         $output = &defaults_javascript($settings);           $output = &defaults_javascript($settings); 
     } elsif ($action eq 'passwords') {  
         $output = &passwords_javascript($action);  
     } elsif ($action eq 'helpsettings') {      } elsif ($action eq 'helpsettings') {
         my (%privs,%levelscurrent);          my (%privs,%levelscurrent);
         my %full=();          my %full=();
Line 791  sub print_config_box { Line 728  sub print_config_box {
         &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);          &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
         my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);          my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
         $output =          $output =
             &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full,              &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full, 
                                                       \@templateroles);                                                        \@templateroles);
     } elsif ($action eq 'ltitools') {  
         $output .= &ltitools_javascript($settings);  
     } elsif ($action eq 'lti') {  
         $output .= &passwords_javascript('secrets')."\n".  
                    &lti_javascript($dom,$settings);  
     } elsif ($action eq 'wafproxy') {  
         $output .= &wafproxy_javascript($dom);  
     } elsif ($action eq 'autoupdate') {  
         $output .= &autoupdate_javascript();  
     } elsif ($action eq 'autoenroll') {  
         $output .= &autoenroll_javascript();  
     } elsif ($action eq 'login') {  
         $output .= &saml_javascript();  
     } elsif ($action eq 'ipaccess') {  
         $output .= &ipaccess_javascript($settings);  
     }      }
     $output .=      $output .=
          '<table class="LC_nested_outer">           '<table class="LC_nested_outer">
           <tr>            <tr>
            <th class="LC_left_item LC_middle"><span class="LC_nobreak">'.             <th align="left" valign="middle"><span class="LC_nobreak">'.
            &mt($item->{text}).'&nbsp;'.             &mt($item->{text}).'&nbsp;'.
            &Apache::loncommon::help_open_topic($item->{'help'}).'</span></th>'."\n".             &Apache::loncommon::help_open_topic($item->{'help'}).'</span></th>'."\n".
           '</tr>';            '</tr>';
Line 824  sub print_config_box { Line 746  sub print_config_box {
     if ($numheaders > 1) {      if ($numheaders > 1) {
         my $colspan = '';          my $colspan = '';
         my $rightcolspan = '';          my $rightcolspan = '';
         my $leftnobr = '';    
         if (($action eq 'rolecolors') || ($action eq 'defaults') ||          if (($action eq 'rolecolors') || ($action eq 'defaults') ||
             ($action eq 'directorysrch') ||              ($action eq 'directorysrch') ||
             (($action eq 'login') && ($numheaders < 5))) {              (($action eq 'login') && ($numheaders < 4))) {
             $colspan = ' colspan="2"';              $colspan = ' colspan="2"';
         }          }
         if ($action eq 'usersessions') {          if ($action eq 'usersessions') {
             $rightcolspan = ' colspan="3"';               $rightcolspan = ' colspan="3"'; 
         }          }
         if ($action eq 'passwords') {  
             $leftnobr = ' LC_nobreak';  
         }  
         $output .= '          $output .= '
           <tr>            <tr>
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item'.$leftnobr.'"'.$colspan.'>'.&mt($item->{'header'}->[0]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
               <td class="LC_right_item"'.$rightcolspan.'>'.&mt($item->{'header'}->[0]->{'col2'}).'</td>                <td class="LC_right_item"'.$rightcolspan.'>'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
              </tr>';               </tr>';
         $rowtotal ++;          $rowtotal ++;
         if (($action eq 'autoupdate') || ($action eq 'usercreation') || ($action eq 'selfcreation') ||          if (($action eq 'autoupdate') || ($action eq 'usercreation') || ($action eq 'selfcreation') ||
             ($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') ||              ($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') ||
             ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'directorysrch') ||              ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'ssl') ||
             ($action eq 'helpsettings') || ($action eq 'contacts') || ($action eq 'wafproxy') || ($action eq 'lti')) {              ($action eq 'directorysrch') || ($action eq 'trust') || ($action eq 'helpsettings')) {
             $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);              $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'passwords') {  
             $output .= $item->{'print'}->('top',$dom,$confname,$settings,\$rowtotal);  
         } elsif ($action eq 'coursecategories') {          } elsif ($action eq 'coursecategories') {
             $output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal);              $output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal);
         } elsif ($action eq 'scantron') {  
             $output .= $item->{'print'}->($r,'top',$dom,$confname,$settings,\$rowtotal);  
         } elsif ($action eq 'login') {          } elsif ($action eq 'login') {
             if ($numheaders == 5) {              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 882  sub print_config_box { Line 796  sub print_config_box {
             $rowtotal ++;              $rowtotal ++;
         if (($action eq 'autoupdate') || ($action eq 'usercreation') ||          if (($action eq 'autoupdate') || ($action eq 'usercreation') ||
             ($action eq 'selfcreation') || ($action eq 'selfenrollment') ||              ($action eq 'selfcreation') || ($action eq 'selfenrollment') ||
             ($action eq 'usersessions') || ($action eq 'coursecategories') ||              ($action eq 'usersessions') || ($action eq 'coursecategories') || 
             ($action eq 'contacts') || ($action eq 'passwords') ||               ($action eq 'ssl') || ($action eq 'trust')) {
             ($action eq 'defaults') || ($action eq 'lti')) {  
             if ($action eq 'coursecategories') {              if ($action eq 'coursecategories') {
                 $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);                  $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);
                 $colspan = ' colspan="2"';                  $colspan = ' colspan="2"';
             } elsif ($action eq 'passwords') {              } elsif ($action eq 'trust') {
                 $output .= $item->{'print'}->('middle',$dom,$confname,$settings,\$rowtotal);                  $output .= $item->{'print'}->('shared',$dom,$settings,\$rowtotal);
             } else {              } else {
                 $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);                  $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);
             }              }
             $output .= '              if ($action eq 'trust') {
            </table>                  $output .= '
               </table>
           </td>            </td>
          </tr>           </tr>';
                   my @trusthdrs = qw(2 3 4 5 6 7);
                   my @prefixes = qw(enroll othcoau coaurem domroles catalog reqcrs);
                   for (my $i=0; $i<@trusthdrs; $i++) {
                       $output .= '
          <tr>           <tr>
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[$trusthdrs[$i]]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>                <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[$trusthdrs[$i]]->{'col2'}).'</td></tr>'.
              </tr>'."\n";                             $item->{'print'}->($prefixes[$i],$dom,$settings,\$rowtotal).'
             if ($action eq 'coursecategories') {              </table>
                 $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);            </td>
             } elsif (($action eq 'contacts') || ($action eq 'passwords')) {           </tr>';
                 if ($action eq 'passwords') {  
                     $output .= $item->{'print'}->('lower',$dom,$confname,$settings,\$rowtotal);  
                 } else {  
                     $output .= $item->{'print'}->('lower',$dom,$settings,\$rowtotal);  
                 }                  }
                 $output .= '                  $output .= '
              </tr>           <tr>
             </table>  
            </td>  
           </tr>  
           <tr>  
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item'.$leftnobr.'"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[8]->{'col1'}).'</td>
               <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td></tr>'."\n";                <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[8]->{'col2'}).'</td></tr>'.
                 if ($action eq 'passwords') {                             $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
                     $output .= $item->{'print'}->('bottom',$dom,$confname,$settings,\$rowtotal);              } else {
                 } else {  
                     $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);  
                 }  
                 $output .= '                  $output .= '
             </table>             </table>
           </td>            </td>
          </tr>           </tr>
          <tr>';           <tr>
             } else {             <td>
                 $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);              <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
                 <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
                </tr>'."\n";
                   if ($action eq 'coursecategories') {
                       $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
                   } else {
                       $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
                   }
             }              }
             $rowtotal ++;              $rowtotal ++;
         } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||          } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||
                  ($action eq 'directorysrch') || ($action eq 'helpsettings') ||                   ($action eq 'defaults') || ($action eq 'directorysrch') ||
                  ($action eq 'wafproxy')) {                   ($action eq 'helpsettings')) {
             $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);              $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'scantron') {  
             $output .= $item->{'print'}->($r,'bottom',$dom,$confname,$settings,\$rowtotal);  
         } elsif ($action eq 'login') {          } elsif ($action eq 'login') {
             if ($numheaders == 5) {              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 968  sub print_config_box { Line 882  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 ($numheaders == 5) {              if ($numheaders == 4) {
                 $output .= '                  $output .= '
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
               <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td>                <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td>
Line 980  sub print_config_box { Line 894  sub print_config_box {
              </tr>';               </tr>';
             }              }
             $rowtotal ++;              $rowtotal ++;
             $output .= &print_login('headtag',$dom,$confname,$phase,$settings,\$rowtotal).'              $output .= &print_login('headtag',$dom,$confname,$phase,$settings,\$rowtotal);
            </table>  
           </td>  
          </tr>  
          <tr>  
            <td>  
             <table class="LC_nested">  
              <tr class="LC_info_row">';  
             if ($numheaders == 5) {  
                 $output .= '  
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[4]->{'col1'}).'</td>  
               <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[4]->{'col2'}).'</td>  
              </tr>';  
             } else {  
                 $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>';  
             }  
             $rowtotal ++;  
             $output .= &print_login('saml',$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);
             $rowtotal ++;              $rowtotal ++;
Line 1119  sub print_config_box { Line 1013  sub print_config_box {
         if ($action eq 'quotas') {          if ($action eq 'quotas') {
             $output .= &print_quotas($dom,$settings,\$rowtotal,$action);              $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
         } elsif (($action eq 'autoenroll') || ($action eq 'autocreate') ||           } elsif (($action eq 'autoenroll') || ($action eq 'autocreate') || 
                  ($action eq 'serverstatuses') || ($action eq 'loadbalancing') ||                   ($action eq 'contacts') || ($action eq 'serverstatuses') || 
                  ($action eq 'ltitools') || ($action eq 'ipaccess')) {                   ($action eq 'loadbalancing') || ($action eq 'ltitools')) {
             $output .= $item->{'print'}->($dom,$settings,\$rowtotal);              $output .= $item->{'print'}->($dom,$settings,\$rowtotal);
           } elsif ($action eq 'scantron') {
               $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);
         }          }
     }      }
     $output .= '      $output .= '
Line 1134  sub print_config_box { Line 1030  sub print_config_box {
   
 sub print_login {  sub print_login {
     my ($caller,$dom,$confname,$phase,$settings,$rowtotal) = @_;      my ($caller,$dom,$confname,$phase,$settings,$rowtotal) = @_;
     my ($css_class,$datatable,$switchserver,%lt);      my ($css_class,$datatable);
     my %choices = &login_choices();      my %choices = &login_choices();
     if (($caller eq 'help') || ($caller eq 'headtag') || ($caller eq 'saml')) {  
         %lt = &login_file_options();  
         $switchserver = &check_switchserver($dom,$confname);  
     }  
   
     if ($caller eq 'service') {      if ($caller eq 'service') {
         my %servers = &Apache::lonnet::internet_dom_servers($dom);          my %servers = &Apache::lonnet::internet_dom_servers($dom);
Line 1227  sub print_login { Line 1119  sub print_login {
             }              }
         }          }
         my @images = ('img','logo','domlogo','login');          my @images = ('img','logo','domlogo','login');
         my @alttext = ('img','logo','domlogo');  
         my @logintext = ('textcol','bgcol');          my @logintext = ('textcol','bgcol');
         my @bgs = ('pgbg','mainbg','sidebg');          my @bgs = ('pgbg','mainbg','sidebg');
         my @links = ('link','alink','vlink');          my @links = ('link','alink','vlink');
Line 1269  sub print_login { Line 1160  sub print_login {
                     $designs{'showlogo'}{$item} = $settings->{'showlogo'}{$item};                      $designs{'showlogo'}{$item} = $settings->{'showlogo'}{$item};
                 }                  }
             }              }
             foreach my $item (@alttext) {  
                 if (ref($settings->{'alttext'}) eq 'HASH') {  
                     if ($settings->{'alttext'}->{$item} ne '') {  
                         $designs{'alttext'}{$item} = $settings->{'alttext'}{$item};  
                     }  
                 }  
             }  
             foreach my $item (@logintext) {              foreach my $item (@logintext) {
                 if ($settings->{$item} ne '') {                  if ($settings->{$item} ne '') {
                     $designs{'logintext'}{$item} = $settings->{$item};                      $designs{'logintext'}{$item} = $settings->{$item};
Line 1342  sub print_login { Line 1226  sub print_login {
         $datatable .= &display_color_options($dom,$confname,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal,\@logintext);          $datatable .= &display_color_options($dom,$confname,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal,\@logintext);
         $datatable .= '</tr></table></td></tr>';          $datatable .= '</tr></table></td></tr>';
     } elsif ($caller eq 'help') {      } elsif ($caller eq 'help') {
         my ($defaulturl,$defaulttype,%url,%type,%langchoices);          my ($defaulturl,$defaulttype,%url,%type,%lt,%langchoices);
           my $switchserver = &check_switchserver($dom,$confname);
         my $itemcount = 1;          my $itemcount = 1;
         $defaulturl = '/adm/loginproblems.html';          $defaulturl = '/adm/loginproblems.html';
         $defaulttype = 'default';          $defaulttype = 'default';
           %lt = &Apache::lonlocal::texthash (
                        del     => 'Delete?',
                        rep     => 'Replace:',
                        upl     => 'Upload:',
                        default => 'Default',
                        custom  => 'Custom',
                                                );
         %langchoices = &Apache::lonlocal::texthash(&get_languages_hash());          %langchoices = &Apache::lonlocal::texthash(&get_languages_hash());
         my @currlangs;          my @currlangs;
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
Line 1442  sub print_login { Line 1334  sub print_login {
                 }                  }
             }              }
         }          }
           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))) {          foreach my $lonhost (sort(keys(%domservers))) {
             my $exempt = &check_exempt_addresses($currexempt{$lonhost});              my $exempt = &check_exempt_addresses($currexempt{$lonhost});
             $datatable .= '<tr><td>'.$domservers{$lonhost}.'</td>';              $datatable .= '<tr><td>'.$domservers{$lonhost}.'</td>';
Line 1462  sub print_login { Line 1362  sub print_login {
             } else {              } else {
                 $datatable .= '<input type="file" name="loginheadtag_'.$lonhost.'" />';                  $datatable .= '<input type="file" name="loginheadtag_'.$lonhost.'" />';
             }              }
             $datatable .= '</td><td><input type="text" name="loginheadtagexempt_'.$lonhost.'" value="'.$exempt.'" /></td></tr>';              $datatable .= '</td><td><input type="textbox" name="loginheadtagexempt_'.$lonhost.'" value="'.$exempt.'" /></td></tr>';
         }  
         $datatable .= '</table></td></tr>';  
     } elsif ($caller eq 'saml') {  
         my %domservers = &Apache::lonnet::get_servers($dom);  
         $datatable .= '<tr><td colspan="3" style="text-align: left">'.  
                       '<table><tr><th>'.$choices{'hostid'}.'</th>'.  
                       '<th>'.$choices{'samllanding'}.'</th>'.  
                       '<th>'.$choices{'samloptions'}.'</th></tr>'."\n";  
         my (%saml,%samltext,%samlimg,%samlalt,%samlurl,%samltitle,%samlwindow,%samlnotsso,%styleon,%styleoff);  
         foreach my $lonhost (keys(%domservers)) {  
             $samlurl{$lonhost} = '/adm/sso';  
             $styleon{$lonhost} = 'display:none';  
             $styleoff{$lonhost} = '';  
         }  
         if ((ref($settings) eq 'HASH') && (ref($settings->{'saml'}) eq 'HASH')) {  
             foreach my $lonhost (keys(%{$settings->{'saml'}})) {  
                 if (ref($settings->{'saml'}{$lonhost}) eq 'HASH') {  
                     $saml{$lonhost} = 1;  
                     $samltext{$lonhost} = $settings->{'saml'}{$lonhost}{'text'};  
                     $samlimg{$lonhost} = $settings->{'saml'}{$lonhost}{'img'};  
                     $samlalt{$lonhost} = $settings->{'saml'}{$lonhost}{'alt'};  
                     $samlurl{$lonhost} = $settings->{'saml'}{$lonhost}{'url'};  
                     $samltitle{$lonhost} = $settings->{'saml'}{$lonhost}{'title'};  
                     $samlwindow{$lonhost} = $settings->{'saml'}{$lonhost}{'window'};  
                     $samlnotsso{$lonhost} = $settings->{'saml'}{$lonhost}{'notsso'};  
                     $styleon{$lonhost} = '';  
                     $styleoff{$lonhost} = 'display:none';  
                 } else {  
                     $styleon{$lonhost} = 'display:none';  
                     $styleoff{$lonhost} = '';  
                 }  
             }  
         }  
         my $itemcount = 1;  
         foreach my $lonhost (sort(keys(%domservers))) {  
             my $samlon = ' ';  
             my $samloff = ' checked="checked" ';  
             if ($saml{$lonhost}) {  
                 $samlon = $samloff;  
                 $samloff = ' ';  
             }  
             my $samlwinon = '';  
             my $samlwinoff = ' checked="checked"';  
             if ($samlwindow{$lonhost}) {  
                 $samlwinon = $samlwinoff;  
                 $samlwinoff = '';  
             }  
             my $css_class = $itemcount%2?' class="LC_odd_row"':'';  
             $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.$domservers{$lonhost}.'</span></td>'.  
                           '<td><span class="LC_nobreak"><label><input type="radio" name="saml_'.$lonhost.'"'.$samloff.  
                           'onclick="toggleSamlOptions(this.form,'."'$lonhost'".');" value="0" />'.  
                           &mt('No').'</label>'.('&nbsp;'x2).  
                           '<label><input type="radio" name="saml_'.$lonhost.'"'.$samlon.  
                           'onclick="toggleSamlOptions(this.form,'."'$lonhost'".');" value="1" />'.  
                           &mt('Yes').'</label></span></td>'.  
                           '<td id="samloptionson_'.$lonhost.'" style="'.$styleon{$lonhost}.'" width="100%">'.  
                           '<table width="100%"><tr><th colspan="3" align="center">'.&mt('SSO').'</th></tr>'.  
                           '<tr><th>'.&mt('Text').'</th><th>'.&mt('Image').'</th>'.  
                           '<th>'.&mt('Alt Text').'</th></tr>'.  
                           '<tr'.$css_class.'><td><input type="text" name="saml_text_'.$lonhost.'" size="20" value="'.  
                           $samltext{$lonhost}.'" /></td><td>';  
             if ($samlimg{$lonhost}) {  
                 $datatable .= '<img src="'.$samlimg{$lonhost}.'" /><br />'.  
                               '<span class="LC_nobreak"><label>'.  
                               '<input type="checkbox" name="saml_img_del" value="'.$lonhost.'" />'.  
                               $lt{'del'}.'</label>&nbsp;'.$lt{'rep'}.'</span>';  
             } else {  
                 $datatable .= $lt{'upl'};  
             }  
             $datatable .='<br />';  
             if ($switchserver) {  
                 $datatable .= &mt('Upload to library server: [_1]',$switchserver);  
             } else {  
                 $datatable .= '<input type="file" name="saml_img_'.$lonhost.'" />';  
             }  
             $datatable .= '</td>'.  
                           '<td><input type="text" name="saml_alt_'.$lonhost.'" size="25" '.  
                           'value="'.$samlalt{$lonhost}.'" /></td></tr></table><br />'.  
                           '<table width="100%"><tr><th colspan="3" align="center">'.&mt('SSO').'</th><th align="center">'.  
                           '<span class="LC_nobreak">'.&mt('Non-SSO').'</span></th></tr>'.  
                           '<tr><th>'.&mt('URL').'</th><th>'.&mt('Tool Tip').'</th>'.  
                           '<th>'.&mt('Pop-up if iframe').'</th><th>'.&mt('Text').'</th></tr>'.  
                           '<tr'.$css_class.'>'.  
                           '<td><input type="text" name="saml_url_'.$lonhost.'" size="30" '.  
                           'value="'.$samlurl{$lonhost}.'" /></td>'.  
                           '<td><textarea name="saml_title_'.$lonhost.'" rows="3" cols="20">'.  
                           $samltitle{$lonhost}.'</textarea></td>'.  
                           '<td><label><input type="radio" name="saml_window_'.$lonhost.'" value=""'.$samlwinoff.'>'.  
                           &mt('No').'</label>'.('&nbsp;'x2).'<label><input type="radio" '.  
                           'name="saml_window_'.$lonhost.'" value="1"'.$samlwinon.'>'.&mt('Yes').'</label></td>'.  
                           '<td><input type="text" name="saml_notsso_'.$lonhost.'" size="12" '.  
                           'value="'.$samlnotsso{$lonhost}.'" /></td></tr>'.  
                           '</table></td>'.  
                           '<td id="samloptionsoff_'.$lonhost.'" style="'.$styleoff{$lonhost}.'" width="100%">&nbsp;</td></tr>';  
            $itemcount ++;  
         }          }
         $datatable .= '</table></td></tr>';          $datatable .= '</table></td></tr>';
     }      }
Line 1596  sub login_choices { Line 1401  sub login_choices {
             headtag       => "Custom markup",              headtag       => "Custom markup",
             action        => "Action",              action        => "Action",
             current       => "Current",              current       => "Current",
             samllanding   => "Dual login?",  
             samloptions   => "Options",  
             alttext       => "Alt text",  
         );          );
     return %choices;      return %choices;
 }  }
   
 sub login_file_options {  
       return &Apache::lonlocal::texthash(  
                                            del     => 'Delete?',  
                                            rep     => 'Replace:',  
                                            upl     => 'Upload:',  
                                            curr    => 'View contents',  
                                            default => 'Default',  
                                            custom  => 'Custom',  
                                            none    => 'None',  
       );  
 }  
   
 sub print_ipaccess {  
     my ($dom,$settings,$rowtotal) = @_;  
     my $css_class;  
     my $itemcount = 0;  
     my $datatable;  
     my %ordered;  
     if (ref($settings) eq 'HASH') {  
         foreach my $item (keys(%{$settings})) {  
             if (ref($settings->{$item}) eq 'HASH') {  
                 my $num = $settings->{$item}{'order'};  
                 if ($num eq '') {  
                     $num = scalar(keys(%{$settings}));  
                 }  
                 $ordered{$num} = $item;  
             }  
         }  
     }  
     my $maxnum = scalar(keys(%ordered));  
     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 ($name,$ipranges,%commblocks,%courses);  
             if (ref($settings->{$item}) eq 'HASH') {  
                 $name = $settings->{$item}->{'name'};  
                 $ipranges = $settings->{$item}->{'ip'};  
                 if (ref($settings->{$item}->{'commblocks'}) eq 'HASH') {  
                     %commblocks = %{$settings->{$item}->{'commblocks'}};  
                 }  
                 if (ref($settings->{$item}->{'courses'}) eq 'HASH') {  
                     %courses = %{$settings->{$item}->{'courses'}};  
                 }  
             }  
             my $chgstr = ' onchange="javascript:reorderIPaccess(this.form,'."'ipaccess_pos_".$item."'".');"';  
             $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'  
                          .'<select name="ipaccess_pos_'.$item.'"'.$chgstr.'>';  
             for (my $k=0; $k<=$maxnum; $k++) {  
                 my $vpos = $k+1;  
                 my $selstr;  
                 if ($k == $i) {  
                     $selstr = ' selected="selected" ';  
                 }  
                 $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';  
             }  
             $datatable .= '</select>'.('&nbsp;'x2).  
                 '<label><input type="checkbox" name="ipaccess_del" value="'.$item.'" />'.  
                 &mt('Delete?').'</label></span></td>'.  
                 '<td colspan="2"><input type="hidden" name="ipaccess_id_'.$i.'" value="'.$item.'" />'.  
                 &ipaccess_options($i,$itemcount,$dom,$name,$ipranges,\%commblocks,\%courses).  
                 '</td></tr>';  
             $itemcount ++;  
         }  
     }  
     $css_class = $itemcount%2?' class="LC_odd_row"':'';  
     my $chgstr = ' onchange="javascript:reorderIPaccess(this.form,'."'ipaccess_pos_add'".');"';  
     $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".  
                   '<input type="hidden" name="ipaccess_maxnum" value="'.$maxnum.'" />'."\n".  
                   '<select name="ipaccess_pos_add"'.$chgstr.'>';  
     for (my $k=0; $k<$maxnum+1; $k++) {  
         my $vpos = $k+1;  
         my $selstr;  
         if ($k == $maxnum) {  
             $selstr = ' selected="selected" ';  
         }  
         $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';  
     }  
     $datatable .= '</select>&nbsp;'."\n".  
                   '<input type="checkbox" name="ipaccess_add" value="1" />'.&mt('Add').'</span></td>'."\n".  
                   '<td colspan="2">'.  
                   &ipaccess_options('add',$itemcount,$dom).  
                   '</td>'."\n".  
                   '</tr>'."\n";  
     $$rowtotal ++;  
     return $datatable;  
 }  
   
 sub ipaccess_options {  
     my ($num,$itemcount,$dom,$name,$ipranges,$blocksref,$coursesref) = @_;  
     my (%currblocks,%currcourses,$output);  
     if (ref($blocksref) eq 'HASH') {  
         %currblocks = %{$blocksref};  
     }  
     if (ref($coursesref) eq 'HASH') {  
         %currcourses = %{$coursesref};  
     }  
     $output = '<fieldset><legend>'.&mt('Location(s)').'</legend>'.  
               '<span class="LC_nobreak">'.&mt('Name').':&nbsp;'.  
               '<input type="text" name="ipaccess_name_'.$num.'" value="'.$name.'" />'.  
               '</span></fieldset>'.  
               '<fieldset><legend>'.&mt('IP Range(s)').'</legend>'.  
               &mt('Format for each IP range').': '.&mt('A.B.C.D/N or A.B.C.D-E.F.G.H').'<br />'.  
               &mt('Range(s) will be stored as IP netblock(s) in CIDR notation (comma separated)').'<br />'.  
               '<textarea name="ipaccess_range_'.$num.'" rows="3" cols="80">'.  
               $ipranges.'</textarea></fieldset>'.  
               '<fieldset><legend>'.&mt('Functionality Blocked?').'</legend>'.  
               &blocker_checkboxes($num,$blocksref).'</fieldset>'.  
               '<fieldset><legend>'.&mt('Courses/Communities allowed').'</legend>'.  
               '<table>';  
     foreach my $cid (sort(keys(%currcourses))) {  
         my %courseinfo = &Apache::lonnet::coursedescription($cid,{'one_time' => 1});  
         $output .= '<tr><td><span class="LC_nobreak">'.  
                    '<label><input type="checkbox" name="ipaccess_course_delete_'.$num.'" value="'.$cid.'" />'.  
                    &mt('Delete?').'&nbsp;<span class="LC_cusr_emph">'.$courseinfo{'description'}.'</span></label></span>'.  
                    ' <span class="LC_fontsize_medium">('.$cid.')</span></td></tr>';  
     }  
     $output .= '<tr><td><span class="LC_nobreak">'.&mt('Add').':&nbsp;'.  
                '<input type="text" name="ipaccess_cdesc_'.$num.'" value="" onfocus="this.blur();opencrsbrowser('."'display','ipaccess_cnum_$num','ipaccess_cdom_$num','ipaccess_cdesc_$num'".');" />'.  
                 &Apache::loncommon::selectcourse_link('display','ipaccess_cnum_'.$num,'ipaccess_cdom_'.$num,'ipaccess_cdesc_'.$num,$dom,undef,'Course/Community').  
                '<input type="hidden" name="ipaccess_cnum_'.$num.'" value="" />'.  
                '<input type="hidden" name="ipaccess_cdom_'.$num.'" value="" />'.  
                '</span></td></tr></table>'."\n".  
                '</fieldset>';  
     return $output;  
 }  
   
 sub blocker_checkboxes {  
     my ($num,$blocks) = @_;  
     my ($typeorder,$types) = &commblocktype_text();  
     my $numinrow = 6;  
     my $output = '<table>';  
     for (my $i=0; $i<@{$typeorder}; $i++) {  
         my $block = $typeorder->[$i];  
         my $blockstatus;  
         if (ref($blocks) eq 'HASH') {  
             if ($blocks->{$block} eq 'on') {  
                 $blockstatus = 'checked="checked"';  
             }  
         }  
         my $rem = $i%($numinrow);  
         if ($rem == 0) {  
             if ($i > 0) {  
                 $output .= '</tr>';  
             }  
             $output .= '<tr>';  
         }  
         if ($i == scalar(@{$typeorder})-1) {  
             my $colsleft = $numinrow-$rem;  
             if ($colsleft > 1) {  
                 $output .= '<td colspan="'.$colsleft.'">';  
             } else {  
                 $output .= '<td>';  
             }  
         } else {  
             $output .= '<td>';  
         }  
         my $item = 'ipaccess_block_'.$num;  
         if ($blockstatus) {  
             $blockstatus = ' '.$blockstatus;  
         }  
         $output .= '<span class="LC_nobreak"><label>'."\n".  
                    '<input type="checkbox" name="'.$item.'"'.  
                    $blockstatus.' value="'.$block.'"'.' />'.  
                    $types->{$block}.'</label></span>'."\n".  
                    '<br /></td>';  
     }  
     $output .= '</tr></table>';  
     return $output;  
 }  
   
 sub commblocktype_text {  
     my %types = &Apache::lonlocal::texthash(  
         'com' => 'Messaging',  
         'chat' => 'Chat Room',  
         'boards' => 'Discussion',  
         'port' => 'Portfolio',  
         'groups' => 'Groups',  
         'blogs' => 'Blogs',  
         'about' => 'User Information',  
         'printout' => 'Printouts',  
         'passwd' => 'Change Password',  
         'grades' => 'Gradebook',  
         'search' => 'Course search',  
         'wishlist' => 'Stored links',  
         'annotate' => 'Annotations',  
     );  
     my $typeorder = ['com','chat','boards','port','groups','blogs','about','wishlist','printout','grades','search','annotate','passwd'];  
     return ($typeorder,\%types);  
 }  
   
 sub print_rolecolors {  sub print_rolecolors {
     my ($phase,$role,$dom,$confname,$settings,$rowtotal) = @_;      my ($phase,$role,$dom,$confname,$settings,$rowtotal) = @_;
     my %choices = &color_font_choices();      my %choices = &color_font_choices();
Line 1912  sub display_color_options { Line 1522  sub display_color_options {
     my $datatable = '<tr'.$css_class.'>'.      my $datatable = '<tr'.$css_class.'>'.
         '<td>'.$choices->{'font'}.'</td>';          '<td>'.$choices->{'font'}.'</td>';
     if (!$is_custom->{'font'}) {      if (!$is_custom->{'font'}) {
         $datatable .=  '<td>'.&mt('Default in use:').'&nbsp;<span class="css_default_'.$role.'_font" style="color: '.$defaults->{'font'}.';">'.$defaults->{'font'}.'</span></td>';          $datatable .=  '<td>'.&mt('Default in use:').'&nbsp;<span id="css_default_'.$role.'_font" style="color: '.$defaults->{'font'}.';">'.$defaults->{'font'}.'</span></td>';
     } else {      } else {
         $datatable .= '<td>&nbsp;</td>';          $datatable .= '<td>&nbsp;</td>';
     }      }
Line 1921  sub display_color_options { Line 1531  sub display_color_options {
     $datatable .= '<td><span class="LC_nobreak">'.      $datatable .= '<td><span class="LC_nobreak">'.
                   '<input type="text" class="colorchooser" size="10" name="'.$role.'_font"'.                    '<input type="text" class="colorchooser" size="10" name="'.$role.'_font"'.
                   ' value="'.$current_color.'" />&nbsp;'.                    ' value="'.$current_color.'" />&nbsp;'.
                   '&nbsp;</span></td></tr>';                    '&nbsp;</td></tr>';
     unless ($role eq 'login') {       unless ($role eq 'login') { 
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                       '<td>'.$choices->{'fontmenu'}.'</td>';                        '<td>'.$choices->{'fontmenu'}.'</td>';
         if (!$is_custom->{'fontmenu'}) {          if (!$is_custom->{'fontmenu'}) {
             $datatable .=  '<td>'.&mt('Default in use:').'&nbsp;<span class="css_default_'.$role.'_font" style="color: '.$defaults->{'fontmenu'}.';">'.$defaults->{'fontmenu'}.'</span></td>';              $datatable .=  '<td>'.&mt('Default in use:').'&nbsp;<span id="css_default_'.$role.'_font" style="color: '.$defaults->{'fontmenu'}.';">'.$defaults->{'fontmenu'}.'</span></td>';
         } else {          } else {
             $datatable .= '<td>&nbsp;</td>';              $datatable .= '<td>&nbsp;</td>';
         }          }
Line 1936  sub display_color_options { Line 1546  sub display_color_options {
                       '<input class="colorchooser" type="text" size="10" name="'                        '<input class="colorchooser" type="text" size="10" name="'
       .$role.'_fontmenu"'.        .$role.'_fontmenu"'.
                       ' value="'.$current_color.'" />&nbsp;'.                        ' value="'.$current_color.'" />&nbsp;'.
                       '&nbsp;</span></td></tr>';                        '&nbsp;</td></tr>';
     }      }
     my $switchserver = &check_switchserver($dom,$confname);      my $switchserver = &check_switchserver($dom,$confname);
     foreach my $img (@{$images}) {      foreach my $img (@{$images}) {
Line 1944  sub display_color_options { Line 1554  sub display_color_options {
         $css_class = $itemcount%2?' class="LC_odd_row"':'';          $css_class = $itemcount%2?' class="LC_odd_row"':'';
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                       '<td>'.$choices->{$img};                        '<td>'.$choices->{$img};
         my ($imgfile,$img_import,$login_hdr_pick,$logincolors,$alttext);          my ($imgfile,$img_import,$login_hdr_pick,$logincolors);
         if ($role eq 'login') {          if ($role eq 'login') {
             if ($img eq 'login') {              if ($img eq 'login') {
                 $login_hdr_pick =                  $login_hdr_pick =
Line 1952  sub display_color_options { Line 1562  sub display_color_options {
                 $logincolors =                  $logincolors =
                     &login_text_colors($img,$role,$logintext,$phase,$choices,                      &login_text_colors($img,$role,$logintext,$phase,$choices,
                                        $designs,$defaults);                                         $designs,$defaults);
             } else {              } elsif ($img ne 'domlogo') {
                 if ($img ne 'domlogo') {                  $datatable.= &logo_display_options($img,$defaults,$designs);
                     $datatable.= &logo_display_options($img,$defaults,$designs);  
                 }  
                 if (ref($designs->{'alttext'}) eq 'HASH') {  
                     $alttext = $designs->{'alttext'}{$img};  
                 }  
             }              }
         }          }
         $datatable .= '</td>';          $datatable .= '</td>';
Line 2000  sub display_color_options { Line 1605  sub display_color_options {
                         if ($fullwidth ne '' && $fullheight ne '') {                          if ($fullwidth ne '' && $fullheight ne '') {
                             if ($fullwidth > $width && $fullheight > $height) {                               if ($fullwidth > $width && $fullheight > $height) { 
                                 my $size = $width.'x'.$height;                                  my $size = $width.'x'.$height;
                                 my @args = ('convert','-sample',$size,$input,$output);                                  system("convert -sample $size $input $output");
                                 system({$args[0]} @args);  
                                 $showfile = "/$imgdir/tn-".$filename;                                  $showfile = "/$imgdir/tn-".$filename;
                             }                              }
                         }                          }
Line 2050  sub display_color_options { Line 1654  sub display_color_options {
                 $datatable .='&nbsp;<input type="file" name="'.$role.'_'.$img.'" />';                  $datatable .='&nbsp;<input type="file" name="'.$role.'_'.$img.'" />';
             }              }
         }          }
         if (($role eq 'login') && ($img ne 'login')) {  
             $datatable .= ('&nbsp;' x2).' <span class="LC_nobreak"><label>'.$choices->{'alttext'}.':'.  
                           '<input type="text" name="'.$role.'_alt_'.$img.'" size="10" value="'.$alttext.'" />'.  
                           '</label></span>';  
         }  
         $datatable .= '</td></tr>';          $datatable .= '</td></tr>';
     }      }
     $itemcount ++;      $itemcount ++;
Line 2064  sub display_color_options { Line 1663  sub display_color_options {
     my $bgs_def;      my $bgs_def;
     foreach my $item (@{$bgs}) {      foreach my $item (@{$bgs}) {
         if (!$is_custom->{$item}) {          if (!$is_custom->{$item}) {
             $bgs_def .= '<td><span class="LC_nobreak">'.$choices->{$item}.'</span>&nbsp;<span class="css_default_'.$role.'_'.$item.'" style="background-color: '.$defaults->{'bgs'}{$item}.';">&nbsp;&nbsp;&nbsp;</span><br />'.$defaults->{'bgs'}{$item}.'</td>';              $bgs_def .= '<td><span class="LC_nobreak">'.$choices->{$item}.'</span>&nbsp;<span id="css_default_'.$role.'_'.$item.'" style="background-color: '.$defaults->{'bgs'}{$item}.';">&nbsp;&nbsp;&nbsp;</span><br />'.$defaults->{'bgs'}{$item}.'</td>';
         }          }
     }      }
     if ($bgs_def) {      if ($bgs_def) {
Line 2092  sub display_color_options { Line 1691  sub display_color_options {
     my $links_def;      my $links_def;
     foreach my $item (@{$links}) {      foreach my $item (@{$links}) {
         if (!$is_custom->{$item}) {          if (!$is_custom->{$item}) {
             $links_def .= '<td>'.$choices->{$item}.'<br /><span class="css_default_'.$role.'_'.$item.'" style="color: '.$defaults->{'links'}{$item}.';">'.$defaults->{'links'}{$item}.'</span></td>';              $links_def .= '<td>'.$choices->{$item}.'<br /><span id="css_default_'.$role.'_'.$item.'" style="color: '.$defaults->{'links'}{$item}.';">'.$defaults->{'links'}{$item}.'</span></td>';
         }          }
     }      }
     if ($links_def) {      if ($links_def) {
Line 2178  sub image_changes { Line 1777  sub image_changes {
     my ($is_custom,$alt_text,$img_import,$showfile,$fullsize,$role,$img,$imgfile,$logincolors) = @_;      my ($is_custom,$alt_text,$img_import,$showfile,$fullsize,$role,$img,$imgfile,$logincolors) = @_;
     my $output;      my $output;
     if ($img eq 'login') {      if ($img eq 'login') {
         $output = '</td><td>'.$logincolors; # suppress image for Log-in header              # suppress image for Log-in header
     } elsif (!$is_custom) {      } elsif (!$is_custom) {
         if ($img ne 'domlogo') {          if ($img ne 'domlogo') {
             $output = &mt('Default image:').'<br />';              $output .= &mt('Default image:').'<br />';
         } else {          } else {
             $output = &mt('Default in use:').'<br />';              $output .= &mt('Default in use:').'<br />';
         }          }
     }      }
     if ($img ne 'login') {      if ($img eq 'login') { # suppress image for Log-in header
           $output .= '<td>'.$logincolors;
       } else {
         if ($img_import) {          if ($img_import) {
             $output .= '<input type="hidden" name="'.$role.'_import_'.$img.'" value="'.$imgfile.'" />';              $output .= '<input type="hidden" name="'.$role.'_import_'.$img.'" value="'.$imgfile.'" />';
         }          }
Line 2217  sub print_quotas { Line 1818  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 2226  sub print_quotas { Line 1827  sub print_quotas {
         @options = ('norequest','approval','automatic');          @options = ('norequest','approval','automatic');
         %titles = &authorrequest_titles();          %titles = &authorrequest_titles();
     } else {      } else {
         @usertools = ('aboutme','blog','webdav','portfolio','timezone');          @usertools = ('aboutme','blog','webdav','portfolio');
         %titles = &tool_titles();          %titles = &tool_titles();
     }      }
     if (ref($types) eq 'ARRAY') {      if (ref($types) eq 'ARRAY') {
Line 2330  sub print_quotas { Line 1931  sub print_quotas {
                         }                          }
                     } else {                      } else {
                         my $checked = 'checked="checked" ';                          my $checked = 'checked="checked" ';
                         if ($item eq 'timezone') {  
                             $checked = '';  
                         }  
                         if (ref($settings) eq 'HASH') {                          if (ref($settings) eq 'HASH') {
                             if (ref($settings->{$item}) eq 'HASH') {                              if (ref($settings->{$item}) eq 'HASH') {
                                 if (!$settings->{$item}->{$type}) {                                  if ($settings->{$item}->{$type} == 0) {
                                     $checked = '';                                      $checked = '';
                                 } elsif ($settings->{$item}->{$type} == 1) {                                  } elsif ($settings->{$item}->{$type} == 1) {
                                     $checked =  'checked="checked" ';                                      $checked =  'checked="checked" ';
Line 2633  sub print_quotas { Line 2231  sub print_quotas {
 }  }
   
 sub print_requestmail {  sub print_requestmail {
     my ($dom,$action,$settings,$rowtotal,$customcss,$rowstyle) = @_;      my ($dom,$action,$settings,$rowtotal) = @_;
     my ($now,$datatable,%currapp);      my ($now,$datatable,%currapp);
     $now = time;      $now = time;
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
Line 2645  sub print_requestmail { Line 2243  sub print_requestmail {
     }      }
     my $numinrow = 2;      my $numinrow = 2;
     my $css_class;      my $css_class;
     if ($$rowtotal%2) {      $css_class = ($$rowtotal%2? ' class="LC_odd_row"':'');
         $css_class = 'LC_odd_row';  
     }  
     if ($customcss) {  
         $css_class .= " $customcss";  
     }  
     $css_class =~ s/^\s+//;  
     if ($css_class) {  
         $css_class = ' class="'.$css_class.'"';  
     }  
     if ($rowstyle) {  
         $css_class .= ' style="'.$rowstyle.'"';  
     }  
     my $text;      my $text;
     if ($action eq 'requestcourses') {      if ($action eq 'requestcourses') {
         $text = &mt('Receive notification of course requests requiring approval');          $text = &mt('Receive notification of course requests requiring approval');
Line 2684  sub print_studentcode { Line 2270  sub print_studentcode {
     my ($settings,$rowtotal) = @_;      my ($settings,$rowtotal) = @_;
     my $rownum = 0;       my $rownum = 0; 
     my ($output,%current);      my ($output,%current);
     my @crstypes = ('official','unofficial','community','textbook');      my @crstypes = ('official','unofficial','community','textbook','placement');
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{'uniquecode'}) eq 'HASH') {          if (ref($settings->{'uniquecode'}) eq 'HASH') {
             foreach my $type (@crstypes) {              foreach my $type (@crstypes) {
Line 2811  sub print_textbookcourses { Line 2397  sub print_textbookcourses {
         $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';          $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
     }      }
     $datatable .= '</select>&nbsp;'."\n".      $datatable .= '</select>&nbsp;'."\n".
                   '<input type="checkbox" name="'.$type.'_addbook" value="1" />'.&mt('Add').'</span></td>'."\n".                    '<input type="checkbox" name="'.$type.'_addbook" value="1" />'.&mt('Add').'</td>'."\n".
                   '<td colspan="2">'.                    '<td colspan="2">'.
                   '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_addbook_subject" value="" /></span> '."\n".                    '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_addbook_subject" value="" /></span> '."\n".
                   ('&nbsp;'x2).                    ('&nbsp;'x2).
Line 2828  sub print_textbookcourses { Line 2414  sub print_textbookcourses {
         } else {          } else {
             $datatable .= '<input type="file" name="'.$type.'_addbook_image" value="" />';              $datatable .= '<input type="file" name="'.$type.'_addbook_image" value="" />';
         }          }
         $datatable .= '</span>'."\n";  
     }      }
     $datatable .= '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.      $datatable .= '</span>'."\n".
                     '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.
                   &Apache::loncommon::select_dom_form($env{'request.role.domain'},$type.'_addbook_cdom').                    &Apache::loncommon::select_dom_form($env{'request.role.domain'},$type.'_addbook_cdom').
                   '<input type="text" size="25" name="'.$type.'_addbook_cnum" value="" />'.                    '<input type="text" size="25" name="'.$type.'_addbook_cnum" value="" />'.
                   &Apache::loncommon::selectcourse_link                    &Apache::loncommon::selectcourse_link
                       ('display',$type.'_addbook_cnum',$type.'_addbook_cdom',undef,undef,undef,'Course').                        ('display',$type.'_addbook_cnum',$type.'_addbook_cdom',undef,undef,undef,'Course');
                   '</span></td>'."\n".                    '</span></td>'."\n".
                   '</tr>'."\n";                    '</tr>'."\n";
     $itemcount ++;      $itemcount ++;
Line 2936  ENDSCRIPT Line 2522  ENDSCRIPT
   
 sub ltitools_javascript {  sub ltitools_javascript {
     my ($settings) = @_;      my ($settings) = @_;
     my $togglejs = &ltitools_toggle_js();      return unless(ref($settings) eq 'HASH');
     unless (ref($settings) eq 'HASH') {  
         return $togglejs;  
     }  
     my (%ordered,$total,%jstext);      my (%ordered,$total,%jstext);
     $total = 0;      $total = 0;
     foreach my $item (keys(%{$settings})) {      foreach my $item (keys(%{$settings})) {
Line 2957  sub ltitools_javascript { Line 2540  sub ltitools_javascript {
     return <<"ENDSCRIPT";      return <<"ENDSCRIPT";
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
 function reorderLTITools(form,item) {  function reorderLTI(form,item) {
     var changedVal;      var changedVal;
 $jstext  $jstext
     var newpos = 'ltitools_add_pos';      var newpos = 'ltitools_add_pos';
Line 3002  $jstext Line 2585  $jstext
 // ]]>  // ]]>
 </script>  </script>
   
 $togglejs  
   
 ENDSCRIPT  
 }  
   
 sub ltitools_toggle_js {  
     return <<"ENDSCRIPT";  
 <script type="text/javascript">  
 // <![CDATA[  
   
 function toggleLTITools(form,setting,item) {  
     var radioname = '';  
     var divid = '';  
     if (setting == 'user') {  
         divid = 'ltitools_'+setting+'_div_'+item;  
         var checkid = 'ltitools_'+setting+'_field_'+item;  
         if (document.getElementById(divid)) {  
             if (document.getElementById(checkid)) {  
                 if (document.getElementById(checkid).checked) {  
                     document.getElementById(divid).style.display = 'inline-block';  
                 } else {  
                     document.getElementById(divid).style.display = 'none';  
                 }  
             }  
         }  
     }  
     return;  
 }  
 // ]]>  
 </script>  
   
 ENDSCRIPT  
 }  
   
 sub wafproxy_javascript {  
     my ($dom) = @_;  
     return <<"ENDSCRIPT";  
 <script type="text/javascript">  
 // <![CDATA[  
 function updateWAF() {  
     if (document.getElementById('wafproxy_remoteip')) {  
         var wafremote = 0;  
         if (document.display.wafproxy_remoteip.options[document.display.wafproxy_remoteip.selectedIndex].value == 'h') {  
             wafremote = 1;  
         }  
         var fields = new Array('header','trust');  
         for (var i=0; i<fields.length; i++) {  
             if (document.getElementById('wafproxy_'+fields[i])) {  
                 if (wafremote == 1) {  
                     document.getElementById('wafproxy_'+fields[i]).style.display = 'table-row';  
                 }  
                 else {  
                     document.getElementById('wafproxy_'+fields[i]).style.display = 'none';  
                 }  
             }  
         }  
         if (document.getElementById('wafproxyranges_$dom')) {  
             if (wafremote == 1) {  
                 document.getElementById('wafproxyranges_$dom').style.display = 'inline-block';  
             } else {  
                 for (var i=0; i<document.display.wafproxy_vpnaccess.length; i++) {  
                     if (document.display.wafproxy_vpnaccess[i].checked) {  
                         if (document.display.wafproxy_vpnaccess[i].value == 0) {  
                             document.getElementById('wafproxyranges_$dom').style.display = 'none';  
                         }  
                     }  
                 }  
             }  
         }  
     }  
     return;  
 }  
   
 function checkWAF() {  
     if (document.getElementById('wafproxy_remoteip')) {  
         var wafvpn = 0;  
         for (var i=0; i<document.display.wafproxy_vpnaccess.length; i++) {  
             if (document.display.wafproxy_vpnaccess[i].checked) {  
                 if (document.display.wafproxy_vpnaccess[i].value == 1) {  
                     wafvpn = 1;  
                 }  
                 break;  
             }  
         }  
         var vpn = new Array('vpnint','vpnext');  
         for (var i=0; i<vpn.length; i++) {  
             if (document.getElementById('wafproxy_show_'+vpn[i])) {  
                 if (wafvpn == 1) {  
                     document.getElementById('wafproxy_show_'+vpn[i]).style.display = 'table-row';  
                 }  
                 else {  
                     document.getElementById('wafproxy_show_'+vpn[i]).style.display = 'none';  
                 }  
             }  
         }  
         if (document.getElementById('wafproxyranges_$dom')) {  
             if (wafvpn == 1) {  
                 document.getElementById('wafproxyranges_$dom').style.display = 'inline-block';  
             }  
             else if (document.display.wafproxy_remoteip.options[document.display.wafproxy_remoteip.selectedIndex].value != 'h') {  
                 document.getElementById('wafproxyranges_$dom').style.display = 'none';  
             }  
         }  
     }  
     return;  
 }  
   
 function toggleWAF() {  
     if (document.getElementById('wafproxy_table')) {  
         var wafproxy = 0;  
         for (var i=0; i<document.display.wafproxy_${dom}.length; i++) {  
              if (document.display.wafproxy_${dom}[i].checked) {  
                  if (document.display.wafproxy_${dom}[i].value == 1) {  
                      wafproxy = 1;  
                      break;  
                 }  
             }  
         }  
         if (wafproxy == 1) {  
             document.getElementById('wafproxy_table').style.display='inline';  
         }  
         else {  
            document.getElementById('wafproxy_table').style.display='none';  
         }  
         if (document.getElementById('wafproxyrow_${dom}')) {  
             if (wafproxy == 1) {  
                 document.getElementById('wafproxyrow_${dom}').style.display = 'table-row';  
             }  
             else {  
                 document.getElementById('wafproxyrow_${dom}').style.display = 'none';  
             }  
         }  
         if (document.getElementById('nowafproxyrow_$dom')) {  
             if (wafproxy == 1) {  
                 document.getElementById('nowafproxyrow_${dom}').style.display = 'none';  
             }  
             else {  
                 document.getElementById('nowafproxyrow_${dom}').style.display = 'table-row';  
             }  
         }  
     }  
     return;  
 }  
 // ]]>  
 </script>  
   
 ENDSCRIPT  
 }  
   
 sub lti_javascript {  
     my ($dom,$settings) = @_;  
     my $togglejs = &lti_toggle_js($dom);  
     my $linkprot_js = &Apache::courseprefs::linkprot_javascript();  
     return <<"ENDSCRIPT";  
 <script type="text/javascript">  
 // <![CDATA[  
   
 $linkprot_js  
   
 // ]]>  
 </script>  
   
 $togglejs  
   
 ENDSCRIPT  
 }  
   
 sub lti_toggle_js {  
     my ($dom) = @_;  
     my %servers = &Apache::lonnet::get_servers($dom,'library');  
     my $primary = &Apache::lonnet::domain($dom,'primary');  
     my $course_servers = "'".join("','",keys(%servers))."'";  
     return <<"ENDSCRIPT";  
 <script type="text/javascript">  
 // <![CDATA[  
 function toggleLTIEncKey(form) {  
     var shownhosts = new Array();  
     var hiddenhosts = new Array();  
     var forcourse = new Array($course_servers);  
     var fromdomain = '$primary';  
     var crsradio = form.elements['ltisec_crslinkprot'];  
     if (crsradio.length) {  
         for (var i=0; i<crsradio.length; i++) {  
             if (crsradio[i].checked) {  
                 if (crsradio[i].value == 1) {  
                     if (forcourse.length > 0) {  
                         for (var j=0; j<forcourse.length; j++) {  
                             if (!shownhosts.includes(forcourse[j])) {  
                                 shownhosts.push(forcourse[j]);  
                             }  
                         }  
                     }  
                 } else {  
                     if (forcourse.length > 0) {  
                         for (var j=0; j<forcourse.length; j++) {  
                             if (!hiddenhosts.includes(forcourse[j])) {  
                                 hiddenhosts.push(forcourse[j]);  
                             }  
                         }  
                     }  
                 }  
             }  
         }  
     }  
     var domradio = form.elements['ltisec_domlinkprot'];  
     if (domradio.length) {  
         for (var i=0; i<domradio.length; i++) {  
             if (domradio[i].checked) {  
                 if (domradio[i].value == 1) {  
                     if (!shownhosts.includes(fromdomain)) {  
                         shownhosts.push(fromdomain);  
                     }  
                 } else {  
                     if (!hiddenhosts.includes(fromdomain)) {  
                         hiddenhosts.push(fromdomain);  
                     }  
                 }  
             }  
         }  
     }  
     if (shownhosts.length > 0) {  
         for (var i=0; i<shownhosts.length; i++) {  
             if (document.getElementById('ltisec_info_'+shownhosts[i])) {  
                 document.getElementById('ltisec_info_'+shownhosts[i]).style.display = 'block';  
             }  
         }  
         if (document.getElementById('ltisec_noprivkey')) {  
             document.getElementById('ltisec_noprivkey').style.display = 'none';  
         }  
     } else {  
         if (document.getElementById('ltisec_noprivkey')) {  
             document.getElementById('ltisec_noprivkey').style.display = 'inline-block';  
         }  
     }  
     if (hiddenhosts.length > 0) {  
         for (var i=0; i<hiddenhosts.length; i++) {  
             if (!shownhosts.includes(hiddenhosts[i])) {  
                 if (document.getElementById('ltisec_info_'+hiddenhosts[i])) {  
                     document.getElementById('ltisec_info_'+hiddenhosts[i]).style.display = 'none';  
                 }  
             }  
         }  
     }  
     return;  
 }  
   
 function togglePrivKey(form,hostid) {  
     var radioname = '';  
     var currdivid = '';  
     var newdivid = '';  
     if ((document.getElementById('ltisec_divcurrprivkey_'+hostid)) &&  
         (document.getElementById('ltisec_divchgprivkey_'+hostid))) {  
         currdivid = document.getElementById('ltisec_divcurrprivkey_'+hostid);  
         newdivid = document.getElementById('ltisec_divchgprivkey_'+hostid);  
         radioname = form.elements['ltisec_changeprivkey_'+hostid];  
         if (radioname) {  
             if (radioname.length > 0) {  
                 var setvis;  
                 for (var i=0; i<radioname.length; i++) {  
                     if (radioname[i].checked == true) {  
                         if (radioname[i].value == 1) {  
                             newdivid.style.display = 'inline-block';  
                             currdivid.style.display = 'none';  
                             setvis = 1;  
                         }  
                         break;  
                     }  
                 }  
                 if (!setvis) {  
                     newdivid.style.display = 'none';  
                     currdivid.style.display = 'inline-block';  
                 }  
             }  
         }  
     }  
 }  
   
 // ]]>  
 </script>  
   
 ENDSCRIPT  
 }  
   
 sub autoupdate_javascript {  
     return <<"ENDSCRIPT";  
 <script type="text/javascript">  
 // <![CDATA[  
 function toggleLastActiveDays(form) {  
     var radioname = 'lastactive';  
     var divid = 'lastactive_div';  
     var num = form.elements[radioname].length;  
     if (num) {  
         var setvis = '';  
         for (var i=0; i<num; i++) {  
             if (form.elements[radioname][i].checked) {  
                 if (form.elements[radioname][i].value == '1') {  
                     if (document.getElementById(divid)) {  
                         document.getElementById(divid).style.display = 'inline-block';  
                     }  
                     setvis = 1;  
                 }  
                 break;  
             }  
         }  
         if (!setvis) {  
             if (document.getElementById(divid)) {  
                 document.getElementById(divid).style.display = 'none';  
             }  
         }  
     }  
     return;  
 }  
 // ]]>  
 </script>  
   
 ENDSCRIPT  
 }  
   
 sub autoenroll_javascript {  
     return <<"ENDSCRIPT";  
 <script type="text/javascript">  
 // <![CDATA[  
 function toggleFailsafe(form) {  
     var radioname = 'autoenroll_failsafe';  
     var divid = 'autoenroll_failsafe_div';  
     var num = form.elements[radioname].length;  
     if (num) {  
         var setvis = '';  
         for (var i=0; i<num; i++) {  
             if (form.elements[radioname][i].checked) {  
                 if ((form.elements[radioname][i].value == 'zero') || (form.elements[radioname][i].value == 'any')) {  
                     if (document.getElementById(divid)) {  
                         document.getElementById(divid).style.display = 'inline-block';  
                     }  
                     setvis = 1;  
                 }  
                 break;  
             }  
         }  
         if (!setvis) {  
             if (document.getElementById(divid)) {  
                 document.getElementById(divid).style.display = 'none';  
             }  
         }  
     }  
     return;  
 }  
 // ]]>  
 </script>  
   
 ENDSCRIPT  
 }  
   
 sub saml_javascript {  
     return <<"ENDSCRIPT";  
 <script type="text/javascript">  
 // <![CDATA[  
 function toggleSamlOptions(form,hostid) {  
     var radioname = 'saml_'+hostid;  
     var tablecellon = 'samloptionson_'+hostid;  
     var tablecelloff = 'samloptionsoff_'+hostid;  
     var num = form.elements[radioname].length;  
     if (num) {  
         var setvis = '';  
         for (var i=0; i<num; i++) {  
             if (form.elements[radioname][i].checked) {  
                 if (form.elements[radioname][i].value == '1') {  
                     if (document.getElementById(tablecellon)) {  
                         document.getElementById(tablecellon).style.display='';  
                     }  
                     if (document.getElementById(tablecelloff)) {  
                         document.getElementById(tablecelloff).style.display='none';  
                     }  
                     setvis = 1;  
                 }  
                 break;  
             }  
         }  
         if (!setvis) {  
             if (document.getElementById(tablecellon)) {  
                 document.getElementById(tablecellon).style.display='none';  
             }  
             if (document.getElementById(tablecelloff)) {  
                 document.getElementById(tablecelloff).style.display='';  
             }  
         }  
     }  
     return;  
 }  
 // ]]>  
 </script>  
   
 ENDSCRIPT  
 }  
   
 sub ipaccess_javascript {  
     my ($settings) = @_;  
     my (%ordered,$total,%jstext);  
     $total = 0;  
     if (ref($settings) eq 'HASH') {  
         foreach my $item (keys(%{$settings})) {  
             if (ref($settings->{$item}) eq 'HASH') {  
                 my $num = $settings->{$item}{'order'};  
                 $ordered{$num} = $item;  
             }  
         }  
         $total = scalar(keys(%{$settings}));  
     }  
     my @jsarray = ();  
     foreach my $item (sort {$a <=> $b } (keys(%ordered))) {  
         push(@jsarray,$ordered{$item});  
     }  
     my $jstext = '    var ipaccess = Array('."'".join("','",@jsarray)."'".');'."\n";  
     return <<"ENDSCRIPT";  
 <script type="text/javascript">  
 // <![CDATA[  
 function reorderIPaccess(form,item) {  
     var changedVal;  
 $jstext  
     var newpos = 'ipaccess_pos_add';  
     var maxh = 1 + $total;  
     var current = new Array;  
     var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;  
     if (item == newpos) {  
         changedVal = newitemVal;  
     } else {  
         changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;  
         current[newitemVal] = newpos;  
     }  
     for (var i=0; i<ipaccess.length; i++) {  
         var elementName = 'ipaccess_pos_'+ipaccess[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  ENDSCRIPT
 }  }
   
 sub print_autoenroll {  sub print_autoenroll {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my $autorun = &Apache::lonnet::auto_run(undef,$dom),      my $autorun = &Apache::lonnet::auto_run(undef,$dom),
     my ($defdom,$runon,$runoff,$coownerson,$coownersoff,      my ($defdom,$runon,$runoff,$coownerson,$coownersoff,$failsafe);
         $failsafe,$autofailsafe,$failsafesty,%failsafechecked);  
     $failsafesty = 'none';  
     %failsafechecked = (  
         off => ' checked="checked"',  
     );  
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (exists($settings->{'run'})) {          if (exists($settings->{'run'})) {
             if ($settings->{'run'} eq '0') {              if ($settings->{'run'} eq '0') {
Line 3507  sub print_autoenroll { Line 2625  sub print_autoenroll {
         if (exists($settings->{'sender_domain'})) {          if (exists($settings->{'sender_domain'})) {
             $defdom = $settings->{'sender_domain'};              $defdom = $settings->{'sender_domain'};
         }          }
         if (exists($settings->{'failsafe'})) {          if (exists($settings->{'autofailsafe'})) {
             $failsafe = $settings->{'failsafe'};              $failsafe = $settings->{'autofailsafe'};
             if ($failsafe eq 'zero') {  
                 $failsafechecked{'zero'} = ' checked="checked"';  
                 $failsafechecked{'off'} = '';  
                 $failsafesty = 'inline-block';  
             } elsif ($failsafe eq 'any') {  
                 $failsafechecked{'any'} = ' checked="checked"';  
                 $failsafechecked{'off'} = '';  
             }  
             $autofailsafe = $settings->{'autofailsafe'};  
         } elsif (exists($settings->{'autofailsafe'})) {  
             $autofailsafe = $settings->{'autofailsafe'};  
             if ($autofailsafe ne '') {  
                 $failsafechecked{'zero'} = ' checked="checked"';  
                 $failsafe = 'zero';  
                 $failsafechecked{'off'} = '';  
             }  
         }          }
     } else {      } else {
         if ($autorun) {          if ($autorun) {
Line 3563  sub print_autoenroll { Line 2665  sub print_autoenroll {
                   $coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.                    $coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.
                   '</tr><tr>'.                    '</tr><tr>'.
                   '<td>'.&mt('Failsafe for no drops when institutional data missing').'</td>'.                    '<td>'.&mt('Failsafe for no drops when institutional data missing').'</td>'.
                   '<td class="LC_left_item"><span class="LC_nobreak">'.                    '<td class="LC_right_item"><span class="LC_nobreak">'.
                   '<span class="LC_nobreak"><label><input type="radio" name="autoenroll_failsafe" value="off" onclick="toggleFailsafe(this.form)"'.$failsafechecked{'off'}.' />'.&mt('Not in use').'</label></span>&nbsp;&nbsp;&nbsp; '.                    '<input type="text" name="autoenroll_failsafe"'.
                   '<span class="LC_nobreak"><label><input type="radio" name="autoenroll_failsafe" value="zero" onclick="toggleFailsafe(this.form)"'.$failsafechecked{'zero'}.' />'.&mt('Retrieved section enrollment is zero').'</label></span><br />'.                    ' value="'.$failsafe.'" size="4" /></td></tr>';
                   '<span class="LC_nobreak"><label><input type="radio" name="autoenroll_failsafe" value="any" onclick="toggleFailsafe(this.form)"'.$failsafechecked{'any'}.' />'.&mt('Retrieved section enrollment is zero or greater').'</label></span>'.  
                   '<div class="LC_floatleft" style="display:'.$failsafesty.';" id="autoenroll_failsafe_div">'.  
                   '<span class="LC_nobreak">'.  
                   &mt('Threshold for number of students in section to drop: [_1]',  
                       '<input type="text" name="autoenroll_autofailsafe" value="'.$autofailsafe.'" size="4" />').  
                   '</span></div></td></tr>';  
     $$rowtotal += 4;      $$rowtotal += 4;
     return $datatable;      return $datatable;
 }  }
   
 sub print_autoupdate {  sub print_autoupdate {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($enable,$datatable);      my $datatable;
     if ($position eq 'top') {      if ($position eq 'top') {
         my %choices = &Apache::lonlocal::texthash (  
                           run        => 'Auto-update active?',  
                           classlists => 'Update information in classlists?',  
                           unexpired  => 'Skip updates for users without active or future roles?',  
                           lastactive => 'Skip updates for inactive users?',  
         );  
         my $itemcount = 0;  
         my $updateon = ' ';          my $updateon = ' ';
         my $updateoff = ' checked="checked" ';          my $updateoff = ' checked="checked" ';
           my $classlistson = ' ';
           my $classlistsoff = ' checked="checked" ';
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if ($settings->{'run'} eq '1') {              if ($settings->{'run'} eq '1') {
                 $updateon = $updateoff;                  $updateon = $updateoff;
                 $updateoff = ' ';                  $updateoff = ' ';
             }              }
               if ($settings->{'classlists'} eq '1') {
                   $classlistson = $classlistsoff;
                   $classlistsoff = ' ';
               }
         }          }
         $enable = '<tr class="LC_odd_row">'.           my %title = (
                   '<td>'.&mt($choices{'run'}).'</td>'.                     run => 'Auto-update active?',
                   '<td class="LC_left_item"><span class="LC_nobreak"><label>'.                     classlists => 'Update information in classlists?',
                       );
           $datatable = '<tr class="LC_odd_row">'. 
                     '<td>'.&mt($title{'run'}).'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                   '<input type="radio" name="autoupdate_run"'.                    '<input type="radio" name="autoupdate_run"'.
                   $updateoff.'value="0" />'.&mt('No').'</label>&nbsp;'.                    $updateon.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                   '<label><input type="radio" name="autoupdate_run"'.                    '<label><input type="radio" name="autoupdate_run"'.
                   $updateon.'value="1" />'.&mt('Yes').'</label></span></td>'.                    $updateoff.'value="0" />'.&mt('No').'</label></span></td>'.
                     '</tr><tr>'.
                     '<td>'.&mt($title{'classlists'}).'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak">'.
                     '<label><input type="radio" name="classlists"'.
                     $classlistson.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                     '<label><input type="radio" name="classlists"'.
                     $classlistsoff.'value="0" />'.&mt('No').'</label></span></td>'.
                   '</tr>';                    '</tr>';
         my @toggles = ('classlists','unexpired');          $$rowtotal += 2;
         my %defaultchecked = ('classlists' => 'off',  
                               'unexpired'  => 'off'  
                               );  
         $$rowtotal ++;  
         ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,  
                                                      \%choices,$itemcount,'','','left','no');  
         $datatable = $enable.$datatable;  
         $$rowtotal += $itemcount;  
         my $lastactiveon = ' ';  
         my $lastactiveoff = ' checked="checked" ';  
         my $lastactivestyle = 'none';  
         my $lastactivedays;  
         my $onclick = ' onclick="javascript:toggleLastActiveDays(this.form);"';  
         if (ref($settings) eq 'HASH') {  
             if ($settings->{'lastactive'} =~ /^\d+$/) {  
                 $lastactiveon = $lastactiveoff;  
                 $lastactiveoff = ' ';  
                 $lastactivestyle = 'inline-block';  
                 $lastactivedays = $settings->{'lastactive'};  
             }  
         }  
         my $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'>'.  
                       '<td>'.$choices{'lastactive'}.'</td>'.  
                       '<td class="LC_left_item"><span class="LC_nobreak"><label>'.  
                       '<input type="radio" name="lastactive"'.  
                       $lastactiveoff.'value="0"'.$onclick.' />'.&mt('No').'</label>'.  
                       '&nbsp;<label>'.  
                       '<input type="radio" name="lastactive"'.  
                       $lastactiveon.' value="1"'.$onclick.' />'.&mt('Yes').'</label>'.  
                       '<div id="lastactive_div" style="display:'.$lastactivestyle.';">'.  
                       ':&nbsp;'.&mt('inactive = no activity in last [_1] days',  
                           '<input type="text" size="5" name="lastactivedays" value="'.  
                           $lastactivedays.'" />').  
                       '</span></td>'.  
                       '</tr>';  
         $$rowtotal ++;  
     } elsif ($position eq 'middle') {      } elsif ($position eq 'middle') {
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);          my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
         my $numinrow = 3;          my $numinrow = 3;
         my $locknamesettings;          my $locknamesettings;
         $datatable .= &insttypes_row($settings,$types,$usertypes,          $datatable .= &insttypes_row($settings,$types,$usertypes,
                                      $dom,$numinrow,$othertitle,                                       $dom,$numinrow,$othertitle,
                                     'lockablenames',$rowtotal);                                      'lockablenames');
         $$rowtotal ++;          $$rowtotal ++;
     } else {      } else {
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);          my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
Line 3790  sub print_directorysrch { Line 2859  sub print_directorysrch {
         if (ref($usertypes) eq 'HASH') {          if (ref($usertypes) eq 'HASH') {
             if (keys(%{$usertypes}) > 0) {              if (keys(%{$usertypes}) > 0) {
                 $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,                  $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,
                                              $numinrow,$othertitle,'cansearch',                                               $numinrow,$othertitle,'cansearch');
                                              $rowtotal);  
                 $cansrchrow = 1;                  $cansrchrow = 1;
             }              }
         }          }
Line 3876  sub print_directorysrch { Line 2944  sub print_directorysrch {
 }  }
   
 sub print_contacts {  sub print_contacts {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my $datatable;      my $datatable;
     my @contacts = ('adminemail','supportemail');      my @contacts = ('adminemail','supportemail');
     my (%checked,%to,%otheremails,%bccemails,%includestr,%includeloc,%currfield,      my (%checked,%to,%otheremails,%bccemails);
         $maxsize,$fields,$fieldtitles,$fieldoptions,$possoptions,@mailings,%lonstatus);      my @mailings = ('errormail','packagesmail','lonstatusmail','helpdeskmail',
     if ($position eq 'top') {                      'requestsmail','updatesmail','idconflictsmail');
         if (ref($settings) eq 'HASH') {      foreach my $type (@mailings) {
             foreach my $item (@contacts) {          $otheremails{$type} = '';
                 if (exists($settings->{$item})) {  
                     $to{$item} = $settings->{$item};  
                 }  
             }  
         }  
     } elsif ($position eq 'middle') {  
         @mailings = ('errormail','packagesmail','lonstatusmail','requestsmail',  
                      'updatesmail','idconflictsmail','hostipmail');  
         foreach my $type (@mailings) {  
             $otheremails{$type} = '';  
         }  
     } elsif ($position eq 'lower') {  
         if (ref($settings) eq 'HASH') {  
             if (ref($settings->{'lonstatus'}) eq 'HASH') {  
                 %lonstatus = %{$settings->{'lonstatus'}};  
             }  
         }  
     } else {  
         @mailings = ('helpdeskmail','otherdomsmail');  
         foreach my $type (@mailings) {  
             $otheremails{$type} = '';  
         }  
         $bccemails{'helpdeskmail'} = '';  
         $bccemails{'otherdomsmail'} = '';  
         $includestr{'helpdeskmail'} = '';  
         $includestr{'otherdomsmail'} = '';  
         ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();  
     }      }
       $bccemails{'helpdeskmail'} = '';
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         unless (($position eq 'top') || ($position eq 'lower')) {          foreach my $item (@contacts) {
             foreach my $type (@mailings) {              if (exists($settings->{$item})) {
                 if (exists($settings->{$type})) {                  $to{$item} = $settings->{$item};
                     if (ref($settings->{$type}) eq 'HASH') {  
                         foreach my $item (@contacts) {  
                             if ($settings->{$type}{$item}) {  
                                 $checked{$type}{$item} = ' checked="checked" ';  
                             }  
                         }  
                         $otheremails{$type} = $settings->{$type}{'others'};  
                         if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {  
                             $bccemails{$type} = $settings->{$type}{'bcc'};  
                             if ($settings->{$type}{'include'} ne '') {  
                                 ($includeloc{$type},$includestr{$type}) = split(/:/,$settings->{$type}{'include'},2);  
                                 $includestr{$type} = &unescape($includestr{$type});  
                             }  
                         }  
                     }  
                 } elsif ($type eq 'lonstatusmail') {  
                     $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';  
                 }  
             }              }
         }          }
         if ($position eq 'bottom') {          foreach my $type (@mailings) {
             foreach my $type (@mailings) {              if (exists($settings->{$type})) {
                 $bccemails{$type} = $settings->{$type}{'bcc'};                  if (ref($settings->{$type}) eq 'HASH') {
                 if ($settings->{$type}{'include'} ne '') {                      foreach my $item (@contacts) {
                     ($includeloc{$type},$includestr{$type}) = split(/:/,$settings->{$type}{'include'},2);                          if ($settings->{$type}{$item}) {
                     $includestr{$type} = &unescape($includestr{$type});                              $checked{$type}{$item} = ' checked="checked" ';
                 }                          }
             }  
             if (ref($settings->{'helpform'}) eq 'HASH') {  
                 if (ref($fields) eq 'ARRAY') {  
                     foreach my $field (@{$fields}) {  
                         $currfield{$field} = $settings->{'helpform'}{$field};  
                     }                      }
                 }                      $otheremails{$type} = $settings->{$type}{'others'};
                 if (exists($settings->{'helpform'}{'maxsize'})) {                      if ($type eq 'helpdeskmail') {
                     $maxsize = $settings->{'helpform'}{'maxsize'};                          $bccemails{$type} = $settings->{$type}{'bcc'};
                 } else {  
                     $maxsize = '1.0';  
                 }  
             } else {  
                 if (ref($fields) eq 'ARRAY') {  
                     foreach my $field (@{$fields}) {  
                         $currfield{$field} = 'yes';  
                     }                      }
                 }                  }
                 $maxsize = '1.0';              } elsif ($type eq 'lonstatusmail') {
                   $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';
             }              }
         }          }
     } else {      } else {
         if ($position eq 'top') {          $to{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};
             $to{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};          $to{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'};
             $to{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'};          $checked{'errormail'}{'adminemail'} = ' checked="checked" ';
             $checked{'errormail'}{'adminemail'} = ' checked="checked" ';          $checked{'packagesmail'}{'adminemail'} = ' checked="checked" ';
             $checked{'packagesmail'}{'adminemail'} = ' checked="checked" ';          $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';
             $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';          $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" '; 
             $checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';          $checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';
             $checked{'updatesmail'}{'adminemail'} = ' checked="checked" ';          $checked{'updatesmail'}{'adminemail'} = ' checked="checked" ';
             $checked{'idconflictsmail'}{'adminemail'} = ' checked="checked" ';          $checked{'idconflictsmail'}{'adminemail'} = ' checked="checked" ';
             $checked{'hostipmail'}{'adminemail'} = ' checked="checked" ';  
         } elsif ($position eq 'bottom') {  
             $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';  
             $checked{'otherdomsmail'}{'supportemail'} = ' checked="checked" ';  
             if (ref($fields) eq 'ARRAY') {  
                 foreach my $field (@{$fields}) {  
                     $currfield{$field} = 'yes';  
                 }  
             }  
             $maxsize = '1.0';  
         }  
     }      }
     my ($titles,$short_titles) = &contact_titles();      my ($titles,$short_titles) = &contact_titles();
     my $rownum = 0;      my $rownum = 0;
     my $css_class;      my $css_class;
     if ($position eq 'top') {      foreach my $item (@contacts) {
         foreach my $item (@contacts) {  
             $css_class = $rownum%2?' class="LC_odd_row"':'';  
             $datatable .= '<tr'.$css_class.'>'.   
                           '<td><span class="LC_nobreak">'.$titles->{$item}.  
                           '</span></td><td class="LC_right_item">'.  
                           '<input type="text" name="'.$item.'" value="'.  
                           $to{$item}.'" /></td></tr>';  
             $rownum ++;  
         }  
     } 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>'.&mt('Extra helpdesk form fields:').'<br />'.                    '<td><span class="LC_nobreak">'.$titles->{$item}.
                       &mt('(e-mail, subject, and description always shown)').                    '</span></td><td class="LC_right_item">'.
                       '</td><td class="LC_left_item">';                    '<input type="text" name="'.$item.'" value="'.
         if ((ref($fields) eq 'ARRAY') && (ref($fieldtitles) eq 'HASH') &&                    $to{$item}.'" /></td></tr>';
             (ref($fieldoptions) eq 'HASH') && (ref($possoptions) eq 'HASH')) {  
             $datatable .= '<table><tr><th>'.&mt('Field').'</th><th>'.&mt('Status').'</th></tr>';  
             foreach my $field (@{$fields}) {  
                 $datatable .= '<tr><td>'.$fieldtitles->{$field};  
                 if (($field eq 'screenshot') || ($field eq 'cc')) {  
                     $datatable .= ' '.&mt('(logged-in users)');  
                 }  
                 $datatable .='</td><td>';  
                 my $clickaction;  
                 if ($field eq 'screenshot') {  
                     $clickaction = ' onclick="screenshotSize(this);"';  
                 }  
                 if (ref($possoptions->{$field}) eq 'ARRAY') {  
                     foreach my $option (@{$possoptions->{$field}}) {  
                         my $checked;  
                         if ($currfield{$field} eq $option) {  
                             $checked = ' checked="checked"';  
                         }  
                         $datatable .= '<span class="LC_nobreak"><label>'.  
                                       '<input type="radio" name="helpform_'.$field.'" '.  
                                       'value="'.$option.'"'.$checked.$clickaction.' />'.$fieldoptions->{$option}.  
                                       '</label></span>'.('&nbsp;'x2);  
                     }  
                 }  
                 if ($field eq 'screenshot') {  
                     my $display;  
                     if ($currfield{$field} eq 'no') {  
                         $display = ' style="display:none"';  
                     }  
                     $datatable .= '</td></tr><tr id="help_screenshotsize"'.$display.'>'.  
                                   '<td>'.&mt('Maximum size for upload (MB)').'</td><td>'.  
                                   '<input type="text" size="5" name="helpform_maxsize" value="'.$maxsize.'" />';  
                 }  
                 $datatable .= '</td></tr>';  
             }  
             $datatable .= '</table>';  
         }  
         $datatable .= '</td></tr>'."\n";  
         $rownum ++;          $rownum ++;
     }      }
     unless (($position eq 'top') || ($position eq 'lower')) {      foreach my $type (@mailings) {
         foreach my $type (@mailings) {  
             $css_class = $rownum%2?' class="LC_odd_row"':'';  
             $datatable .= '<tr'.$css_class.'>'.  
                           '<td><span class="LC_nobreak">'.  
                           $titles->{$type}.': </span></td>'.  
                           '<td class="LC_left_item">';  
             if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {  
                 $datatable .= '<fieldset><legend>'.&mt('E-mail recipient(s)').'</legend>';  
             }  
             $datatable .= '<span class="LC_nobreak">';  
             foreach my $item (@contacts) {  
                 $datatable .= '<label>'.  
                               '<input type="checkbox" name="'.$type.'"'.  
                               $checked{$type}{$item}.  
                               ' value="'.$item.'" />'.$short_titles->{$item}.  
                               '</label>&nbsp;';  
             }  
             $datatable .= '</span><br />'.&mt('Others').':&nbsp;&nbsp;'.  
                           '<input type="text" name="'.$type.'_others" '.  
                           'value="'.$otheremails{$type}.'"  />';  
             my %locchecked;  
             if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {  
                 foreach my $loc ('s','b') {  
                     if ($includeloc{$type} eq $loc) {  
                         $locchecked{$loc} = ' checked="checked"';  
                         last;  
                     }  
                 }  
                 $datatable .= '<br />'.&mt('Bcc:').('&nbsp;'x6).  
                               '<input type="text" name="'.$type.'_bcc" '.  
                               'value="'.$bccemails{$type}.'"  /></fieldset>'.  
                               '<fieldset><legend>'.&mt('Optional added text').'</legend>'.  
                               &mt('Text automatically added to e-mail:').' '.  
                               '<input type="text" name="'.$type.'_includestr" value="'.$includestr{$type}.'" /><br />'.  
                               '<span class="LC_nobreak">'.&mt('Location:').'&nbsp;'.  
                               '<label><input type="radio" name="'.$type.'_includeloc" value="s"'.$locchecked{'s'}.' />'.&mt('in subject').'</label>'.  
                               ('&nbsp;'x2).  
                               '<label><input type="radio" name="'.$type.'_includeloc" value="b"'.$locchecked{'b'}.' />'.&mt('in body').'</label>'.  
                               '</span></fieldset>';  
             }  
             $datatable .= '</td></tr>'."\n";  
             $rownum ++;  
         }  
     }  
     if ($position eq 'middle') {  
         my %choices;  
         my $corelink = &core_link_msu();  
         $choices{'reporterrors'} = &mt('E-mail error reports to [_1]',$corelink);  
         $choices{'reportupdates'} = &mt('E-mail record of completed LON-CAPA updates to [_1]',  
                                         $corelink);  
         $choices{'reportstatus'} = &mt('E-mail status if errors above threshold to [_1]',$corelink);  
         my @toggles = ('reporterrors','reportupdates','reportstatus');  
         my %defaultchecked = ('reporterrors'  => 'on',  
                               'reportupdates' => 'on',  
                               'reportstatus'  => 'on');  
         (my $reports,$rownum) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,  
                                                    \%choices,$rownum);  
         $datatable .= $reports;  
     } elsif ($position eq 'lower') {  
         my (%current,%excluded,%weights);  
         my ($defaults,$names) = &Apache::loncommon::lon_status_items();  
         if ($lonstatus{'threshold'} =~ /^\d+$/) {  
             $current{'errorthreshold'} = $lonstatus{'threshold'};  
         } else {  
             $current{'errorthreshold'} = $defaults->{'threshold'};  
         }  
         if ($lonstatus{'sysmail'} =~ /^\d+$/) {  
             $current{'errorsysmail'} = $lonstatus{'sysmail'};  
         } else {  
             $current{'errorsysmail'} = $defaults->{'sysmail'};  
         }  
         if (ref($lonstatus{'weights'}) eq 'HASH') {  
             foreach my $type ('E','W','N','U') {  
                 if ($lonstatus{'weights'}{$type} =~ /^\d+$/) {  
                     $weights{$type} = $lonstatus{'weights'}{$type};  
                 } else {  
                     $weights{$type} = $defaults->{$type};  
                 }  
             }  
         } else {  
             foreach my $type ('E','W','N','U') {  
                 $weights{$type} = $defaults->{$type};  
             }  
         }  
         if (ref($lonstatus{'excluded'}) eq 'ARRAY') {  
             if (@{$lonstatus{'excluded'}} > 0) {  
                 map {$excluded{$_} = 1; } @{$lonstatus{'excluded'}};  
             }  
         }  
         foreach my $item ('errorthreshold','errorsysmail') {  
             $css_class = $rownum%2?' class="LC_odd_row"':'';  
             $datatable .= '<tr'.$css_class.'>'.  
                           '<td class="LC_left_item"><span class="LC_nobreak">'.  
                           $titles->{$item}.  
                           '</span></td><td class="LC_left_item">'.  
                           '<input type="text" name="'.$item.'" value="'.  
                           $current{$item}.'" size="5" /></td></tr>';  
             $rownum ++;  
         }  
         $css_class = $rownum%2?' class="LC_odd_row"':'';          $css_class = $rownum%2?' class="LC_odd_row"':'';
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                         '<td><span class="LC_nobreak">'.
                         $titles->{$type}.': </span></td>'.
                       '<td class="LC_left_item">'.                        '<td class="LC_left_item">'.
                       '<span class="LC_nobreak">'.$titles->{'errorweights'}.                        '<span class="LC_nobreak">';
                       '</span></td><td class="LC_left_item"><table><tr>';          foreach my $item (@contacts) {
         foreach my $type ('E','W','N','U') {              $datatable .= '<label>'.
             $datatable .= '<td>'.$names->{$type}.'<br />'.                            '<input type="checkbox" name="'.$type.'"'.
                           '<input type="text" name="errorweights_'.$type.'" value="'.                            $checked{$type}{$item}.
                           $weights{$type}.'" size="5" /></td>';                            ' value="'.$item.'" />'.$short_titles->{$item}.
         }                            '</label>&nbsp;';
         $datatable .= '</tr></table></tr>';          }
         $rownum ++;          $datatable .= '</span><br />'.&mt('Others').':&nbsp;&nbsp;'.
         $css_class = $rownum%2?' class="LC_odd_row"':'';                        '<input type="text" name="'.$type.'_others" '.
         $datatable .= '<tr'.$css_class.'><td class="LC_left_item">'.                        'value="'.$otheremails{$type}.'"  />';
                       $titles->{'errorexcluded'}.'</td>'.          if ($type eq 'helpdeskmail') {
                       '<td class="LC_left_item"><table>';              $datatable .= '<br />'.&mt('Bcc:').('&nbsp;'x6).
         my $numinrow = 4;                            '<input type="text" name="'.$type.'_bcc" '.
         my @ids = sort(values(%Apache::lonnet::serverhomeIDs));                            'value="'.$bccemails{$type}.'"  />';
         for (my $i=0; $i<@ids; $i++) {  
             my $rem = $i%($numinrow);  
             if ($rem == 0) {  
                 if ($i > 0) {  
                     $datatable .= '</tr>';  
                 }  
                 $datatable .= '<tr>';  
             }  
             my $check;  
             if ($excluded{$ids[$i]}) {  
                 $check = ' checked="checked" ';  
             }  
             $datatable .= '<td class="LC_left_item">'.  
                           '<span class="LC_nobreak"><label>'.  
                           '<input type="checkbox" name="errorexcluded" '.  
                           'value="'.$ids[$i].'"'.$check.' />'.  
                           $ids[$i].'</label></span></td>';  
         }  
         my $colsleft = $numinrow - @ids%($numinrow);  
         if ($colsleft > 1 ) {  
             $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.  
                           '&nbsp;</td>';  
         } elsif ($colsleft == 1) {  
             $datatable .= '<td class="LC_left_item">&nbsp;</td>';  
         }          }
         $datatable .= '</tr></table></td></tr>';          $datatable .= '</td></tr>'."\n";
         $rownum ++;          $rownum ++;
     } elsif ($position eq 'bottom') {  
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
         my (@posstypes,%usertypeshash);  
         if (ref($types) eq 'ARRAY') {  
             @posstypes = @{$types};  
         }  
         if (@posstypes) {  
             if (ref($usertypes) eq 'HASH') {  
                 %usertypeshash = %{$usertypes};  
             }  
             my @overridden;  
             my $numinrow = 4;  
             if (ref($settings) eq 'HASH') {  
                 if (ref($settings->{'overrides'}) eq 'HASH') {  
                     foreach my $key (sort(keys(%{$settings->{'overrides'}}))) {  
                         if (ref($settings->{'overrides'}{$key}) eq 'HASH') {  
                             push(@overridden,$key);  
                             foreach my $item (@contacts) {  
                                 if ($settings->{'overrides'}{$key}{$item}) {  
                                     $checked{'override_'.$key}{$item} = ' checked="checked" ';  
                                 }  
                             }  
                             $otheremails{'override_'.$key} = $settings->{'overrides'}{$key}{'others'};  
                             $bccemails{'override_'.$key} = $settings->{'overrides'}{$key}{'bcc'};  
                             $includeloc{'override_'.$key} = '';  
                             $includestr{'override_'.$key} = '';  
                             if ($settings->{'overrides'}{$key}{'include'} ne '') {  
                                 ($includeloc{'override_'.$key},$includestr{'override_'.$key}) =  
                                     split(/:/,$settings->{'overrides'}{$key}{'include'},2);  
                                 $includestr{'override_'.$key} = &unescape($includestr{'override_'.$key});  
                             }  
                         }  
                     }  
                 }  
             }  
             my $customclass = 'LC_helpdesk_override';  
             my $optionsprefix = 'LC_options_helpdesk_';  
   
             my $onclicktypes = "toggleHelpdeskRow(this.form,'overrides','$customclass','$optionsprefix');";  
   
             $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,  
                                          $numinrow,$othertitle,'overrides',  
                                          \$rownum,$onclicktypes,$customclass);  
             $rownum ++;  
             $usertypeshash{'default'} = $othertitle;  
             foreach my $status (@posstypes) {  
                 my $css_class;  
                 if ($rownum%2) {  
                     $css_class = 'LC_odd_row ';  
                 }  
                 $css_class .= $customclass;  
                 my $rowid = $optionsprefix.$status;  
                 my $hidden = 1;  
                 my $currstyle = 'display:none';  
                 if (grep(/^\Q$status\E$/,@overridden)) {  
                     $currstyle = 'display:table-row';  
                     $hidden = 0;  
                 }  
                 my $key = 'override_'.$status;  
                 $datatable .= &overridden_helpdesk($checked{$key},$otheremails{$key},$bccemails{$key},  
                                                   $includeloc{$key},$includestr{$key},$status,$rowid,  
                                                   $usertypeshash{$status},$css_class,$currstyle,  
                                                   \@contacts,$short_titles);  
                 unless ($hidden) {  
                     $rownum ++;  
                 }  
             }  
         }  
     }      }
       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 core_link_msu {  
     return &Apache::loncommon::modal_link('http://loncapa.org/core.html',  
                                           &mt('LON-CAPA core group - MSU'),600,500);  
 }  
   
 sub overridden_helpdesk {  
     my ($checked,$otheremails,$bccemails,$includeloc,$includestr,$type,$rowid,  
         $typetitle,$css_class,$rowstyle,$contacts,$short_titles) = @_;  
     my $class = 'LC_left_item';  
     if ($css_class) {  
         $css_class = ' class="'.$css_class.'"';  
     }  
     if ($rowid) {  
         $rowid = ' id="'.$rowid.'"';  
     }  
     if ($rowstyle) {  
         $rowstyle = ' style="'.$rowstyle.'"';  
     }  
     my ($output,$description);  
     $description = &mt('Helpdesk requests from: [_1] in this domain (overrides default)',"<b>$typetitle</b>");  
     $output = '<tr'.$css_class.$rowid.$rowstyle.'>'.  
               "<td>$description</td>\n".  
               '<td class="'.$class.'" colspan="2">'.  
               '<fieldset><legend>'.&mt('E-mail recipient(s)').'</legend>'.  
               '<span class="LC_nobreak">';  
     if (ref($contacts) eq 'ARRAY') {  
         foreach my $item (@{$contacts}) {  
             my $check;  
             if (ref($checked) eq 'HASH') {  
                $check = $checked->{$item};  
             }  
             my $title;  
             if (ref($short_titles) eq 'HASH') {  
                 $title = $short_titles->{$item};  
             }  
             $output .= '<label>'.  
                        '<input type="checkbox" name="override_'.$type.'"'.$check.  
                        ' value="'.$item.'" />'.$title.'</label>&nbsp;';  
         }  
     }  
     $output .= '</span><br />'.&mt('Others').':&nbsp;&nbsp;'.  
                '<input type="text" name="override_'.$type.'_others" '.  
                'value="'.$otheremails.'"  />';  
     my %locchecked;  
     foreach my $loc ('s','b') {  
         if ($includeloc eq $loc) {  
             $locchecked{$loc} = ' checked="checked"';  
             last;  
         }  
     }  
     $output .= '<br />'.&mt('Bcc:').('&nbsp;'x6).  
                '<input type="text" name="override_'.$type.'_bcc" '.  
                'value="'.$bccemails.'"  /></fieldset>'.  
                '<fieldset><legend>'.&mt('Optional added text').'</legend>'.  
                &mt('Text automatically added to e-mail:').' '.  
                '<input type="text" name="override_'.$type.'_includestr" value="'.$includestr.'" /><br />'.  
                '<span class="LC_nobreak">'.&mt('Location:').'&nbsp;'.  
                '<label><input type="radio" name="override_'.$type.'_includeloc" value="s"'.$locchecked{'s'}.' />'.&mt('in subject').'</label>'.  
                ('&nbsp;'x2).  
                '<label><input type="radio" name="override_'.$type.'_includeloc" value="b"'.$locchecked{'b'}.' />'.&mt('in body').'</label>'.  
                '</span></fieldset>'.  
                '</td></tr>'."\n";  
     return $output;  
 }  
   
 sub contacts_javascript {  
     return <<"ENDSCRIPT";  
   
 <script type="text/javascript">  
 // <![CDATA[  
   
 function screenshotSize(field) {  
     if (document.getElementById('help_screenshotsize')) {  
         if (field.value == 'no') {  
             document.getElementById('help_screenshotsize').style.display="none";  
         } else {  
             document.getElementById('help_screenshotsize').style.display="";  
         }  
     }  
     return;  
 }  
   
 function toggleHelpdeskRow(form,checkbox,target,prefix,docount) {  
     if (form.elements[checkbox].length != undefined) {  
         var count = 0;  
         if (docount) {  
             for (var i=0; i<form.elements[checkbox].length; i++) {  
                 if (form.elements[checkbox][i].checked) {  
                     count ++;  
                 }  
             }  
         }  
         for (var i=0; i<form.elements[checkbox].length; i++) {  
             var type = form.elements[checkbox][i].value;  
             if (document.getElementById(prefix+type)) {  
                 if (form.elements[checkbox][i].checked) {  
                     document.getElementById(prefix+type).style.display = 'table-row';  
                     if (count % 2 == 1) {  
                         document.getElementById(prefix+type).className = target+' LC_odd_row';  
                     } else {  
                         document.getElementById(prefix+type).className = target;  
                     }  
                     count ++;  
                 } else {  
                     document.getElementById(prefix+type).style.display = 'none';  
                 }  
             }  
         }  
     }  
     return;  
 }  
   
 // ]]>  
 </script>  
   
 ENDSCRIPT  
 }  
   
 sub print_helpsettings {  sub print_helpsettings {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my $confname = $dom.'-domainconfig';      my $confname = $dom.'-domainconfig';
     my $formname = 'display';  
     my ($datatable,$itemcount);      my ($datatable,$itemcount);
     if ($position eq 'top') {      if ($position eq 'top') {
         $itemcount = 1;          $itemcount = 1;
Line 4401  sub print_helpsettings { Line 3060  sub print_helpsettings {
     } else {      } else {
         my $css_class;          my $css_class;
         my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');          my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');
         my (%customroles,%ordered,%current);          my %customroles;
         if (ref($settings) eq 'HASH') {          foreach my $key (keys(%existing)) {
             if (ref($settings->{'adhoc'}) eq 'HASH') {  
                 %current = %{$settings->{'adhoc'}};  
             }  
         }  
         my $count = 0;  
         foreach my $key (sort(keys(%existing))) {  
             if ($key=~/^rolesdef\_(\w+)$/) {              if ($key=~/^rolesdef\_(\w+)$/) {
                 my $rolename = $1;                  my $rolename = $1;
                 my (%privs,$order);                  my %privs;
                 ($privs{'system'},$privs{'domain'},$privs{'course'}) = split(/\_/,$existing{$key});                  ($privs{'system'},$privs{'domain'},$privs{'course'}) = split(/\_/,$existing{$key});
                 $customroles{$rolename} = \%privs;                  $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']);          my $count = 0;
         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 $context = 'domprefs';
         my $crstype = 'Course';          my $crstype = 'Course';
         my $prefix = 'helproles_';          foreach my $role (sort(keys(%customroles))) {
         my $add_class = 'LC_hidden';              my $prefix = 'custhelp'.$count;
         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 %full=();
             my %levels= (              my %levels= (
                          course => {},                           course => {},
Line 4480  sub print_helpsettings { Line 3088  sub print_helpsettings {
             &Apache::lonuserutils::custom_role_privs($customroles{$role},\%full,\%levels,\%levelscurrent);              &Apache::lonuserutils::custom_role_privs($customroles{$role},\%full,\%levels,\%levelscurrent);
             my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);              my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
             $css_class = $itemcount%2?' class="LC_odd_row"':'';              $css_class = $itemcount%2?' class="LC_odd_row"':'';
             my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$num."_pos'".');"';              $datatable .= '<tr '.$css_class.'><td><label>'.
             $datatable .= '<tr '.$css_class.'><td valign="top"><b>'.$role.'</b><br />'.                            '<input type="checkbox" name="modifycusthelp" value="'.$count.'" />'.
                           '<select name="helproles_'.$num.'_pos"'.$chgstr.'>';                            '<input type="hidden" name="custhelprole'.$count.'" value="'.$role.'" />'. 
             for (my $k=0; $k<=$maxnum; $k++) {                            &mt('Modify').'</label></td>'.
                 my $vpos = $k+1;                            '<td>'.&mt('Existing helpdesk role:').'&nbsp;'.
                 my $selstr;                            '<b>'.$role.'</b><br />'.
                 if ($k == $num) {                            &Apache::lonuserutils::custom_role_header($context,$crstype,
                     $selstr = ' selected="selected" ';                                                                      \@templateroles,$prefix).
                 }  
                 $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,                            &Apache::lonuserutils::custom_role_table($crstype,\%full,\%levels,
                                                                    \%levelscurrent,$identifier,                                                                     \%levelscurrent,$prefix).
                                                                    'LC_hidden',$prefix.$num.'_privs').                            '<br /></td>';
                           '</fieldset></td>';              $count ++;
             $itemcount ++;              $itemcount ++;
         }          }
         $css_class = $itemcount%2?' class="LC_odd_row"':'';          $css_class = $itemcount%2?' class="LC_odd_row"':'';
Line 4519  sub print_helpsettings { Line 3113  sub print_helpsettings {
                     );                      );
         &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);          &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
         my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);          my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
         my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$count."_pos'".');"';          $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak"><label>'.
         $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').                        '<input type="checkbox" name="newcusthelp" value="'.$count.'" />'. &mt('Add').
                       '</label></span></td>'.                        '</label></span></td>'.
                       '<td><fieldset><legend>'.&mt('Role name').'</legend>'.                        '<td><span class="LC_nobreak">'.
                       '<span class="LC_nobreak">'.                        '<b>'.&mt('Name of new helpdesk role:').'</b>&nbsp;'.
                       &mt('Internal name:').                        '<input type="text" size="20" name="newcusthelpname" value="" />'.
                       '<input type="text" size="10" name="custhelpname'.$count.'" value="" />'.                        '</span><br />'.
                       '</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,                        &Apache::lonuserutils::custom_role_header($context,$crstype,
                                                                 \@templateroles,$newcust).                                                                  \@templateroles,$newcust).
                       &Apache::lonuserutils::custom_role_table('Course',\%full,\%levels,                        &Apache::lonuserutils::custom_role_table('Course',\%full,\%levels,
                                                                \%levelscurrent,$newcust).                                                                 \%levelscurrent,$newcust).
                       '</fieldset>'.                        '<br /><br />'.
                       &helpsettings_javascript(\@roles_by_num,$maxnum,$hiddenstr,$formname).  
                       '</td></tr>';                        '</td></tr>';
         $count ++;          $count ++;
         $$rowtotal += $count;          $$rowtotal += $count;
Line 4559  sub print_helpsettings { Line 3132  sub print_helpsettings {
     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,$align,$firstval) = @_;          $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 4809  sub radiobutton_prefs { Line 3174  sub radiobutton_prefs {
         } else {          } else {
             $datatable .= '<td class="LC_right_item">';              $datatable .= '<td class="LC_right_item">';
         }          }
         $datatable .= '<span class="LC_nobreak">';          $datatable .= 
         if ($firstval eq 'no') {              '<span class="LC_nobreak">'.
             $datatable .=  
                 '<label><input type="radio" name="'.  
                 $item.'" '.$checkedoff{$item}.' value="0"'.$onclick.' />'.&mt('No').  
                 '</label>&nbsp;<label><input type="radio" name="'.$item.'" '.  
                 $checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').'</label>';  
         } else {  
             $datatable .=  
             '<label><input type="radio" name="'.              '<label><input type="radio" name="'.
             $item.'" '.$checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').              $item.'" '.$checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').
             '</label>&nbsp;<label><input type="radio" name="'.$item.'" '.              '</label>&nbsp;<label><input type="radio" name="'.$item.'" '.
             $checkedoff{$item}.' value="0"'.$onclick.' />'.&mt('No').'</label>';              $checkedoff{$item}.' value="0"'.$onclick.' />'.&mt('No').'</label>'.
         }              '</span>'.$additional.
         $datatable .= '</span>'.$additional.'</td></tr>';              '</td>'.
               '</tr>';
         $itemcount ++;          $itemcount ++;
     }      }
     return ($datatable,$itemcount);      return ($datatable,$itemcount);
Line 4847  sub print_ltitools { Line 3206  sub print_ltitools {
     my $confname = $dom.'-domainconfig';      my $confname = $dom.'-domainconfig';
     my $switchserver = &check_switchserver($dom,$confname);      my $switchserver = &check_switchserver($dom,$confname);
     my $maxnum = scalar(keys(%ordered));      my $maxnum = scalar(keys(%ordered));
     my $datatable;      my $datatable = &ltitools_javascript($settings);
     my %lt = &ltitools_names();      my %lt = &ltitools_names();
     my @courseroles = ('cc','in','ta','ep','st');      my @courseroles = ('cc','in','ta','ep','st');
     my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner);      my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner);
     my @fields = ('fullname','firstname','lastname','email','roles','user');      my @fields = ('fullname','firstname','lastname','email','user','roles');
     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++) {
             $css_class = $itemcount%2?' class="LC_odd_row"':'';              $css_class = $itemcount%2?' class="LC_odd_row"':'';
             my $item = $ordered{$items[$i]};              my $item = $ordered{$items[$i]};
             my ($title,$key,$secret,$url,$lifetime,$imgsrc,%sigsel);              my ($title,$key,$secret,$url,$imgsrc,$version);
             if (ref($settings->{$item}) eq 'HASH') {              if (ref($settings->{$item}) eq 'HASH') {
                 $title = $settings->{$item}->{'title'};                  $title = $settings->{$item}->{'title'};
                 $url = $settings->{$item}->{'url'};                  $url = $settings->{$item}->{'url'};
                 $key = $settings->{$item}->{'key'};                  $key = $settings->{$item}->{'key'};
                 $secret = $settings->{$item}->{'secret'};                  $secret = $settings->{$item}->{'secret'};
                 $lifetime = $settings->{$item}->{'lifetime'};  
                 my $image = $settings->{$item}->{'image'};                  my $image = $settings->{$item}->{'image'};
                 if ($image ne '') {                  if ($image ne '') {
                     $imgsrc = '<img src="'.$image.'" alt="'.&mt('Tool Provider icon').'" />';                      $imgsrc = '<img src="'.$image.'" alt="'.&mt('Tool Provider icon').'" />';
                 }                  }
                 if ($settings->{$item}->{'sigmethod'} eq 'HMAC-256') {  
                     $sigsel{'HMAC-256'} = ' selected="selected"';  
                 } else {  
                     $sigsel{'HMAC-SHA1'} = ' selected="selected"';  
                 }  
             }              }
             my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_".$item."'".');"';              my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_".$item."'".');"';
             $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'              $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
                          .'<select name="ltitools_'.$item.'"'.$chgstr.'>';                           .'<select name="ltitools_'.$item.'"'.$chgstr.'>';
             for (my $k=0; $k<=$maxnum; $k++) {              for (my $k=0; $k<=$maxnum; $k++) {
Line 4890  sub print_ltitools { Line 3243  sub print_ltitools {
                 &mt('Delete?').'</label></span></td>'.                  &mt('Delete?').'</label></span></td>'.
                 '<td colspan="2">'.                  '<td colspan="2">'.
                 '<fieldset><legend>'.&mt('Required settings').'</legend>'.                  '<fieldset><legend>'.&mt('Required settings').'</legend>'.
                 '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="20" name="ltitools_title_'.$i.'" value="'.$title.'" /></span> '.                  '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="30" name="ltitools_title_'.$i.'" value="'.$title.'" /></span> '.
                 ('&nbsp;'x2).                  ('&nbsp;'x2).
                 '<span class="LC_nobreak">'.$lt{'version'}.':<select name="ltitools_version_'.$i.'">'.                  '<span class="LC_nobreak">'.$lt{'version'}.':<select name="ltitools_version_'.$i.'">'.
                 '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '.                  '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '.
                 ('&nbsp;'x2).                  ('&nbsp;'x2).
                 '<span class="LC_nobreak">'.$lt{'msgtype'}.':<select name="ltitools_msgtype_'.$i.'">'.                  '<span class="LC_nobreak">'.$lt{'msgtype'}.':<select name="ltitools_msgtype_'.$i.'">'.
                 '<option value="basic-lti-launch-request" selected="selected">Launch</option></select></span> '.                  '<option value="basic-lti-launch-request" selected="selected">Launch</option></select></span> '.
                 ('&nbsp;'x2).  
                 '<span class="LC_nobreak">'.$lt{'sigmethod'}.':<select name="ltitools_sigmethod_'.$i.'">'.  
                 '<option value="HMAC-SHA1"'.$sigsel{'HMAC-SHA1'}.'>HMAC-SHA1</option>'.  
                 '<option value="HMAC-SHA256"'.$sigsel{'HMAC-SHA256'}.'>HMAC-SHA256</option></select></span>'.  
                 '<br /><br />'.                  '<br /><br />'.
                 '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="40" name="ltitools_url_'.$i.'"'.                  '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="30" name="ltitools_url_'.$i.'"'.
                 ' value="'.$url.'" /></span>'.                  ' value="'.$url.'" /></span>'.
                 ('&nbsp;'x2).                  ('&nbsp;'x2).
                 '<span class="LC_nobreak">'.$lt{'key'}.':'.                  '<span class="LC_nobreak">'.$lt{'key'}.
                 '<input type="text" size="25" name="ltitools_key_'.$i.'" value="'.$key.'" /></span> '.                  '<input type="text" size="25" name="ltitools_key_'.$i.'" value="'.$key.'" /></span> '.
                 ('&nbsp;'x2).                  ('&nbsp;'x2).
                 '<span class="LC_nobreak">'.$lt{'lifetime'}.':'.  
                 '<input type="text" size="5" name="ltitools_lifetime_'.$i.'" value="'.$lifetime.'" /></span> '.  
                 ('&nbsp;'x2).  
                 '<span class="LC_nobreak">'.$lt{'secret'}.':'.                  '<span class="LC_nobreak">'.$lt{'secret'}.':'.
                 '<input type="password" size="20" name="ltitools_secret_'.$i.'" value="'.$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>'.                  '<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>'.
Line 4922  sub print_ltitools { Line 3268  sub print_ltitools {
             if (ref($settings->{$item}->{'display'}) eq 'HASH') {              if (ref($settings->{$item}->{'display'}) eq 'HASH') {
                 if ($settings->{$item}->{'display'}->{'target'} eq 'window') {                  if ($settings->{$item}->{'display'}->{'target'} eq 'window') {
                     $currdisp{'window'} = ' checked="checked"';                      $currdisp{'window'} = ' checked="checked"';
                 } elsif ($settings->{$item}->{'display'}->{'target'} eq 'tab') {  
                     $currdisp{'tab'} = ' checked="checked"';  
                 } else {                  } else {
                     $currdisp{'iframe'} = ' checked="checked"';                      $currdisp{'iframe'} = ' checked="checked"';
                 }                  }
Line 4933  sub print_ltitools { Line 3277  sub print_ltitools {
                 if ($settings->{$item}->{'display'}->{'height'} =~ /^(\d+)$/) {                  if ($settings->{$item}->{'display'}->{'height'} =~ /^(\d+)$/) {
                      $currdisp{'height'} = $1;                       $currdisp{'height'} = $1;
                 }                  }
                 $currdisp{'linktext'} = $settings->{$item}->{'display'}->{'linktext'};  
                 $currdisp{'explanation'} = $settings->{$item}->{'display'}->{'explanation'};  
             } else {              } else {
                 $currdisp{'iframe'} = ' checked="checked"';                  $currdisp{'iframe'} = ' checked="checked"';
             }              }
             foreach my $disp ('iframe','tab','window') {              foreach my $disp ('iframe','window') {
                 $datatable .= '<label><input type="radio" name="ltitools_target_'.$i.'" value="'.$disp.'"'.$currdisp{$disp}.' />'.                  $datatable .= '<label><input type="radio" name="ltitools_target_'.$i.'" value="'.$disp.'"'.$currdisp{$disp}.' />'.
                               $lt{$disp}.'</label>'.('&nbsp;'x2);                                $lt{$disp}.'</label>'.('&nbsp;'x2);
             }              }
Line 4948  sub print_ltitools { Line 3290  sub print_ltitools {
                               '<input type="text" name="ltitools_'.$dimen.'_'.$i.'" size="5" value="'.$currdisp{$dimen}.'" /></label>'.                                '<input type="text" name="ltitools_'.$dimen.'_'.$i.'" size="5" value="'.$currdisp{$dimen}.'" /></label>'.
                               ('&nbsp;'x2);                                ('&nbsp;'x2);
             }              }
             $datatable .= '</span><br />'.              $datatable .= '<br />';
                           '<div class="LC_left_float">'.$lt{'linktext'}.'<br />'.              foreach my $extra ('passback','roster') {
                           '<input type="text" name="ltitools_linktext_'.$i.'" size="25" value="'.$currdisp{'linktext'}.'" /></div>'.                  my $checkedon = '';
                           '<div class="LC_left_float">'.$lt{'explanation'}.'<br />'.                  my $checkedoff = ' checked="checked"';
                           '<textarea name="ltitools_explanation_'.$i.'" rows="5" cols="40">'.$currdisp{'explanation'}.                  if ($settings->{$item}->{$extra}) {
                           '</textarea></div><div style=""></div>'.                      $checkedon = $checkedoff;
                           '<div style="padding:0;clear:both;margin:0;border:0"></div>';                      $checkedoff = '';
             $datatable .= '<span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;';                  }
                   $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) {              if ($imgsrc) {
                 $datatable .= $imgsrc.                  $datatable .= $imgsrc.
                               '<label><input type="checkbox" name="ltitools_image_del"'.                                '<label><input type="checkbox" name="ltitools_image_del"'.
Line 4970  sub print_ltitools { Line 3319  sub print_ltitools {
                 $datatable .= '<input type="file" name="ltitools_image_'.$i.'" value="" />';                  $datatable .= '<input type="file" name="ltitools_image_'.$i.'" value="" />';
             }              }
             $datatable .= '</span></fieldset>';              $datatable .= '</span></fieldset>';
             my (%checkedfields,%rolemaps,$userincdom);              my (%checkedfields,%rolemaps);
             if (ref($settings->{$item}) eq 'HASH') {              if (ref($settings->{$item}) eq 'HASH') {
                 if (ref($settings->{$item}->{'fields'}) eq 'HASH') {                  if (ref($settings->{$item}->{'fields'}) eq 'HASH') {
                     %checkedfields = %{$settings->{$item}->{'fields'}};                      %checkedfields = %{$settings->{$item}->{'fields'}};
                 }                  }
                 $userincdom = $settings->{$item}->{'incdom'};  
                 if (ref($settings->{$item}->{'roles'}) eq 'HASH') {                  if (ref($settings->{$item}->{'roles'}) eq 'HASH') {
                     %rolemaps = %{$settings->{$item}->{'roles'}};                      %rolemaps = %{$settings->{$item}->{'roles'}};
                     $checkedfields{'roles'} = 1;                      $checkedfields{'roles'} = 1;
Line 4983  sub print_ltitools { Line 3331  sub print_ltitools {
             }              }
             $datatable .= '<fieldset><legend>'.&mt('User data sent on launch').'</legend>'.              $datatable .= '<fieldset><legend>'.&mt('User data sent on launch').'</legend>'.
                           '<span class="LC_nobreak">';                            '<span class="LC_nobreak">';
             my $userfieldstyle = 'display:none;';  
             my $seluserdom = '';  
             my $unseluserdom = ' selected="selected"';  
             foreach my $field (@fields) {              foreach my $field (@fields) {
                 my ($checked,$onclick,$id,$spacer);                  my $checked;
                 if ($checkedfields{$field}) {                  if ($checkedfields{$field}) {
                     $checked = ' checked="checked"';                      $checked = ' checked="checked"';
                 }                  }
                 if ($field eq 'user') {  
                     $id = ' id="ltitools_user_field_'.$i.'"';  
                     $onclick = ' onclick="toggleLTITools(this.form,'."'$field','$i'".')"';  
                     if ($checked) {  
                         $userfieldstyle = 'display:inline-block';  
                         if ($userincdom) {  
                             $seluserdom = $unseluserdom;  
                             $unseluserdom = '';  
                         }  
                     }  
                 } else {  
                     $spacer = ('&nbsp;' x2);  
                 }  
                 $datatable .= '<label>'.                  $datatable .= '<label>'.
                               '<input type="checkbox" name="ltitools_fields_'.$i.'" value="'.$field.'"'.$id.$checked.$onclick.' />'.                                '<input type="checkbox" name="ltitools_fields_'.$i.'" value="'.$field.'"'.$checked.' />'.
                               $lt{$field}.'</label>'.$spacer;                                $lt{$field}.'</label>'.('&nbsp;' x2);
             }              }
             $datatable .= '</span>';              $datatable .= '</span></fieldset>'.
             $datatable .= '<div style="'.$userfieldstyle.'" id="ltitools_user_div_'.$i.'">'.  
                           '<span class="LC_nobreak"> : '.  
                           '<select name="ltitools_userincdom_'.$i.'">'.  
                           '<option value="">'.&mt('Select').'</option>'.  
                           '<option value="0"'.$unseluserdom.'>'.&mt('username').'</option>'.  
                           '<option value="1"'.$seluserdom.'>'.&mt('username:domain').'</option>'.  
                           '</select></span></div>';  
             $datatable .= '</fieldset>'.  
                           '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';                            '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';
             foreach my $role (@courseroles) {              foreach my $role (@courseroles) {
                 my ($selected,$selectnone);                  my ($selected,$selectnone);
                 if (!$rolemaps{$role}) {                  if (!$rolemaps{$role}) {
                     $selectnone = ' selected="selected"';                      $selectnone = ' selected="selected"';
                 }                  }
                 $datatable .= '<td align="center">'.                  $datatable .= '<td align="center">'. 
                               &Apache::lonnet::plaintext($role,'Course').'<br />'.                                &Apache::lonnet::plaintext($role,'Course').'<br />'.
                               '<select name="ltitools_roles_'.$role.'_'.$i.'">'.                                '<select name="ltitools_roles_'.$role.'_'.$i.'">'.
                               '<option value=""'.$selectnone.'>'.&mt('Select').'</option>';                                '<option value=""'.$selectnone.'>'.&mt('Select').'</option>';
Line 5047  sub print_ltitools { Line 3371  sub print_ltitools {
                 }                  }
             }              }
             $datatable .= '<fieldset><legend>'.&mt('Configurable in course').'</legend><span class="LC_nobreak">';              $datatable .= '<fieldset><legend>'.&mt('Configurable in course').'</legend><span class="LC_nobreak">';
             foreach my $item ('label','title','target','linktext','explanation','append') {              foreach my $item ('label','title','target') {
                 my $checked;                  my $checked;
                 if ($courseconfig{$item}) {                  if ($courseconfig{$item}) {
                     $checked = ' checked="checked"';                      $checked = ' checked="checked"';
Line 5080  sub print_ltitools { Line 3404  sub print_ltitools {
         }          }
     }      }
     $css_class = $itemcount%2?' class="LC_odd_row"':'';      $css_class = $itemcount%2?' class="LC_odd_row"':'';
     my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_add_pos'".');"';      my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_add_pos'".');"';
     $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".      $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
                   '<input type="hidden" name="ltitools_maxnum" value="'.$maxnum.'" />'."\n".                    '<input type="hidden" name="ltitools_maxnum" value="'.$maxnum.'" />'."\n".
                   '<select name="ltitools_add_pos"'.$chgstr.'>';                    '<select name="ltitools_add_pos"'.$chgstr.'>';
Line 5093  sub print_ltitools { Line 3417  sub print_ltitools {
         $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="ltitools_add" value="1" />'.&mt('Add').'</span></td>'."\n".                    '<input type="checkbox" name="ltitools_add" value="1" />'.&mt('Add').'</td>'."\n".
                   '<td colspan="2">'.                    '<td colspan="2">'.
                   '<fieldset><legend>'.&mt('Required settings').'</legend>'.                    '<fieldset><legend>'.&mt('Required settings').'</legend>'.
                   '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="20" name="ltitools_add_title" value="" /></span> '."\n".                    '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="30" name="ltitools_add_title" value="" /></span> '."\n".
                   ('&nbsp;'x2).                    ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'version'}.':<select name="ltitools_add_version">'.                    '<span class="LC_nobreak">'.$lt{'version'}.':<select name="ltitools_add_version">'.
                   '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '."\n".                    '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '."\n".
                   ('&nbsp;'x2).                    ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'msgtype'}.':<select name="ltitools_add_msgtype">'.                    '<span class="LC_nobreak">'.$lt{'msgtype'}.':<select name="ltitools_add_msgtype">'.
                   '<option value="basic-lti-launch-request" selected="selected">Launch</option></select></span> '.                    '<option value="basic-lti-launch-request" selected="selected">Launch</option></select></span> '.
                   '<span class="LC_nobreak">'.$lt{'sigmethod'}.':<select name="ltitools_add_sigmethod">'.  
                   '<option value="HMAC-SHA1" selected="selected">HMAC-SHA1</option>'.  
                   '<option value="HMAC-SHA256">HMAC-SHA256</option></select></span>'.  
                   '<br />'.                    '<br />'.
                   '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="40" name="ltitools_add_url" value="" /></span> '."\n".                    '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="30" name="ltitools_add_url" value="" /></span> '."\n".
                   ('&nbsp;'x2).                    ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'key'}.':<input type="text" size="25" name="ltitools_add_key" value="" /></span> '."\n".                    '<span class="LC_nobreak">'.$lt{'key'}.':<input type="text" size="25" name="ltitools_add_key" value="" /></span> '."\n".
                   ('&nbsp;'x2).                    ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'lifetime'}.':<input type="text" size="5" name="ltitools_add_lifetime" value="300" /></span> '."\n".  
                   ('&nbsp;'x2).  
                   '<span class="LC_nobreak">'.$lt{'secret'}.':<input type="password" size="20" name="ltitools_add_secret" value="" />'.                    '<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".                    '<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>'.
Line 5120  sub print_ltitools { Line 3439  sub print_ltitools {
                   '<span class="LC_nobreak">'.&mt('Display target:');                    '<span class="LC_nobreak">'.&mt('Display target:');
     my %defaultdisp;      my %defaultdisp;
     $defaultdisp{'iframe'} = ' checked="checked"';      $defaultdisp{'iframe'} = ' checked="checked"';
     foreach my $disp ('iframe','tab','window') {      foreach my $disp ('iframe','window') {
         $datatable .= '<label><input type="radio" name="ltitools_add_target" value="'.$disp.'"'.$defaultdisp{$disp}.' />'.          $datatable .= '<label><input type="radio" name="ltitools_add_target" value="'.$disp.'"'.$defaultdisp{$disp}.' />'.
                       $lt{$disp}.'</label>'.('&nbsp;'x2);                        $lt{$disp}.'</label>'.('&nbsp;'x2);
     }      }
Line 5130  sub print_ltitools { Line 3449  sub print_ltitools {
                       '<input type="text" name="ltitools_add_'.$dimen.'" size="5" /></label>'.                        '<input type="text" name="ltitools_add_'.$dimen.'" size="5" /></label>'.
                       ('&nbsp;'x2);                        ('&nbsp;'x2);
     }      }
     $datatable .= '</span><br />'.      $datatable .= '<br />';
                   '<div class="LC_left_float">'.$lt{'linktext'}.'<br />'.      foreach my $extra ('passback','roster') {
                   '<input type="text" name="ltitools_add_linktext" size="5" /></div>'.          $datatable .= $lt{$extra}.'&nbsp;'.
                   '<div class="LC_left_float">'.$lt{'explanation'}.'<br />'.                        '<label><input type="radio" name="ltitools_add_'.$extra.'" value="1" />'.
                   '<textarea name="ltitools_add_explanation" rows="5" cols="40"></textarea>'.                        &mt('Yes').'</label>'.('&nbsp;'x2).
                   '</div><div style=""></div>'.                        '<label><input type="radio" name="ltitools_add_'.$extra.'" value="0" checked="checked" />'.
                   '<div style="padding:0;clear:both;margin:0;border:0"></div>';                        &mt('No').'</label>'.('&nbsp;'x4);
     $datatable .= '<span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;'.      }
       $datatable .= '<br /><br /><span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;'.
                   '('.&mt('if larger than 21x21 pixels, image will be scaled').')&nbsp;';                    '('.&mt('if larger than 21x21 pixels, image will be scaled').')&nbsp;';
     if ($switchserver) {      if ($switchserver) {
         $datatable .= &mt('Upload to library server: [_1]',$switchserver);          $datatable .= &mt('Upload to library server: [_1]',$switchserver);
Line 5148  sub print_ltitools { Line 3468  sub print_ltitools {
                   '<fieldset><legend>'.&mt('User data sent on launch').'</legend>'.                    '<fieldset><legend>'.&mt('User data sent on launch').'</legend>'.
                   '<span class="LC_nobreak">';                    '<span class="LC_nobreak">';
     foreach my $field (@fields) {      foreach my $field (@fields) {
         my ($id,$onclick,$spacer);  
         if ($field eq 'user') {  
             $id = ' id="ltitools_user_field_add"';  
             $onclick = ' onclick="toggleLTITools(this.form,'."'$field','add'".')"';  
         } else {  
             $spacer = ('&nbsp;' x2);  
         }  
         $datatable .= '<label>'.          $datatable .= '<label>'.
                       '<input type="checkbox" name="ltitools_add_fields" value="'.$field.'"'.$id.$onclick.' />'.                        '<input type="checkbox" name="ltitools_add_fields" value="'.$field.'" />'.
                       $lt{$field}.'</label>'.$spacer;                        $lt{$field}.'</label>'.('&nbsp;' x2);
     }      }
     $datatable .= '</span>'.      $datatable .= '</span></fieldset>'.
                   '<div style="display:none;" id="ltitools_user_div_add">'.                    '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';
                   '<span class="LC_nobreak"> : '.  
                   '<select name="ltitools_userincdom_add">'.  
                   '<option value="" selected="selected">'.&mt('Select').'</option>'.  
                   '<option value="0">'.&mt('username').'</option>'.  
                   '<option value="1">'.&mt('username:domain').'</option>'.  
                   '</select></span></div></fieldset>';  
     $datatable .= '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';  
     foreach my $role (@courseroles) {      foreach my $role (@courseroles) {
         my ($checked,$checkednone);          my ($checked,$checkednone);
         $datatable .= '<td align="center">'.          $datatable .= '<td align="center">'.
Line 5181  sub print_ltitools { Line 3487  sub print_ltitools {
     }      }
     $datatable .= '</tr></table></fieldset>'.      $datatable .= '</tr></table></fieldset>'.
                   '<fieldset><legend>'.&mt('Configurable in course').'</legend><span class="LC_nobreak">';                    '<fieldset><legend>'.&mt('Configurable in course').'</legend><span class="LC_nobreak">';
     foreach my $item ('label','title','target','linktext','explanation','append') {      foreach my $item ('label','title','target') {
         $datatable .= '<label>'.           $datatable .= '<label>'.
                       '<input type="checkbox" name="ltitools_courseconfig" value="'.$item.'" checked="checked" />'.                         '<input type="checkbox" name="ltitools_courseconfig" value="'.$item.'" checked="checked" />'.
                       $lt{'crs'.$item}.'</label>'.('&nbsp;' x2)."\n";                         $lt{'crs'.$item}.'</label>'.('&nbsp;' x2)."\n";
     }      }
     $datatable .= '</span></fieldset>'.      $datatable .= '</span></fieldset>'.
                   '<fieldset><legend>'.&mt('Custom items sent on launch').'</legend>'.                    '<fieldset><legend>'.&mt('Custom items sent on launch').'</legend>'.
Line 5193  sub print_ltitools { Line 3499  sub print_ltitools {
                   '<label><input type="checkbox" name="ltitools_add_custom" value="1" />'.                    '<label><input type="checkbox" name="ltitools_add_custom" value="1" />'.
                   &mt('Add').'</label></span></td><td><input type="text" name="ltitools_add_custom_name" />'.                    &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>'.                    '</td><td><input type="text" name="ltitools_add_custom_value" /></td></tr>'.
                   '</table></fieldset>'."\n".                    '</table></fieldset></td></tr>'."\n".
                   '</td>'."\n".                    '</td>'."\n".
                   '</tr>'."\n";                    '</tr>'."\n";
     $itemcount ++;      $itemcount ++;
Line 5202  sub print_ltitools { Line 3508  sub print_ltitools {
   
 sub ltitools_names {  sub ltitools_names {
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
                                           'title'          => 'Title',                                            'title'     => 'Title',
                                           'version'        => 'Version',                                            'version'   => 'Version',
                                           'msgtype'        => 'Message Type',                                            'msgtype'   => 'Message Type',
                                           'sigmethod'      => 'Signature Method',                                            'url'       => 'URL',
                                           'url'            => 'URL',                                            'key'       => 'Key',
                                           'key'            => 'Key',                                            'secret'    => 'Secret',
                                           'lifetime'       => 'Nonce lifetime (s)',                                            'icon'      => 'Icon',   
                                           'secret'         => 'Secret',                                            'user'      => 'Username:domain',
                                           'icon'           => 'Icon',                                            'fullname'  => 'Full Name',
                                           'user'           => 'User',                                            'firstname' => 'First Name',
                                           'fullname'       => 'Full Name',                                            'lastname'  => 'Last Name',
                                           'firstname'      => 'First Name',                                            'email'     => 'E-mail',
                                           'lastname'       => 'Last Name',                                            'roles'     => 'Role',
                                           'email'          => 'E-mail',                                            'window'    => 'Window/Tab',
                                           'roles'          => 'Role',                                            'iframe'    => 'iFrame',
                                           'window'         => 'Window',                                            'height'    => 'Height',
                                           'tab'            => 'Tab',                                            'width'     => 'Width',
                                           'iframe'         => 'iFrame',                                            'passback'  => 'Tool can return grades:',
                                           'height'         => 'Height',                                            'roster'    => 'Tool can retrieve roster:',
                                           'width'          => 'Width',                                            'crstarget' => 'Display target',
                                           'linktext'       => 'Default Link Text',                                            'crslabel'  => 'Course label',
                                           'explanation'    => 'Default Explanation',                                            'crstitle'  => 'Course title', 
                                           'crstarget'      => 'Display target',  
                                           'crslabel'       => 'Course label',  
                                           'crstitle'       => 'Course title',  
                                           'crslinktext'    => 'Link Text',  
                                           'crsexplanation' => 'Explanation',  
                                           'crsappend'      => 'Provider URL',  
                                         );                                          );
   
     return %lt;      return %lt;
 }  }
   
 sub print_lti {  
     my ($position,$dom,$settings,$rowtotal) = @_;  
     my $itemcount = 1;  
     my ($datatable,$css_class);  
     my (%rules,%encrypt,%privkeys,%linkprot);  
     if (ref($settings) eq 'HASH') {  
         if ($position eq 'top') {  
             if (exists($settings->{'encrypt'})) {  
                 if (ref($settings->{'encrypt'}) eq 'HASH') {  
                     foreach my $key (keys(%{$settings->{'encrypt'}})) {  
                         $encrypt{'ltisec_'.$key.'linkprot'} = $settings->{'encrypt'}{$key};  
                     }  
                 }  
             }  
             if (exists($settings->{'private'})) {  
                 if (ref($settings->{'private'}) eq 'HASH') {  
                     if (ref($settings->{'private'}) eq 'HASH') {  
                         if (ref($settings->{'private'}{'keys'}) eq 'ARRAY') {  
                             map { $privkeys{$_} = 1; } (@{$settings->{'private'}{'keys'}});  
                         }  
                     }  
                 }  
             }  
         } elsif ($position eq 'middle') {  
             if (exists($settings->{'rules'})) {  
                 if (ref($settings->{'rules'}) eq 'HASH') {  
                     %rules = %{$settings->{'rules'}};  
                 }  
             }  
         } elsif ($position eq 'bottom') {  
             if (exists($settings->{'linkprot'})) {  
                 if (ref($settings->{'linkprot'}) eq 'HASH') {  
                     %linkprot = %{$settings->{'linkprot'}};  
                     if ($linkprot{'lock'}) {  
                         delete($linkprot{'lock'});  
                     }  
                 }  
             }  
         }  
     }  
     if ($position eq 'top') {  
         my @ids=&Apache::lonnet::current_machine_ids();  
         my %servers = &Apache::lonnet::get_servers($dom,'library');  
         my $primary = &Apache::lonnet::domain($dom,'primary');  
         my ($extra,$numshown);  
         foreach my $hostid (sort(keys(%servers))) {  
             my ($showextra,$divsty,$switch);  
             if ($hostid eq $primary) {  
                 if ($encrypt{'ltisec_domlinkprot'}) {  
                     $showextra = 1;  
                 }  
             }  
             if ($encrypt{'ltisec_crslinkprot'}) {  
                 $showextra = 1;  
             }  
             unless (grep(/^\Q$hostid\E$/,@ids)) {  
                 $switch = 1;  
             }  
             if ($showextra) {  
                 $numshown ++;  
                 $divsty = 'display:inline-block';  
             } else {  
                 $divsty = 'display:none';  
             }  
             $extra .= '<fieldset id="ltisec_info_'.$hostid.'" style="'.$divsty.'">'.  
                       '<legend>'.$hostid.'</legend>';  
             if ($switch) {  
                 my $switchserver = '<a href="/adm/switchserver?otherserver='.$hostid.'&amp;role='.  
                                    &HTML::Entities::encode($env{'request.role'},'\'<>"&').  
                                    '&amp;destinationurl=/adm/domainprefs">'.&mt('Switch Server').'</a>';  
                 if (exists($privkeys{$hostid})) {  
                     $extra .= '<div id="ltisec_divcurrprivkey_'.$hostid.'" style="display:inline-block" />'.  
                               '<span class="LC_nobreak">'.  
                               &mt('Encryption Key').': ['.&mt('not shown').'] '.('&nbsp;'x2).'</span></div>'.  
                               '<span class="LC_nobreak">'.&mt('Change?').  
                               '<label><input type="radio" value="0" name="ltisec_changeprivkey_'.$hostid.'" onclick="javascript:togglePrivKey(this.form,'."'$hostid'".');" checked="checked" />'.&mt('No').'</label>'.  
                               ('&nbsp;'x2).  
                               '<label><input type="radio" value="1" name="ltisec_changeprivkey_'.$hostid.'" onclick="javascript:togglePrivKey(this.form,'."'$hostid'".');" />'.&mt('Yes').  
                               '</label>&nbsp;&nbsp;</span><div id="ltisec_divchgprivkey_'.$hostid.'" style="display:none" />'.  
                               '<span class="LC_nobreak"> - '.&mt('submit from server ([_1]): [_2].',$hostid,$switchserver).  
                               '</span></div>';  
                 } else {  
                     $extra .= '<span class="LC_nobreak">'.  
                               &mt('Key required').' - '.&mt('submit from server ([_1]): [_2].',$hostid,$switchserver).  
                               '</span>'."\n";  
                 }  
             } elsif (exists($privkeys{$hostid})) {  
                 $extra .= '<div id="ltisec_divcurrprivkey_'.$hostid.'" style="display:inline-block" /><span class="LC_nobreak">'.  
                           &mt('Encryption Key').': ['.&mt('not shown').'] '.('&nbsp;'x2).'</span></div>'.  
                           '<span class="LC_nobreak">'.&mt('Change?').  
                           '<label><input type="radio" value="0" name="ltisec_changeprivkey_'.$hostid.'" onclick="javascript:togglePrivKey(this.form,'."'$hostid'".');" checked="checked" />'.&mt('No').'</label>'.  
                           ('&nbsp;'x2).  
                           '<label><input type="radio" value="1" name="ltisec_changeprivkey_'.$hostid.'" onclick="javascript:togglePrivKey(this.form,'."'$hostid'".');" />'.&mt('Yes').  
                           '</label>&nbsp;&nbsp;</span><div id="ltisec_divchgprivkey_'.$hostid.'" style="display:none" />'.  
                           '<span class="LC_nobreak">'.&mt('New Key').':'.  
                           '<input type="password" size="20" name="ltisec_privkey_'.$hostid.'" value="" autocomplete="off" />'.  
                           '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.ltisec_privkey_'.$hostid.'.type='."'text'".' } else { this.form.ltisec_privkey_'.$hostid.'.type='."'password'".' }" />'.&mt('Visible input').'</label>'.  
                           '</span></div>';  
             } else {  
                 $extra .= '<span class="LC_nobreak">'.&mt('Encryption Key').':'.  
                           '<input type="password" size="20" name="ltisec_privkey_'.$hostid.'" value="" autocomplete="off" />'.  
                           '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.ltisec_privkey_'.$hostid.'.type='."'text'".' } else { this.form.ltisec_privkey_'.$hostid.'.type='."'password'".' }" />'.&mt('Visible input').'</label>';  
             }  
             $extra .= '</fieldset>';  
         }  
         my %choices = &Apache::lonlocal::texthash (  
                                                       ltisec_crslinkprot => 'Encrypt stored link protection secrets defined in courses',  
                                                       ltisec_domlinkprot => 'Encrypt stored link protection secrets defined in domain',  
                                                   );  
         my @toggles = qw(ltisec_crslinkprot ltisec_domlinkprot);  
         my %defaultchecked = (  
                                'ltisec_crslinkprot' => 'off',  
                                'ltisec_domlinkprot' => 'off',  
                              );  
         my ($onclick,$itemcount);  
         $onclick = 'javascript:toggleLTIEncKey(this.form);';  
         ($datatable,$itemcount) = &radiobutton_prefs(\%encrypt,\@toggles,\%defaultchecked,  
                                                      \%choices,$itemcount,$onclick,'','left','no');  
   
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         my $noprivkeysty = 'display:inline-block';  
         if ($numshown) {  
             $noprivkeysty = 'display:none';  
         }  
         $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'.&mt('Encryption Key(s)').'</td>'.  
                       '<td><div id="ltisec_noprivkey" style="'.$noprivkeysty.'" >'.  
                       '<span class="LC_nobreak">'.&mt('Not in use').'</span></div>'.  
                       $extra.  
                       '</td></tr>';  
         $itemcount ++;  
         $$rowtotal += $itemcount;  
     } elsif ($position eq 'middle') {  
         $datatable = &password_rules('secrets',\$itemcount,\%rules);  
         $$rowtotal += $itemcount;  
     } elsif ($position eq 'bottom') {  
          $datatable .= &Apache::courseprefs::print_linkprotection($dom,'',$settings,$rowtotal,'','','domain');  
     }  
     return $datatable;  
 }  
   
 sub print_coursedefaults {  sub print_coursedefaults {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles);      my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles);
     my $itemcount = 1;      my $itemcount = 1;
     my %choices =  &Apache::lonlocal::texthash (      my %choices =  &Apache::lonlocal::texthash (
           canuse_pdfforms      => 'Course/Community users can create/upload PDF forms',
         uploadquota          => 'Default quota for files uploaded directly to course/community using Course Editor (MB)',          uploadquota          => 'Default quota for files uploaded directly to course/community using Course Editor (MB)',
         anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',          anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',
         coursecredits        => 'Credits can be specified for courses',          coursecredits        => 'Credits can be specified for courses',
         uselcmath            => 'Math preview uses LON-CAPA previewer (javascript) in place of DragMath (Java)',          uselcmath            => 'Math preview uses LON-CAPA previewer (javascript) in place of DragMath (Java)',
         usejsme              => 'Molecule editor uses JSME (HTML5) in place of JME (Java)',          usejsme              => 'Molecule editor uses JSME (HTML5) in place of JME (Java)',
         inline_chem          => 'Use inline previewer for chemical reaction response in place of pop-up',  
         texengine            => 'Default method to display mathematics',  
         postsubmit           => 'Disable submit button/keypress following student submission',          postsubmit           => 'Disable submit button/keypress following student submission',
         canclone             => "People who may clone a course (besides course's owner and coordinators)",          canclone             => "People who may clone a course (besides course's owner and coordinators)",
         mysqltables          => 'Lifetime (s) of "Temporary" MySQL tables (student performance data) on homeserver',          mysqltables          => 'Lifetime (s) of "Temporary" MySQL tables (student performance data) on homeserver',
         ltiauth              => 'Student username in LTI launch of deep-linked URL can be accepted without re-authentication',  
     );      );
     my %staticdefaults = (      my %staticdefaults = (
                            anonsurvey_threshold => 10,                             anonsurvey_threshold => 10,
Line 5400  sub print_coursedefaults { Line 3557  sub print_coursedefaults {
                          );                           );
     if ($position eq 'top') {      if ($position eq 'top') {
         %defaultchecked = (          %defaultchecked = (
                               'canuse_pdfforms' => 'off',
                             'uselcmath'       => 'on',                              'uselcmath'       => 'on',
                             'usejsme'         => 'on',                              'usejsme'         => 'on',
                             'inline_chem'     => 'on',                              'canclone'        => 'none', 
                             'canclone'        => 'none',  
                           );                            );
         @toggles = ('uselcmath','usejsme','inline_chem');          @toggles = ('canuse_pdfforms','uselcmath','usejsme');
         my $deftex = $Apache::lonnet::deftex;  
         if (ref($settings) eq 'HASH') {  
             if ($settings->{'texengine'}) {  
                 if ($settings->{'texengine'} =~ /^(MathJax|mimetex|tth)$/) {  
                     $deftex = $settings->{'texengine'};  
                 }  
             }  
         }  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         my $mathdisp = '<tr'.$css_class.'><td style="vertical-align: top">'.  
                        '<span class="LC_nobreak">'.$choices{'texengine'}.  
                        '</span></td><td class="LC_right_item">'.  
                        '<select name="texengine">'."\n";  
         my %texoptions = (  
                             MathJax  => 'MathJax',  
                             mimetex  => &mt('Convert to Images'),  
                             tth      => &mt('TeX to HTML'),  
                          );  
         foreach my $renderer ('MathJax','mimetex','tth') {  
             my $selected = '';  
             if ($renderer eq $deftex) {  
                 $selected = ' selected="selected"';  
             }  
             $mathdisp .= '<option value="'.$renderer.'"'.$selected.'>'.$texoptions{$renderer}.'</option>'."\n";  
         }  
         $mathdisp .= '</select></td></tr>'."\n";  
         $itemcount ++;  
         ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,          ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
                                                      \%choices,$itemcount);                                                       \%choices,$itemcount);
         $datatable = $mathdisp.$datatable;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';          $css_class = $itemcount%2?' class="LC_odd_row"':'';
         $datatable .=          $datatable .=
             '<tr'.$css_class.'><td valign="top">'.              '<tr'.$css_class.'><td valign="top">'.
Line 5444  sub print_coursedefaults { Line 3573  sub print_coursedefaults {
         my $currcanclone = 'none';          my $currcanclone = 'none';
         my $onclick;          my $onclick;
         my @cloneoptions = ('none','domain');          my @cloneoptions = ('none','domain');
         my %clonetitles = &Apache::lonlocal::texthash (          my %clonetitles = (
                              none     => 'No additional course requesters',                               none     => 'No additional course requesters',
                              domain   => "Any course requester in course's domain",                               domain   => "Any course requester in course's domain",
                              instcode => 'Course requests for official courses ...',                               instcode => 'Course requests for official courses ...',
Line 5470  sub print_coursedefaults { Line 3599  sub print_coursedefaults {
                     $currcanclone = $settings->{'canclone'};                      $currcanclone = $settings->{'canclone'};
                 }                  }
             }              }
         }          } 
         foreach my $option (@cloneoptions) {          foreach my $option (@cloneoptions) {
             my ($checked,$additional);              my ($checked,$additional);
             if ($currcanclone eq $option) {              if ($currcanclone eq $option) {
Line 5512  sub print_coursedefaults { Line 3641  sub print_coursedefaults {
         my ($currdefresponder,%defcredits,%curruploadquota,%deftimeout,%currmysql);          my ($currdefresponder,%defcredits,%curruploadquota,%deftimeout,%currmysql);
         my $currusecredits = 0;          my $currusecredits = 0;
         my $postsubmitclient = 1;          my $postsubmitclient = 1;
         my $ltiauth = 0;          my @types = ('official','unofficial','community','textbook','placement');
         my @types = ('official','unofficial','community','textbook');  
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if ($settings->{'ltiauth'}) {  
                 $ltiauth = 1;  
             }  
             $currdefresponder = $settings->{'anonsurvey_threshold'};              $currdefresponder = $settings->{'anonsurvey_threshold'};
             if (ref($settings->{'uploadquota'}) eq 'HASH') {              if (ref($settings->{'uploadquota'}) eq 'HASH') {
                 foreach my $type (keys(%{$settings->{'uploadquota'}})) {                  foreach my $type (keys(%{$settings->{'uploadquota'}})) {
Line 5543  sub print_coursedefaults { Line 3668  sub print_coursedefaults {
                     foreach my $type (@types) {                      foreach my $type (@types) {
                         if (ref($settings->{'postsubmit'}->{'timeout'}) eq 'HASH') {                          if (ref($settings->{'postsubmit'}->{'timeout'}) eq 'HASH') {
                             if ($settings->{'postsubmit'}->{'timeout'}->{$type} =~ /^\d+$/) {                              if ($settings->{'postsubmit'}->{'timeout'}->{$type} =~ /^\d+$/) {
                                 $deftimeout{$type} = $settings->{'postsubmit'}->{'timeout'}->{$type};                                  $deftimeout{$type} = $settings->{'postsubmit'}->{'timeout'}->{$type}; 
                             } else {                              } else {
                                 $deftimeout{$type} = $staticdefaults{'postsubmit'};                                  $deftimeout{$type} = $staticdefaults{'postsubmit'};
                             }                              }
Line 5659  sub print_coursedefaults { Line 3784  sub print_coursedefaults {
         foreach my $type (@types) {          foreach my $type (@types) {
             $datatable .= '<td align="center">'.&mt($type).'<br />'.              $datatable .= '<td align="center">'.&mt($type).'<br />'.
                            '<input type="text" name="mysqltables_'.$type.'"'.                             '<input type="text" name="mysqltables_'.$type.'"'.
                            ' value="'.$currmysql{$type}.'" size="8" /></td>';                             ' value="'.$currmysql{$type}.'" size="5" /></td>';
         }          }
         $datatable .= '</tr></table></td></tr>'."\n";          $datatable .= '</tr></table></td></tr>'."\n";
         $itemcount ++;          $itemcount ++;
         %defaultchecked = ('ltiauth' => 'off');  
         @toggles = ('ltiauth');  
         $current = {  
                        'ltiauth' => $ltiauth,  
                    };  
         ($table,$itemcount) =  
             &radiobutton_prefs($current,\@toggles,\%defaultchecked,  
                                \%choices,$itemcount,undef,undef,'left');  
         $datatable .= $table;  
         $itemcount ++;  
     }      }
     $$rowtotal += $itemcount;      $$rowtotal += $itemcount;
     return $datatable;      return $datatable;
Line 5682  sub print_selfenrollment { Line 3798  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 5866  sub print_validation_rows { Line 3982  sub print_validation_rows {
                               '</label></span> ';                                '</label></span> ';
             }              }
         } elsif ($item eq 'markup') {          } elsif ($item eq 'markup') {
             $datatable .= '<textarea name="'.$caller.'_validation_markup" cols="50" rows="5">'.              $datatable .= '<textarea name="'.$caller.'_validation_markup" cols="50" rows="5" wrap="soft">'.
                            $currvalidation{$item}.                             $currvalidation{$item}.
                               '</textarea>';                                '</textarea>';
         }          }
Line 5888  sub print_validation_rows { Line 4004  sub print_validation_rows {
         my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',          my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',
                                                        'validationdc',%currhash);                                                         'validationdc',%currhash);
         my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';          my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
         $datatable .= '<tr'.$css_class.'><td>';          $datatable .= '</td></tr><tr'.$css_class.'><td>';
         if ($numdc > 1) {          if ($numdc > 1) {
             $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)');              $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)');
         } else {          } else {
Line 5903  sub print_validation_rows { Line 4019  sub print_validation_rows {
     return $datatable;      return $datatable;
 }  }
   
 sub print_passwords {  sub print_usersessions {
     my ($position,$dom,$confname,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($datatable,$css_class);      my ($css_class,$datatable,$itemcount,%checked,%choices);
     my $itemcount = 0;      my (%by_ip,%by_location,@intdoms,@instdoms);
     my %titles = &Apache::lonlocal::texthash (      &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
         captcha        => '"Forgot Password" CAPTCHA validation',  
         link           => 'Reset link expiration (hours)',      my @alldoms = &Apache::lonnet::all_domains();
         case           => 'Case-sensitive usernames/e-mail',      my %serverhomes = %Apache::lonnet::serverhomeIDs;
         prelink        => 'Information required (form 1)',      my %servers = &Apache::lonnet::internet_dom_servers($dom);
         postlink       => 'Information required (form 2)',      my %altids = &id_for_thisdom(%servers);
         emailsrc       => 'LON-CAPA e-mail address type(s)',  
         customtext     => 'Domain specific text (HTML)',  
         intauth_cost   => 'Encryption cost for bcrypt (positive integer)',  
         intauth_check  => 'Check bcrypt cost if authenticated',  
         intauth_switch => 'Existing crypt-based switched to bcrypt on authentication',  
         permanent      => 'Permanent e-mail address',  
         critical       => 'Critical notification address',  
         notify         => 'Notification address',  
         min            => 'Minimum password length',  
         max            => 'Maximum password length',  
         chars          => 'Required characters',  
         numsaved       => 'Number of previous passwords to save and disallow reuse',  
     );  
     if ($position eq 'top') {      if ($position eq 'top') {
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);          if (keys(%serverhomes) > 1) {
         my $shownlinklife = 2;              my %spareid = &current_offloads_to($dom,$settings,\%servers);
         my $prelink = 'both';              my $curroffloadnow;
         my (%casesens,%postlink,%emailsrc,$nostdtext,$customurl);              if (ref($settings) eq 'HASH') {
         if (ref($settings) eq 'HASH') {                  if (ref($settings->{'offloadnow'}) eq 'HASH') {
             if ($settings->{resetlink} =~ /^\d+(|\.\d*)$/) {                      $curroffloadnow = $settings->{'offloadnow'};
                 $shownlinklife = $settings->{resetlink};  
             }  
             if (ref($settings->{resetcase}) eq 'ARRAY') {  
                 map { $casesens{$_} = 1; } (@{$settings->{resetcase}});  
             }  
             if ($settings->{resetprelink} =~ /^(both|either)$/) {  
                 $prelink = $settings->{resetprelink};  
             }  
             if (ref($settings->{resetpostlink}) eq 'HASH') {  
                 %postlink = %{$settings->{resetpostlink}};  
             }  
             if (ref($settings->{resetemail}) eq 'ARRAY') {  
                 map { $emailsrc{$_} = 1; } (@{$settings->{resetemail}});  
             }  
             if ($settings->{resetremove}) {  
                 $nostdtext = 1;  
             }  
             if ($settings->{resetcustom}) {  
                 $customurl = $settings->{resetcustom};  
             }  
         } else {  
             if (ref($types) eq 'ARRAY') {  
                 foreach my $item (@{$types}) {  
                     $casesens{$item} = 1;  
                     $postlink{$item} = ['username','email'];  
                 }  
             }  
             $casesens{'default'} = 1;  
             $postlink{'default'} = ['username','email'];  
             $prelink = 'both';  
             %emailsrc = (  
                           permanent => 1,  
                           critical  => 1,  
                           notify    => 1,  
             );  
         }  
         $datatable = &captcha_choice('passwords',$settings,$$rowtotal);  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'link'}.'</td>'.  
                       '<td class="LC_left_item">'.  
                       '<input type="textbox" value="'.$shownlinklife.'" '.  
                       'name="passwords_link" size="3" /></td></tr>';  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'case'}.'</td>'.  
                       '<td class="LC_left_item">';  
         if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {  
             foreach my $item (@{$types}) {  
                 my $checkedcase;  
                 if ($casesens{$item}) {  
                     $checkedcase = ' checked="checked"';  
                 }                  }
                 $datatable .= '<span class="LC_nobreak"><label>'.  
                               '<input type="checkbox" name="passwords_case_sensitive" value="'.  
                               $item.'"'.$checkedcase.' />'.$usertypes->{$item}.'</label>'.  
                               '</span>&nbsp;&nbsp; ';  
             }  
         }  
         my $checkedcase;  
         if ($casesens{'default'}) {  
             $checkedcase = ' checked="checked"';  
         }  
         $datatable .= '<span class="LC_nobreak"><label><input type="checkbox" '.  
                       'name="passwords_case_sensitive" value="default"'.$checkedcase.' />'.  
                       $othertitle.'</label></span></td>';  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         my %checkedpre = (  
                              both => ' checked="checked"',  
                              either => '',  
                          );  
         if ($prelink eq 'either') {  
             $checkedpre{either} = ' checked="checked"';  
             $checkedpre{both} = '';  
         }  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'prelink'}.'</td>'.  
                       '<td class="LC_left_item"><span class="LC_nobreak">'.  
                       '<label><input type="radio" name="passwords_prelink" value="both"'.$checkedpre{'both'}.' />'.  
                       &mt('Both username and e-mail address').'</label></span>&nbsp;&nbsp; '.  
                       '<span class="LC_nobreak"><label>'.  
                       '<input type="radio" name="passwords_prelink" value="either"'.$checkedpre{'either'}.' />'.  
                       &mt('Either username or e-mail address').'</label></span></td></tr>';  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'postlink'}.'</td>'.  
                       '<td class="LC_left_item">';  
         my %postlinked;  
         if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {  
             foreach my $item (@{$types}) {  
                 undef(%postlinked);  
                 $datatable .= '<fieldset style="display: inline-block;">'.  
                               '<legend>'.$usertypes->{$item}.'</legend>';  
                 if (ref($postlink{$item}) eq 'ARRAY') {  
                     map { $postlinked{$_} = 1; } (@{$postlink{$item}});  
                 }  
                 foreach my $field ('email','username') {  
                     my $checked;  
                     if ($postlinked{$field}) {  
                         $checked = ' checked="checked"';  
                     }  
                     $datatable .= '<span class="LC_nobreak"><label>'.  
                                   '<input type="checkbox" name="passwords_postlink_'.$item.'" value="'.  
                                   $field.'"'.$checked.' />'.$field.'</label>'.  
                                   '<span>&nbsp;&nbsp; ';  
                 }  
                 $datatable .= '</fieldset>';  
             }  
         }  
         if (ref($postlink{'default'}) eq 'ARRAY') {  
             map { $postlinked{$_} = 1; } (@{$postlink{'default'}});  
         }  
         $datatable .= '<fieldset style="display: inline-block;">'.  
                       '<legend>'.$othertitle.'</legend>';  
         foreach my $field ('email','username') {  
             my $checked;  
             if ($postlinked{$field}) {  
                 $checked = ' checked="checked"';  
             }  
             $datatable .= '<span class="LC_nobreak"><label>'.  
                           '<input type="checkbox" name="passwords_postlink_default" value="'.  
                           $field.'"'.$checked.' />'.$field.'</label>'.  
                           '<span>&nbsp;&nbsp; ';  
         }  
         $datatable .= '</fieldset></td></tr>';  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'emailsrc'}.'</td>'.  
                       '<td class="LC_left_item">';  
         foreach my $type ('permanent','critical','notify') {  
             my $checkedemail;  
             if ($emailsrc{$type}) {  
                 $checkedemail = ' checked="checked"';  
             }              }
             $datatable .= '<span class="LC_nobreak"><label>'.              $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$curroffloadnow,$rowtotal);
                           '<input type="checkbox" name="passwords_emailsrc" value="'.  
                           $type.'"'.$checkedemail.' />'.$titles{$type}.'</label>'.  
                           '<span>&nbsp;&nbsp; ';  
         }  
         $datatable .= '</td></tr>';  
         $itemcount ++;  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         my $switchserver = &check_switchserver($dom,$confname);  
         my ($showstd,$noshowstd);  
         if ($nostdtext) {  
             $noshowstd = ' checked="checked"';  
         } else {  
             $showstd = ' checked="checked"';  
         }  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'customtext'}.'</td>'.  
                       '<td class="LC_left_item"><span class="LC_nobreak">'.  
                       &mt('Retain standard text:').  
                       '<label><input type="radio" name="passwords_stdtext" value="1"'.$showstd.' />'.  
                       &mt('Yes').'</label>'.'&nbsp;'.  
                       '<label><input type="radio" name="passwords_stdtext" value="0"'.$noshowstd.' />'.  
                       &mt('No').'</label></span><br />'.  
                       '<span class="LC_fontsize_small">'.  
                       &mt('(If you use the same account ...  reset a password from this page.)').'</span><br /><br />'.  
                       &mt('Include custom text:');  
         if ($customurl) {  
             my $link =  &Apache::loncommon::modal_link($customurl,&mt('custom text'),600,500,  
                                                        undef,undef,undef,undef,'background-color:#ffffff');  
             $datatable .= '<span class="LC_nobreak">&nbsp;'.$link.  
                           '<label><input type="checkbox" name="passwords_custom_del"'.  
                           ' value="1" />'.&mt('Delete?').'</label></span>'.  
                           ' <span class="LC_nobreak">&nbsp;'.&mt('Replace:').'</span>';  
         }  
         if ($switchserver) {  
             $datatable .= '<span class="LC_nobreak">&nbsp;'.&mt('Upload to library server: [_1]',$switchserver).'</span>';  
         } else {          } else {
             $datatable .='<span class="LC_nobreak">&nbsp;'.              $datatable .= '<tr'.$css_class.'><td colspan="2">'.
                          '<input type="file" name="passwords_customfile" /></span>';                            &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.').
         }                            '</td></tr>';
         $datatable .= '</td></tr>';  
     } elsif ($position eq 'middle') {  
         my %domconf = &Apache::lonnet::get_dom('configuration',['defaults'],$dom);  
         my @items = ('intauth_cost','intauth_check','intauth_switch');  
         my %defaults;  
         if (ref($domconf{'defaults'}) eq 'HASH') {  
             %defaults = %{$domconf{'defaults'}};  
             if ($defaults{'intauth_cost'} !~ /^\d+$/) {  
                 $defaults{'intauth_cost'} = 10;  
             }  
             if ($defaults{'intauth_check'} !~ /^(0|1|2)$/) {  
                 $defaults{'intauth_check'} = 0;  
             }  
             if ($defaults{'intauth_switch'} !~ /^(0|1|2)$/) {  
                 $defaults{'intauth_switch'} = 0;  
             }  
         } else {  
             %defaults = (  
                           'intauth_cost'   => 10,  
                           'intauth_check'  => 0,  
                           'intauth_switch' => 0,  
                         );  
         }  
         foreach my $item (@items) {  
             if ($itemcount%2) {  
                 $css_class = '';  
             } else {  
                 $css_class = ' class="LC_odd_row" ';  
             }  
             $datatable .= '<tr'.$css_class.'>'.  
                           '<td><span class="LC_nobreak">'.$titles{$item}.  
                           '</span></td><td class="LC_left_item" colspan="3">';  
             if ($item eq 'intauth_switch') {  
                 my @options = (0,1,2);  
                 my %optiondesc = &Apache::lonlocal::texthash (  
                                    0 => 'No',  
                                    1 => 'Yes',  
                                    2 => 'Yes, and copy existing passwd file to passwd.bak file',  
                                  );  
                 $datatable .= '<table width="100%">';  
                 foreach my $option (@options) {  
                     my $checked = ' ';  
                     if ($defaults{$item} eq $option) {  
                         $checked = ' checked="checked"';  
                     }  
                     $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.  
                                   '<label><input type="radio" name="'.$item.  
                                   '" value="'.$option.'"'.$checked.' />'.  
                                   $optiondesc{$option}.'</label></span></td></tr>';  
                 }  
                 $datatable .= '</table>';  
             } elsif ($item eq 'intauth_check') {  
                 my @options = (0,1,2);  
                 my %optiondesc = &Apache::lonlocal::texthash (  
                                    0 => 'No',  
                                    1 => 'Yes, allow login then update passwd file using default cost (if higher)',  
                                    2 => 'Yes, disallow login if stored cost is less than domain default',  
                                  );  
                 $datatable .= '<table width="100%">';  
                 foreach my $option (@options) {  
                     my $checked = ' ';  
                     my $onclick;  
                     if ($defaults{$item} eq $option) {  
                         $checked = ' checked="checked"';  
                     }  
                     if ($option == 2) {  
                         $onclick = ' onclick="javascript:warnIntAuth(this);"';  
                     }  
                     $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.  
                                   '<label><input type="radio" name="'.$item.  
                                   '" value="'.$option.'"'.$checked.$onclick.' />'.  
                                   $optiondesc{$option}.'</label></span></td></tr>';  
                 }  
                 $datatable .= '</table>';  
             } else {  
                 $datatable .= '<input type="text" name="'.$item.'" value="'.  
                               $defaults{$item}.'" size="3" onblur="javascript:warnIntAuth(this);" />';  
             }  
             $datatable .= '</td></tr>';  
             $itemcount ++;  
         }          }
     } elsif ($position eq 'lower') {  
         $datatable .= &password_rules('passwords',\$itemcount,$settings);  
     } else {      } else {
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);          my %titles = &usersession_titles();
         my %ownerchg = (          my ($prefix,@types);
                           by  => {},          if ($position eq 'bottom') {
                           for => {},              $prefix = 'remote';
                        );              @types = ('version','excludedomain','includedomain');
         my %ownertitles = &Apache::lonlocal::texthash (          } else {
                             by  => 'Course owner status(es) allowed',              $prefix = 'hosted';
                             for => 'Student status(es) allowed',              @types = ('excludedomain','includedomain');
                           );  
         if (ref($settings) eq 'HASH') {  
             if (ref($settings->{crsownerchg}) eq 'HASH') {  
                 if (ref($settings->{crsownerchg}{'by'}) eq 'ARRAY') {  
                     map { $ownerchg{by}{$_} = 1; } (@{$settings->{crsownerchg}{'by'}});  
                 }  
                 if (ref($settings->{crsownerchg}{'for'}) eq 'ARRAY') {  
                     map { $ownerchg{for}{$_} = 1; } (@{$settings->{crsownerchg}{'for'}});  
                 }  
             }  
         }  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr '.$css_class.'>'.  
                       '<td>'.  
                       &mt('Requirements').'<ul>'.  
                       '<li>'.&mt("Course 'type' is not a Community").'</li>'.  
                       '<li>'.&mt('User is Course Coordinator and also course owner').'</li>'.  
                       '<li>'.&mt("Student's only active roles are student role(s) in course(s) owned by this user").'</li>'.  
                       '<li>'.&mt('User, course, and student share same domain').'</li>'.  
                       '</ul>'.  
                       '</td>'.  
                       '<td class="LC_left_item">';  
         foreach my $item ('by','for') {  
             $datatable .= '<fieldset style="display: inline-block;">'.  
                           '<legend>'.$ownertitles{$item}.'</legend>';  
             if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {  
                 foreach my $type (@{$types}) {  
                     my $checked;  
                     if ($ownerchg{$item}{$type}) {  
                         $checked = ' checked="checked"';  
                     }  
                     $datatable .= '<span class="LC_nobreak"><label>'.  
                                   '<input type="checkbox" name="passwords_crsowner_'.$item.'" value="'.  
                                   $type.'"'.$checked.' />'.$usertypes->{$type}.'</label>'.  
                                   '</span>&nbsp;&nbsp; ';  
                 }  
             }  
             my $checked;  
             if ($ownerchg{$item}{'default'}) {  
                 $checked = ' checked="checked"';  
             }  
             $datatable .= '<span class="LC_nobreak"><label><input type="checkbox" '.  
                           'name="passwords_crsowner_'.$item.'" value="default"'.$checked.' />'.  
                           $othertitle.'</label></span></fieldset>';  
         }  
         $datatable .= '</td></tr>';  
     }  
     return $datatable;  
 }  
   
 sub password_rules {  
     my ($prefix,$itemcountref,$settings) = @_;  
     my ($min,$max,%chars,$numsaved,$numinrow);  
     my %titles;  
     if ($prefix eq 'passwords') {  
         %titles = &Apache::lonlocal::texthash (  
             min            => 'Minimum password length',  
             max            => 'Maximum password length',  
             chars          => 'Required characters',  
         );  
     } elsif ($prefix eq 'secrets') {  
         %titles = &Apache::lonlocal::texthash (  
             min            => 'Minimum secret length',  
             max            => 'Maximum secret length',  
             chars          => 'Required characters',  
         );  
     }  
     $min = $Apache::lonnet::passwdmin;  
     my $datatable;  
     my $itemcount;  
     if (ref($itemcountref)) {  
         $itemcount = $$itemcountref;  
     }  
     if (ref($settings) eq 'HASH') {  
         if ($settings->{min}) {  
             $min = $settings->{min};  
         }  
         if ($settings->{max}) {  
             $max = $settings->{max};  
         }  
         if (ref($settings->{chars}) eq 'ARRAY') {  
             map { $chars{$_} = 1; } (@{$settings->{chars}});  
         }  
         if ($prefix eq 'passwords') {  
             if ($settings->{numsaved}) {  
                 $numsaved = $settings->{numsaved};  
             }  
         }  
     }  
     my %rulenames = &Apache::lonlocal::texthash(  
                                                  uc => 'At least one upper case letter',  
                                                  lc => 'At least one lower case letter',  
                                                  num => 'At least one number',  
                                                  spec => 'At least one non-alphanumeric',  
                                                );  
     my $css_class = $itemcount%2?' class="LC_odd_row"':'';  
     $datatable .= '<tr'.$css_class.'><td>'.$titles{'min'}.'</td>'.  
                   '<td class="LC_left_item"><span class="LC_nobreak">'.  
                   '<input type="text" name="'.$prefix.'_min" value="'.$min.'" size="3" '.  
                   'onblur="javascript:warnInt'.$prefix.'(this);" />'.  
                   '<span class="LC_fontsize_small"> '.&mt('(Enter an integer: 7 or larger)').'</span>'.  
                   '</span></td></tr>';  
     $itemcount ++;  
     $css_class = $itemcount%2?' class="LC_odd_row"':'';  
     $datatable .= '<tr'.$css_class.'><td>'.$titles{'max'}.'</td>'.  
                   '<td class="LC_left_item"><span class="LC_nobreak">'.  
                   '<input type="text" name="'.$prefix.'_max" value="'.$max.'" size="3" '.  
                   'onblur="javascript:warnInt'.$prefix.'(this);" />'.  
                   '<span class="LC_fontsize_small"> '.&mt('(Leave blank for no maximum)').'</span>'.  
                   '</span></td></tr>';  
     $itemcount ++;  
     $css_class = $itemcount%2?' class="LC_odd_row"':'';  
     $datatable .= '<tr'.$css_class.'><td>'.$titles{'chars'}.'<br />'.  
                   '<span class="LC_nobreak LC_fontsize_small">'.&mt('(Leave unchecked if not required)').  
                   '</span></td>';  
     my $numinrow = 2;  
     my @possrules = ('uc','lc','num','spec');  
     $datatable .= '<td class="LC_left_item"><table>';  
     for (my $i=0; $i<@possrules; $i++) {  
         my ($rem,$checked);  
         if ($chars{$possrules[$i]}) {  
             $checked = ' checked="checked"';  
         }  
         $rem = $i%($numinrow);  
         if ($rem == 0) {  
             if ($i > 0) {  
                 $datatable .= '</tr>';  
             }  
             $datatable .= '<tr>';  
         }          }
         $datatable .= '<td><span class="LC_nobreak"><label>'.          ($datatable,$itemcount) = &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
                       '<input type="checkbox" name="'.$prefix.'_chars" value="'.$possrules[$i].'"'.$checked.' />'.  
                       $rulenames{$possrules[$i]}.'</label></span></td>';  
     }  
     my $rem = @possrules%($numinrow);  
     my $colsleft = $numinrow - $rem;  
     if ($colsleft > 1 ) {  
         $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.  
                       '&nbsp;</td>';  
     } elsif ($colsleft == 1) {  
         $datatable .= '<td class="LC_left_item">&nbsp;</td>';  
     }  
     $datatable .='</table></td></tr>';  
     $itemcount ++;  
     if ($prefix eq 'passwords') {  
         $titles{'numsaved'} = &mt('Number of previous passwords to save and disallow reuse');  
         $css_class = $itemcount%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'><td>'.$titles{'numsaved'}.'</td>'.  
                       '<td class="LC_left_item"><span class="LC_nobreak">'.  
                       '<input type="text" name="'.$prefix.'_numsaved" value="'.$numsaved.'" size="3" '.  
                       'onblur="javascript:warnInt'.$prefix.'(this);" />'.  
                       '<span class="LC_fontsize_small"> '.&mt('(Leave blank to not save previous passwords)').'</span>'.  
                       '</span></td></tr>';  
         $itemcount ++;  
     }  
     if (ref($itemcountref)) {  
         $$itemcountref += $itemcount;  
     }      }
       $$rowtotal += $itemcount;
     return $datatable;      return $datatable;
 }  }
   
 sub print_wafproxy {  sub rules_by_location {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($settings,$prefix,$by_location,$by_ip,$types,$titles) = @_; 
     my $css_class;      my ($datatable,$itemcount,$css_class);
     my $itemcount = 0;      if (keys(%{$by_location}) == 0) {
     my $datatable;          $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
     my %servers = &Apache::lonnet::internet_dom_servers($dom);          $datatable = '<tr'.$css_class.'><td colspan="2">'.
     my (%othercontrol,%otherdoms,%aliases,%saml,%values,$setdom,$showdom);                       &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.').
     my %lt = &wafproxy_titles();                       '</td></tr>';
     foreach my $server (sort(keys(%servers))) {          $itemcount = 1;
         my $serverhome = &Apache::lonnet::get_server_homeID($servers{$server});      } else {
         next if ($serverhome eq '');          $itemcount = 0;
         my $serverdom;          my $numinrow = 5;
         if ($serverhome ne $server) {          my (%current,%checkedon,%checkedoff);
             $serverdom = &Apache::lonnet::host_domain($serverhome);          my @locations = sort(keys(%{$by_location}));
             if (($serverdom ne '') && (&Apache::lonnet::domain($serverdom) ne '')) {          foreach my $type (@{$types}) {
                 $othercontrol{$server} = $serverdom;              $checkedon{$type} = '';
             }              $checkedoff{$type} = ' checked="checked"';
         } else {  
             $serverdom = &Apache::lonnet::host_domain($server);  
             next if (($serverdom eq '') || (&Apache::lonnet::domain($serverdom) eq ''));  
             if ($serverdom ne $dom) {  
                 $othercontrol{$server} = $serverdom;  
             } else {  
                 $setdom = 1;  
                 if (ref($settings) eq 'HASH') {  
                     if (ref($settings->{'alias'}) eq 'HASH') {  
                         $aliases{$dom} = $settings->{'alias'};  
                         if ($aliases{$dom} ne '') {  
                             $showdom = 1;  
                         }  
                     }  
                     if (ref($settings->{'saml'}) eq 'HASH') {  
                         $saml{$dom} = $settings->{'saml'};  
                     }  
                 }  
             }  
         }          }
     }  
     if ($setdom) {  
         %{$values{$dom}} = ();  
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {              if (ref($settings->{$prefix}) eq 'HASH') {
                 $values{$dom}{$item} = $settings->{$item};                  foreach my $key (keys(%{$settings->{$prefix}})) {
             }                      $current{$key} = $settings->{$prefix}{$key};
         }                      if ($key eq 'version') {
     }                          if ($current{$key} ne '') {
     if (keys(%othercontrol)) {                              $checkedon{$key} = ' checked="checked"';
         %otherdoms = reverse(%othercontrol);                              $checkedoff{$key} = '';
         foreach my $domain (keys(%otherdoms)) {                          }
             %{$values{$domain}} = ();                      } elsif (ref($current{$key}) eq 'ARRAY') {
             my %config = &Apache::lonnet::get_dom('configuration',['wafproxy'],$domain);                          $checkedon{$key} = ' checked="checked"';
             if (ref($config{'wafproxy'}) eq 'HASH') {                          $checkedoff{$key} = '';
                 $aliases{$domain} = $config{'wafproxy'}{'alias'};  
                 if (exists($config{'wafproxy'}{'saml'})) {  
                     $saml{$domain} = $config{'wafproxy'}{'saml'};  
                 }  
                 foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {  
                     $values{$domain}{$item} = $config{'wafproxy'}{$item};  
                 }  
             }  
         }  
     }  
     if ($position eq 'top') {  
         my %servers = &Apache::lonnet::internet_dom_servers($dom);  
         my %aliasinfo;  
         foreach my $server (sort(keys(%servers))) {  
             $itemcount ++;  
             my $dom_in_effect;  
             my $aliasrows = '<tr>'.  
                             '<td class="LC_left_item" style="vertical-align: baseline;">'.  
                             &mt('Hostname').':&nbsp;'.  
                             '<i>'.&Apache::lonnet::hostname($server).'</i></td><td>&nbsp;</td>';  
             if ($othercontrol{$server}) {  
                 $dom_in_effect = $othercontrol{$server};  
                 my ($current,$forsaml);  
                 if (ref($aliases{$dom_in_effect}) eq 'HASH') {  
                     $current = $aliases{$dom_in_effect}{$server};  
                 }  
                 if (ref($saml{$dom_in_effect}) eq 'HASH') {  
                     if ($saml{$dom_in_effect}{$server}) {  
                         $forsaml = 1;  
                     }  
                 }  
                 $aliasrows .= '<td class="LC_left_item" style="vertical-align: baseline;">'.  
                               &mt('Alias').':&nbsp';  
                 if ($current) {  
                     $aliasrows .= $current;  
                     if ($forsaml) {  
                          $aliasrows .= '&nbsp;('.&mt('also for SSO Auth').')';  
                     }                      }
                 } else {  
                     $aliasrows .= &mt('None');  
                 }                  }
                 $aliasrows .= '&nbsp;<span class="LC_small">('.  
                               &mt('controlled by domain: [_1]',  
                                   '<b>'.$dom_in_effect.'</b>').')</span></td>';  
             } else {  
                 $dom_in_effect = $dom;  
                 my ($current,$samlon,$samloff);  
                 $samloff = ' checked="checked"';  
                 if (ref($aliases{$dom}) eq 'HASH') {  
                     if ($aliases{$dom}{$server}) {  
                         $current = $aliases{$dom}{$server};  
                     }  
                 }  
                 if (ref($saml{$dom}) eq 'HASH') {  
                     if ($saml{$dom}{$server}) {  
                         $samlon = $samloff;  
                         undef($samloff);  
                     }  
                 }  
                 $aliasrows .= '<td class="LC_left_item" style="vertical-align: baseline;">'.  
                               &mt('Alias').':&nbsp;'.  
                               '<input type="text" name="wafproxy_alias_'.$server.'" '.  
                               'value="'.$current.'" size="30" />'.  
                               ('&nbsp;'x2).'<span class="LC_nobreak">'.  
                               &mt('Alias used for SSO Auth').':&nbsp;<label>'.  
                               '<input type="radio" value="0"'.$samloff.' name="wafproxy_alias_saml_'.$server.'" />'.  
                               &mt('No').'</label>&nbsp;<label>'.  
                               '<input type="radio" value="1"'.$samlon.' name="wafproxy_alias_saml_'.$server.'" />'.  
                               &mt('Yes').'</label></span>'.  
                               '</td>';  
             }  
             $aliasrows .= '</tr>';  
             $aliasinfo{$dom_in_effect} .= $aliasrows;  
         }  
         if ($aliasinfo{$dom}) {  
             my ($onclick,$wafon,$wafoff,$showtable);  
             $onclick = ' onclick="javascript:toggleWAF();"';  
             $wafoff = ' checked="checked"';  
             $showtable = ' style="display:none";';  
             if ($showdom) {  
                 $wafon = $wafoff;  
                 $wafoff = '';  
                 $showtable = ' style="display:inline;"';  
             }  
             $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';  
             $datatable = '<tr'.$css_class.'>'.  
                          '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$dom.'</b>').'<br />'.  
                          '<span class="LC_nobreak">'.&mt('WAF in use?').'&nbsp;<label>'.  
                          '<input type="radio" name="wafproxy_'.$dom.'" value="1"'.$wafon.$onclick.' />'.  
                          &mt('Yes').'</label>'.('&nbsp;'x2).'<label>'.  
                          '<input type="radio" name="wafproxy_'.$dom.'" value="0"'.$wafoff.$onclick.' />'.  
                          &mt('No').'</label></span></td>'.  
                          '<td class="LC_left_item">'.  
                          '<table id="wafproxy_table"'.$showtable.'>'.$aliasinfo{$dom}.  
                          '</table></td></tr>';  
             $itemcount++;  
         }  
         if (keys(%otherdoms)) {  
             foreach my $key (sort(keys(%otherdoms))) {  
                 $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';  
                 $datatable .= '<tr'.$css_class.'>'.  
                               '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$key.'</b>').'</td>'.  
                               '<td class="LC_left_item"><table>'.$aliasinfo{$key}.  
                               '</table></td></tr>';  
                 $itemcount++;  
             }              }
         }          }
     } else {          foreach my $type (@{$types}) {
         my %ip_methods = &remoteip_methods();              next if ($type ne 'version' && !@locations);
         if ($setdom) {  
             $itemcount ++;  
             $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';              $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
             my ($nowafstyle,$wafstyle,$curr_remotip,$currwafdisplay,$vpndircheck,$vpnaliascheck,              $datatable .= '<tr'.$css_class.'>
                 $currwafvpn,$wafrangestyle,$alltossl,$ssltossl);                             <td><span class="LC_nobreak">'.$titles->{$type}.'</span><br />
             $wafstyle = ' style="display:none;"';                             <span class="LC_nobreak">&nbsp;
             $nowafstyle = ' style="display:table-row;"';                             <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>&nbsp;
             $currwafdisplay = ' style="display: none"';                             <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';
             $wafrangestyle = ' style="display: none"';              if ($type eq 'version') {
             $curr_remotip = 'n';                  my @lcversions = &Apache::lonnet::all_loncaparevs();
             $ssltossl = ' checked="checked"';                  my $selector = '<select name="'.$prefix.'_version">';
             if ($showdom) {                  foreach my $version (@lcversions) {
                 $wafstyle = ' style="display:table-row;"';                      my $selected = '';
                 $nowafstyle =  ' style="display:none;"';                      if ($current{'version'} eq $version) {
                 if (keys(%{$values{$dom}})) {                          $selected = ' selected="selected"';
                     if ($values{$dom}{remoteip} =~ /^[nmh]$/) {                      }
                         $curr_remotip = $values{$dom}{remoteip};                      $selector .= ' <option value="'.$version.'"'.
                     }                                   $selected.'>'.$version.'</option>';
                     if ($curr_remotip eq 'h') {  
                         $currwafdisplay = ' style="display:table-row"';  
                         $wafrangestyle = ' style="display:inline-block;"';  
                     }  
                     if ($values{$dom}{'sslopt'}) {  
                         $alltossl = ' checked="checked"';  
                         $ssltossl = '';  
                     }  
                 }  
                 if (($values{$dom}{'vpnint'} ne '') || ($values{$dom}{'vpnext'} ne '')) {  
                     $vpndircheck = ' checked="checked"';  
                     $currwafvpn = ' style="display:table-row;"';  
                     $wafrangestyle = ' style="display:inline-block;"';  
                 } else {  
                     $vpnaliascheck = ' checked="checked"';  
                     $currwafvpn = ' style="display:none;"';  
                 }                  }
             }                  $selector .= '</select> ';
             $datatable .= '<tr'.$css_class.' id="nowafproxyrow_'.$dom.'"'.$wafstyle.'>'.                  $datatable .= &mt('remote server must be version: [_1] or later',$selector);
                           '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$dom.'</b>').'</td>'.              } else {
                           '<td class="LC_right_item">'.&mt('WAF not in use, nothing to set').'</td>'.                  $datatable.= '<div><input type="button" value="'.&mt('check all').'" '.
                           '</tr>'.                               'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.
                           '<tr'.$css_class.' id="wafproxyrow_'.$dom.'"'.$wafstyle.'>'.                               ' />'.('&nbsp;'x2).
                           '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$dom.'</b>').'<br /><br />'.                               '<input type="button" value="'.&mt('uncheck all').'" '.
                           '<div id="wafproxyranges_'.$dom.'">'.&mt('Format for comma separated IP ranges').':<br />'.                               'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.
                           &mt('A.B.C.D/N or A.B.C.D-E.F.G.H').'<br />'.                               "\n".
                           &mt('Range(s) stored in CIDR notation').'</div></td>'.                               '</div><div><table>';
                           '<td class="LC_left_item"><table>'.                  my $rem;
                           '<tr>'.                  for (my $i=0; $i<@locations; $i++) {
                           '<td valign="top">'.$lt{'remoteip'}.':&nbsp;'.                      my ($showloc,$value,$checkedtype);
                           '<select name="wafproxy_remoteip" id="wafproxy_remoteip" onchange="javascript:updateWAF();">';                      if (ref($by_location->{$locations[$i]}) eq 'ARRAY') {
             foreach my $option ('m','h','n') {                          my $ip = $by_location->{$locations[$i]}->[0];
                 my $sel;                          if (ref($by_ip->{$ip}) eq 'ARRAY') {
                 if ($option eq $curr_remotip) {                              $value = join(':',@{$by_ip->{$ip}});
                    $sel = ' selected="selected"';                              $showloc = join(', ',@{$by_ip->{$ip}});
                 }                              if (ref($current{$type}) eq 'ARRAY') {
                 $datatable .= '<option value="'.$option.'"'.$sel.'>'.                                  foreach my $loc (@{$by_ip->{$ip}}) {
                               $ip_methods{$option}.'</option>';                                      if (grep(/^\Q$loc\E$/,@{$current{$type}})) {
             }                                          $checkedtype = ' checked="checked"';
             $datatable .= '</select></td></tr>'."\n".                                          last;
                           '<tr id="wafproxy_header"'.$currwafdisplay.'><td>'.                                      }
                           $lt{'ipheader'}.':&nbsp;'.                                  }
                           '<input type="text" value="'.$values{$dom}{'ipheader'}.'" '.                              }
                           'name="wafproxy_ipheader" />'.  
                           '</td></tr>'."\n".  
                           '<tr id="wafproxy_trust"'.$currwafdisplay.'><td>'.  
                           $lt{'trusted'}.':<br />'.  
                           '<textarea name="wafproxy_trusted" rows="3" cols="80">'.  
                           $values{$dom}{'trusted'}.'</textarea>'.  
                           '</td></tr>'."\n".  
                           '<tr><td><hr /></td></tr>'."\n".  
                           '<tr>'.  
                           '<td valign="top">'.$lt{'vpnaccess'}.':<br /><span class="LC_nobreak">'.  
                           '<label><input type="radio" name="wafproxy_vpnaccess"'.$vpndircheck.' value="1" onclick="javascript:checkWAF();" />'.  
                           $lt{'vpndirect'}.'</label>'.('&nbsp;'x2).  
                           '<label><input type="radio" name="wafproxy_vpnaccess"'.$vpnaliascheck.' value="0" onclick="javascript:checkWAF();" />'.  
                           $lt{'vpnaliased'}.'</label></span></td></tr>';  
             foreach my $item ('vpnint','vpnext') {  
                 $datatable .= '<tr id="wafproxy_show_'.$item.'"'.$currwafvpn.'>'.  
                               '<td valign="top">'.$lt{$item}.':<br />'.  
                               '<textarea name="wafproxy_'.$item.'" rows="3" cols="80">'.  
                               $values{$dom}{$item}.'</textarea>'.  
                               '</td></tr>'."\n";  
             }  
             $datatable .= '<tr><td><hr /></td></tr>'."\n".  
                           '<tr>'.  
                           '<td valign="top">'.$lt{'sslopt'}.':<br /><span class="LC_nobreak">'.  
                           '<label><input type="radio" name="wafproxy_sslopt"'.$alltossl.' value="1" />'.  
                           $lt{'alltossl'}.'</label>'.('&nbsp;'x2).  
                           '<label><input type="radio" name="wafproxy_sslopt"'.$ssltossl.' value="0" />'.  
                           $lt{'ssltossl'}.'</label></span></td></tr>'."\n".  
                           '</table></td></tr>';  
         }  
         if (keys(%otherdoms)) {  
             foreach my $domain (sort(keys(%otherdoms))) {  
                 $itemcount ++;  
                 $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';  
                 $datatable .= '<tr'.$css_class.'>'.  
                               '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$domain.'</b>').'</td>'.  
                               '<td class="LC_left_item"><table>';  
                 foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext','sslopt') {  
                     my $showval = &mt('None');  
                     if ($item eq 'ssl') {  
                         $showval = $lt{'ssltossl'};  
                     }  
                     if ($values{$domain}{$item}) {  
                         $showval = $values{$domain}{$item};  
                         if ($item eq 'ssl') {  
                             $showval = $lt{'alltossl'};  
                         } elsif ($item eq 'remoteip') {  
                             $showval = $ip_methods{$values{$domain}{$item}};  
                         }                          }
                     }                      }
                     $datatable .= '<tr>'.                      $rem = $i%($numinrow);
                                   '<td>'.$lt{$item}.':&nbsp;'.$showval.'</td></tr>';                      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>';
                 }                  }
                 $datatable .= '</table></td></tr>';                  $rem = @locations%($numinrow);
                   my $colsleft = $numinrow - $rem;
                   if ($colsleft > 1 ) {
                       $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                                     '&nbsp;</td>';
                   } elsif ($colsleft == 1) {
                       $datatable .= '<td class="LC_left_item">&nbsp;</td>';
                   }
                   $datatable .= '</tr></table>';
             }              }
               $datatable .= '</td></tr>';
               $itemcount ++;
         }          }
     }      }
     $$rowtotal += $itemcount;      return ($datatable,$itemcount);
     return $datatable;  
 }  
   
 sub wafproxy_titles {  
     return &Apache::lonlocal::texthash(  
                remoteip   => "Method for determining user's IP",  
                ipheader   => 'Request header containing remote IP',  
                trusted    => 'Trusted IP range(s)',  
                vpnaccess  => 'Access from institutional VPN',  
                vpndirect  => 'via regular hostname (no WAF)',  
                vpnaliased => 'via aliased hostname (WAF)',  
                vpnint     => 'Internal IP Range(s) for VPN sessions',  
                vpnext     => 'IP Range(s) for backend WAF connections',  
                sslopt     => 'Forwarding http/https',  
                alltossl   => 'WAF forwards both http and https requests to https',  
                ssltossl   => 'WAF forwards http requests to http and https to https',  
            );  
 }  
   
 sub remoteip_methods {  
     return &Apache::lonlocal::texthash(  
               m => 'Use Apache mod_remoteip',  
               h => 'Use headers parsed by LON-CAPA',  
               n => 'Not in use',  
            );  
 }  }
   
 sub print_usersessions {  sub print_ssl {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable,%checked,%choices);      my ($css_class,$datatable);
     my (%by_ip,%by_location,@intdoms);  
     &build_location_hashes(\@intdoms,\%by_ip,\%by_location);  
   
     my @alldoms = &Apache::lonnet::all_domains();  
     my %serverhomes = %Apache::lonnet::serverhomeIDs;  
     my %servers = &Apache::lonnet::internet_dom_servers($dom);  
     my %altids = &id_for_thisdom(%servers);  
     my $itemcount = 1;      my $itemcount = 1;
     if ($position eq 'top') {      if ($position eq 'top') {
         if (keys(%serverhomes) > 1) {          my $primary_id = &Apache::lonnet::domain($dom,'primary');
             my %spareid = &current_offloads_to($dom,$settings,\%servers);          my $intdom = &Apache::lonnet::internet_dom($primary_id);
             my ($curroffloadnow,$curroffloadoth);          my $same_institution;
             if (ref($settings) eq 'HASH') {          if ($intdom ne '') {
                 if (ref($settings->{'offloadnow'}) eq 'HASH') {              my $internet_names = &Apache::lonnet::get_internet_names($Apache::lonnet::perlvar{'lonHostID'});
                     $curroffloadnow = $settings->{'offloadnow'};              if (ref($internet_names) eq 'ARRAY') {
                 }                  if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
                 if (ref($settings->{'offloadoth'}) eq 'HASH') {                      $same_institution = 1;
                     $curroffloadoth = $settings->{'offloadoth'};  
                 }                  }
             }              }
             my $other_insts = scalar(keys(%by_location));          }
             $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,          $css_class = $itemcount%2?' class="LC_odd_row"':'';
                                       $other_insts,$curroffloadnow,$curroffloadoth,$rowtotal);          $datatable = '<tr'.$css_class.'><td colspan="2">';
           if ($same_institution) {
               my %domservers = &Apache::lonnet::get_servers($dom);
               $datatable .= &LONCAPA::SSL::print_certstatus(\%domservers,'web','domprefs');
         } else {          } else {
             $datatable .= '<tr'.$css_class.'><td colspan="2">'.              $datatable .= &mt("You need to be logged into one of your own domain's servers to display information about the status of LON-CAPA SSL certificates.");
                           &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.');  
         }          }
           $datatable .= '</td></tr>';
           $itemcount ++;
     } else {      } else {
         if (keys(%by_location) == 0) {          my %titles = &ssl_titles();
             $datatable .= '<tr'.$css_class.'><td colspan="2">'.          my (%by_ip,%by_location,@intdoms,@instdoms);
                           &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.');          &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
         } else {          my @alldoms = &Apache::lonnet::all_domains();
             my %lt = &usersession_titles();          my %serverhomes = %Apache::lonnet::serverhomeIDs;
             my $numinrow = 5;          my @domservers = &Apache::lonnet::get_servers($dom);
             my $prefix;          my %servers = &Apache::lonnet::internet_dom_servers($dom);
             my @types;          my %altids = &id_for_thisdom(%servers);
             if ($position eq 'bottom') {          if ($position eq 'middle') {
                 $prefix = 'remote';              foreach my $type ('dom','intdom','other') {
                 @types = ('version','excludedomain','includedomain');                  my %checked;
             } else {                  $css_class = $itemcount%2?' class="LC_odd_row"':'';
                 $prefix = 'hosted';                  $datatable .= '<tr'.$css_class.'><td>'.$titles{$type}.'</td>'.
                 @types = ('excludedomain','includedomain');                                '<td class="LC_right_item">';
             }                  my $skip; 
             my (%current,%checkedon,%checkedoff);                  if ($type eq 'dom') {
             my @lcversions = &Apache::lonnet::all_loncaparevs();                      unless (keys(%servers) > 1) {
             my @locations = sort(keys(%by_location));                          $datatable .= &mt('Nothing to set here, as there are no other servers/VMs');    
             foreach my $type (@types) {                          $skip = 1;
                 $checkedon{$type} = '';  
                 $checkedoff{$type} = ' checked="checked"';  
             }  
             if (ref($settings) eq 'HASH') {  
                 if (ref($settings->{$prefix}) eq 'HASH') {  
                     foreach my $key (keys(%{$settings->{$prefix}})) {  
                         $current{$key} = $settings->{$prefix}{$key};  
                         if ($key eq 'version') {  
                             if ($current{$key} ne '') {  
                                 $checkedon{$key} = ' checked="checked"';  
                                 $checkedoff{$key} = '';  
                             }  
                         } elsif (ref($current{$key}) eq 'ARRAY') {  
                             $checkedon{$key} = ' checked="checked"';  
                             $checkedoff{$key} = '';  
                         }  
                     }                      }
                 }                  }
             }                  if ($type eq 'intdom') {
             foreach my $type (@types) {                      unless (@instdoms > 1) {
                 next if ($type ne 'version' && !@locations);                          $datatable .= &mt('Nothing to set here, as there are no other domains for this institution');
                 $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';                          $skip = 1;
                 $datatable .= '<tr'.$css_class.'>                      } 
                                <td><span class="LC_nobreak">'.$lt{$type}.'</span><br />                  } elsif ($type eq 'other') {
                                <span class="LC_nobreak">&nbsp;                      if (keys(%by_location) == 0) {
                                <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>&nbsp;                          $datatable .= &mt('Nothing to set here, as there are no other institutions');
                                <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';                          $skip = 1;
                 if ($type eq 'version') {  
                     my $selector = '<select name="'.$prefix.'_version">';  
                     foreach my $version (@lcversions) {  
                         my $selected = '';  
                         if ($current{'version'} eq $version) {  
                             $selected = ' selected="selected"';  
                         }  
                         $selector .= ' <option value="'.$version.'"'.  
                                      $selected.'>'.$version.'</option>';  
                     }                      }
                     $selector .= '</select> ';                  }
                     $datatable .= &mt('remote server must be version: [_1] or later',$selector);                  unless ($skip) {
                 } else {                      $checked{'yes'} = ' checked="checked"'; 
                     $datatable.= '<div><input type="button" value="'.&mt('check all').'" '.                      if (ref($settings) eq 'HASH') {
                                  'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.                          if (ref($settings->{'connect'}) eq 'HASH') {
                                  ' />'.('&nbsp;'x2).                              if ($settings->{'connect'}->{$type} =~ /^(no|req)$/) {
                                  '<input type="button" value="'.&mt('uncheck all').'" '.                                  $checked{$1} = $checked{'yes'};
                                  'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.                                  delete($checked{'yes'}); 
                                  "\n".  
                                  '</div><div><table>';  
                     my $rem;  
                     for (my $i=0; $i<@locations; $i++) {  
                         my ($showloc,$value,$checkedtype);  
                         if (ref($by_location{$locations[$i]}) eq 'ARRAY') {  
                             my $ip = $by_location{$locations[$i]}->[0];  
                             if (ref($by_ip{$ip}) eq 'ARRAY') {  
                                  $value = join(':',@{$by_ip{$ip}});  
                                 $showloc = join(', ',@{$by_ip{$ip}});  
                                 if (ref($current{$type}) eq 'ARRAY') {  
                                     foreach my $loc (@{$by_ip{$ip}}) {    
                                         if (grep(/^\Q$loc\E$/,@{$current{$type}})) {  
                                             $checkedtype = ' checked="checked"';  
                                             last;  
                                         }  
                                     }  
                                 }  
                             }                              }
                         }                          }
                         $rem = $i%($numinrow);  
                         if ($rem == 0) {  
                             if ($i > 0) {  
                                 $datatable .= '</tr>';  
                             }  
                             $datatable .= '<tr>';  
                         }  
                         $datatable .= '<td class="LC_left_item">'.  
                                       '<span class="LC_nobreak"><label>'.  
                                       '<input type="checkbox" name="'.$prefix.'_'.$type.  
                                       '" value="'.$value.'"'.$checkedtype.' />'.$showloc.  
                                       '</label></span></td>';  
                     }                      }
                     $rem = @locations%($numinrow);                      foreach my $option ('no','yes','req') {
                     my $colsleft = $numinrow - $rem;                          $datatable .= '<span class="LC_nobreak"><label>'.
                     if ($colsleft > 1 ) {                                        '<input type="radio" name="connect_'.$type.'" '.
                         $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.                                        'value="'.$option.'"'.$checked{$option}.' />'.$titles{$option}.
                                       '&nbsp;</td>';                                        '</label></span>'.('&nbsp;'x2);
                     } elsif ($colsleft == 1) {  
                         $datatable .= '<td class="LC_left_item">&nbsp;</td>';  
                     }                      }
                     $datatable .= '</tr></table>';  
                 }                  }
                 $datatable .= '</td></tr>';                  $datatable .= '</td></tr>';
                   $itemcount ++; 
               }
           } else {
               my $prefix = 'replication';
               my @types = ('certreq','nocertreq');
               if (keys(%by_location) == 0) {
                   $datatable .= '<tr'.$css_class.'><td>'.
                                 &mt('Nothing to set here, as there are no other institutions').
                                 '</td></tr>';
                 $itemcount ++;                  $itemcount ++;
               } else {
                   ($datatable,$itemcount) = 
                       &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
             }              }
         }          }
     }      }
Line 6813  sub print_usersessions { Line 4268  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',
                  connect       => 'Connections to 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 6833  sub build_location_hashes { Line 4337  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 6941  sub current_offloads_to { Line 4451  sub current_offloads_to {
 }  }
   
 sub spares_row {  sub spares_row {
     my ($dom,$servers,$spareid,$serverhomes,$altids,$other_insts,      my ($dom,$servers,$spareid,$serverhomes,$altids,$curroffloadnow,$rowtotal) = @_;
         $curroffloadnow,$curroffloadoth,$rowtotal) = @_;  
     my $css_class;      my $css_class;
     my $numinrow = 4;      my $numinrow = 4;
     my $itemcount = 1;      my $itemcount = 1;
Line 6962  sub spares_row { Line 4471  sub spares_row {
                 }                  }
             }              }
             next unless (ref($spareid->{$server}) eq 'HASH');              next unless (ref($spareid->{$server}) eq 'HASH');
             my ($checkednow,$checkedoth);              my $checkednow;
             if (ref($curroffloadnow) eq 'HASH') {              if (ref($curroffloadnow) eq 'HASH') {
                 if ($curroffloadnow->{$server}) {                  if ($curroffloadnow->{$server}) {
                     $checkednow = ' checked="checked"';                      $checkednow = ' checked="checked"';
                 }                  }
             }              }
             if (ref($curroffloadoth) eq 'HASH') {  
                 if ($curroffloadoth->{$server}) {  
                     $checkedoth = ' checked="checked"';  
                 }  
             }  
             $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';              $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
             $datatable .= '<tr'.$css_class.'>              $datatable .= '<tr'.$css_class.'>
                            <td rowspan="2">                             <td rowspan="2">
                             <span class="LC_nobreak">'.                              <span class="LC_nobreak">'.
                           &mt('[_1] when busy, offloads to:'                            &mt('[_1] when busy, offloads to:'
                               ,'<b>'.$server.'</b>').'</span><br />'.                                ,'<b>'.$server.'</b>').'</span><br />'.
                           '<span class="LC_nobreak">'."\n".                            '<span class="LC_nobreak">'."\n". 
                           '<label><input type="checkbox" name="offloadnow" value="'.$server.'"'.$checkednow.' />'.                            '<label><input type="checkbox" name="offloadnow" value="'.$server.'"'.$checkednow.' />'.
                           '&nbsp;'.&mt('Switch any active user on next access').'</label></span>'.                            '&nbsp;'.&mt('Switch active users on next access').'</label></span>'.
                           "\n";                            "\n";
             if ($other_insts) {  
                 $datatable .= '<br />'.  
                               '<span class="LC_nobreak">'."\n".  
                           '<label><input type="checkbox" name="offloadoth" value="'.$server.'"'.$checkedoth.' />'.  
                           '&nbsp;'.&mt('Switch other institutions on next access').'</label></span>'.  
                           "\n";  
             }  
             my (%current,%canselect);              my (%current,%canselect);
             my @choices =               my @choices = 
                 &possible_newspares($server,$spareid->{$server},$serverhomes,$altids);                  &possible_newspares($server,$spareid->{$server},$serverhomes,$altids);
Line 7113  sub print_loadbalancing { Line 4610  sub print_loadbalancing {
     my $numinrow = 1;      my $numinrow = 1;
     my $datatable;      my $datatable;
     my %servers = &Apache::lonnet::internet_dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
     my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);      my (%currbalancer,%currtargets,%currrules,%existing);
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         %existing = %{$settings};          %existing = %{$settings};
     }      }
     if ((keys(%servers) > 1) || (keys(%existing) > 0)) {      if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
         &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,          &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
                                   \%currtargets,\%currrules,\%currcookies);                                    \%currtargets,\%currrules);
     } else {      } else {
         return;          return;
     }      }
Line 7196  sub print_loadbalancing { Line 4693  sub print_loadbalancing {
         my %hostherechecked = (          my %hostherechecked = (
                                   no => ' checked="checked"',                                    no => ' checked="checked"',
                               );                                );
         my %balcookiechecked = (  
                                   no => ' checked="checked"',  
                                );  
         foreach my $sparetype (@sparestypes) {          foreach my $sparetype (@sparestypes) {
             my $targettable;              my $targettable;
             for (my $i=0; $i<$numspares; $i++) {              for (my $i=0; $i<$numspares; $i++) {
Line 7254  sub print_loadbalancing { Line 4748  sub print_loadbalancing {
                 }                  }
             }              }
         }          }
         if ($currcookies{$lonhost}) {  
             %balcookiechecked = (  
                                     yes => ' checked="checked"',  
                                 );  
         }  
         $datatable .= &mt('Hosting on balancer itself').'<br />'.          $datatable .= &mt('Hosting on balancer itself').'<br />'.
                       '<label><input type="radio" name="loadbalancing_target_'.$balnum.'_hosthere" value="no"'.                        '<label><input type="radio" name="loadbalancing_target_'.$balnum.'_hosthere" value="no"'.
                       $hostherechecked{'no'}.' />'.&mt('No').'</label><br />';                        $hostherechecked{'no'}.' />'.&mt('No').'</label><br />';
Line 7267  sub print_loadbalancing { Line 4756  sub print_loadbalancing {
                           'value="'.$sparetype.'"'.$hostherechecked{$sparetype}.' /><i>'.$typetitles{$sparetype}.                            'value="'.$sparetype.'"'.$hostherechecked{$sparetype}.' /><i>'.$typetitles{$sparetype}.
                           '</i></label><br />';                            '</i></label><br />';
         }          }
         $datatable .= &mt('Use balancer cookie').'<br />'.          $datatable .= '</div></td></tr>'.
                       '<label><input type="radio" name="loadbalancing_cookie_'.$balnum.'" value="1"'.  
                       $balcookiechecked{'yes'}.' />'.&mt('Yes').'</label><br />'.  
                       '<label><input type="radio" name="loadbalancing_cookie_'.$balnum.'" value="0"'.  
                       $balcookiechecked{'no'}.' />'.&mt('No').'</label><br />'.  
                       '</div></td></tr>'.  
                       &loadbalancing_rules($dom,$intdom,$currrules{$lonhost},                        &loadbalancing_rules($dom,$intdom,$currrules{$lonhost},
                                            $othertitle,$usertypes,$types,\%servers,                                             $othertitle,$usertypes,$types,\%servers,
                                            \%currbalancer,$lonhost,                                             \%currbalancer,$lonhost,
Line 7286  sub print_loadbalancing { Line 4770  sub print_loadbalancing {
 }  }
   
 sub get_loadbalancers_config {  sub get_loadbalancers_config {
     my ($servers,$existing,$currbalancer,$currtargets,$currrules,$currcookies) = @_;      my ($servers,$existing,$currbalancer,$currtargets,$currrules) = @_;
     return unless ((ref($servers) eq 'HASH') &&      return unless ((ref($servers) eq 'HASH') &&
                    (ref($existing) eq 'HASH') && (ref($currbalancer) eq 'HASH') &&                     (ref($existing) eq 'HASH') && (ref($currbalancer) eq 'HASH') &&
                    (ref($currtargets) eq 'HASH') && (ref($currrules) eq 'HASH') &&                     (ref($currtargets) eq 'HASH') && (ref($currrules) eq 'HASH'));
                    (ref($currcookies) eq 'HASH'));  
     if (keys(%{$existing}) > 0) {      if (keys(%{$existing}) > 0) {
         my $oldlonhost;          my $oldlonhost;
         foreach my $key (sort(keys(%{$existing}))) {          foreach my $key (sort(keys(%{$existing}))) {
Line 7309  sub get_loadbalancers_config { Line 4792  sub get_loadbalancers_config {
                 $currbalancer->{$key} = 1;                  $currbalancer->{$key} = 1;
                 $currtargets->{$key} = $existing->{$key}{'targets'};                  $currtargets->{$key} = $existing->{$key}{'targets'};
                 $currrules->{$key} = $existing->{$key}{'rules'};                  $currrules->{$key} = $existing->{$key}{'rules'};
                 if ($existing->{$key}{'cookie'}) {  
                     $currcookies->{$key} = 1;  
                 }  
             }              }
         }          }
     } else {      } else {
Line 7367  sub loadbalancing_titles { Line 4847  sub loadbalancing_titles {
            '_LC_ipchange'    => &mt('Non-SSO users with IP mismatch'),             '_LC_ipchange'    => &mt('Non-SSO users with IP mismatch'),
                      );                       );
     my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external','_LC_ipchangesso','_LC_ipchange');      my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external','_LC_ipchangesso','_LC_ipchange');
     my @available;  
     if (ref($types) eq 'ARRAY') {      if (ref($types) eq 'ARRAY') {
         @available = @{$types};          unshift(@alltypes,@{$types},'default');
     }      }
     unless (grep(/^default$/,@available)) {  
         push(@available,'default');  
     }  
     unshift(@alltypes,@available);  
     my %titles;      my %titles;
     foreach my $type (@alltypes) {      foreach my $type (@alltypes) {
         if ($type =~ /^_LC_/) {          if ($type =~ /^_LC_/) {
Line 7497  sub sparestype_titles { Line 4972  sub sparestype_titles {
   
 sub contact_titles {  sub contact_titles {
     my %titles = &Apache::lonlocal::texthash (      my %titles = &Apache::lonlocal::texthash (
                    'supportemail'    => 'Support E-mail address',                     'supportemail' => 'Support E-mail address',
                    'adminemail'      => 'Default Server Admin E-mail address',                     'adminemail'   => 'Default Server Admin E-mail address',
                    'errormail'       => 'Error reports to be e-mailed to',                     'errormail'    => 'Error reports to be e-mailed to',
                    'packagesmail'    => 'Package update alerts to be e-mailed to',                     'packagesmail' => 'Package update alerts to be e-mailed to',
                    'helpdeskmail'    => "Helpdesk requests from all users in this domain",                     'helpdeskmail' => 'Helpdesk requests to be e-mailed to',
                    'otherdomsmail'   => 'Helpdesk requests from users in other (unconfigured) domains',                     'lonstatusmail' => 'E-mail from nightly status check (warnings/errors)',
                    'lonstatusmail'   => 'E-mail from nightly status check (warnings/errors)',                     'requestsmail' => 'E-mail from course requests requiring approval',
                    'requestsmail'    => 'E-mail from course requests requiring approval',                     'updatesmail'  => 'E-mail from nightly check of LON-CAPA module integrity/updates',
                    'updatesmail'     => 'E-mail from nightly check of LON-CAPA module integrity/updates',  
                    'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID',                     'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID',
                    'hostipmail'      => 'E-mail from nightly check of hostname/IP network changes',  
                    'errorthreshold'  => 'Error count threshold for status e-mail to admin(s)',  
                    'errorsysmail'    => 'Error count threshold for e-mail to developer group',  
                    'errorweights'    => 'Weights used to compute error count',  
                    'errorexcluded'   => 'Servers with unsent updates excluded from count',  
                  );                   );
     my %short_titles = &Apache::lonlocal::texthash (      my %short_titles = &Apache::lonlocal::texthash (
                            adminemail   => 'Admin E-mail address',                             adminemail   => 'Admin E-mail address',
Line 7520  sub contact_titles { Line 4989  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',
                      blog       => 'Blog',                       blog       => 'Blog',
                      webdav     => 'WebDAV',                       webdav     => 'WebDAV',
                      portfolio  => 'Portfolio',                       portfolio  => 'Portfolio',
                      timezone   => 'Can set time zone',  
                      official   => 'Official courses (with institutional codes)',                       official   => 'Official courses (with institutional codes)',
                      unofficial => 'Unofficial courses',                       unofficial => 'Unofficial courses',
                      community  => 'Communities',                       community  => 'Communities',
                      textbook   => 'Textbook courses',                       textbook   => 'Textbook courses',
                        placement  => 'Placement tests',
                  );                   );
     return %titles;      return %titles;
 }  }
Line 7569  sub courserequest_titles { Line 5010  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 7733  sub print_usercreation { Line 5175  sub print_usercreation {
   
 sub print_selfcreation {  sub print_selfcreation {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my (@selfcreate,$createsettings,$processing,$emailoptions,$emailverified,      my (@selfcreate,$createsettings,$processing,$datatable);
         $emaildomain,$datatable);  
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{'cancreate'}) eq 'HASH') {          if (ref($settings->{'cancreate'}) eq 'HASH') {
             $createsettings = $settings->{'cancreate'};              $createsettings = $settings->{'cancreate'};
Line 7751  sub print_selfcreation { Line 5192  sub print_selfcreation {
                 if (ref($createsettings->{'selfcreateprocessing'}) eq 'HASH') {                  if (ref($createsettings->{'selfcreateprocessing'}) eq 'HASH') {
                     $processing = $createsettings->{'selfcreateprocessing'};                      $processing = $createsettings->{'selfcreateprocessing'};
                 }                  }
                 if (ref($createsettings->{'emailoptions'}) eq 'HASH') {  
                     $emailoptions = $createsettings->{'emailoptions'};  
                 }  
                 if (ref($createsettings->{'emailverified'}) eq 'HASH') {  
                     $emailverified = $createsettings->{'emailverified'};  
                 }  
                 if (ref($createsettings->{'emaildomain'}) eq 'HASH') {  
                     $emaildomain = $createsettings->{'emaildomain'};  
                 }  
             }              }
         }          }
     }      }
     my %radiohash;      my %radiohash;
     my $numinrow = 4;      my $numinrow = 4;
     map { $radiohash{'cancreate_'.$_} = 1; } @selfcreate;      map { $radiohash{'cancreate_'.$_} = 1; } @selfcreate;
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
     if ($position eq 'top') {      if ($position eq 'top') {
         my %choices = &Apache::lonlocal::texthash (          my %choices = &Apache::lonlocal::texthash (
                                                       cancreate_login      => 'Institutional Login',                                                        cancreate_login      => 'Institutional Login',
Line 7781  sub print_selfcreation { Line 5212  sub print_selfcreation {
         ($datatable,$itemcount) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,          ($datatable,$itemcount) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,
                                                      \%choices,$itemcount,$onclick);                                                       \%choices,$itemcount,$onclick);
         $$rowtotal += $itemcount;          $$rowtotal += $itemcount;
           
           my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
   
         if (ref($usertypes) eq 'HASH') {          if (ref($usertypes) eq 'HASH') {
             if (keys(%{$usertypes}) > 0) {              if (keys(%{$usertypes}) > 0) {
                 $datatable .= &insttypes_row($createsettings,$types,$usertypes,                  $datatable .= &insttypes_row($createsettings,$types,$usertypes,
                                              $dom,$numinrow,$othertitle,                                               $dom,$numinrow,$othertitle,
                                              'statustocreate',$rowtotal);                                               'statustocreate',$$rowtotal);
                 $$rowtotal ++;                  $$rowtotal ++;
             }              }
         }          }
Line 7799  sub print_selfcreation { Line 5232  sub print_selfcreation {
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                      '<td class="LC_left_item">'.&mt('Mapping of Shibboleth environment variable names to user data fields (SSO auth)').'</td>'.                       '<td class="LC_left_item">'.&mt('Mapping of Shibboleth environment variable names to user data fields (SSO auth)').'</td>'.
                      '<td class="LC_left_item">'."\n".                       '<td class="LC_left_item">'."\n".
                      '<table>'."\n";                       '<table><tr><td>'."\n";
         for (my $i=0; $i<@fields; $i++) {          for (my $i=0; $i<@fields; $i++) {
             $rem = $i%($numperrow);              $rem = $i%($numperrow);
             if ($rem == 0) {              if ($rem == 0) {
Line 7831  sub print_selfcreation { Line 5264  sub print_selfcreation {
         $$rowtotal ++;          $$rowtotal ++;
     } elsif ($position eq 'middle') {      } elsif ($position eq 'middle') {
         my %domconf = &Apache::lonnet::get_dom('configuration',['usermodification'],$dom);          my %domconf = &Apache::lonnet::get_dom('configuration',['usermodification'],$dom);
         my @posstypes;          my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
           $usertypes->{'default'} = $othertitle;
         if (ref($types) eq 'ARRAY') {          if (ref($types) eq 'ARRAY') {
             @posstypes = @{$types};              push(@{$types},'default');
         }              $usertypes->{'default'} = $othertitle;
         unless (grep(/^default$/,@posstypes)) {              foreach my $status (@{$types}) {
             push(@posstypes,'default');                  $datatable .= &modifiable_userdata_row('selfcreate',$status,$domconf{'usermodification'},
         }                                                         $numinrow,$$rowtotal,$usertypes);
         my %usertypeshash;                  $$rowtotal ++;
         if (ref($usertypes) eq 'HASH') {              }
             %usertypeshash = %{$usertypes};  
         }  
         $usertypeshash{'default'} = $othertitle;  
         foreach my $status (@posstypes) {  
             $datatable .= &modifiable_userdata_row('selfcreate',$status,$domconf{'usermodification'},  
                                                    $numinrow,$$rowtotal,\%usertypeshash);  
             $$rowtotal ++;  
         }          }
     } else {      } else {
         my %choices = &Apache::lonlocal::texthash (          my %choices = &Apache::lonlocal::texthash (
                           'cancreate_email' => 'Non-institutional username (via e-mail verification)',                                                        cancreate_email => 'E-mail address as username',
                                                   );                                                    );
         my @toggles = sort(keys(%choices));          my @toggles = sort(keys(%choices));
         my %defaultchecked = (          my %defaultchecked = (
                                'cancreate_email' => 'off',                                 'cancreate_email' => 'off',
                              );                               );
         my $customclass = 'LC_selfcreate_email';          my $itemcount = 0;
         my $classprefix = 'LC_canmodify_emailusername_';  
         my $optionsprefix = 'LC_options_emailusername_';  
         my $display = 'none';          my $display = 'none';
         my $rowstyle = 'display:none';  
         if (grep(/^\Qemail\E$/,@selfcreate)) {          if (grep(/^\Qemail\E$/,@selfcreate)) {
             $display = 'block';              $display = 'block';
             $rowstyle = 'display:table-row';  
         }          }
         my $onclick = "toggleRows(this.form,'cancreate_email','selfassign','$customclass','$classprefix','$optionsprefix');";          my $onclick = "toggleDisplay(this.form,'emailoptions');";
         ($datatable,$$rowtotal) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,          my $additional = '<div id="emailoptions" style="display: '.$display.'">';
                                                      \%choices,$$rowtotal,$onclick);  
         $datatable .= &print_requestmail($dom,'selfcreation',$createsettings,$rowtotal,$customclass,  
                                          $rowstyle);  
         $$rowtotal ++;  
         $datatable .= &captcha_choice('cancreate',$createsettings,$$rowtotal,$customclass,  
                                       $rowstyle);  
         $$rowtotal ++;  
         my (@ordered,@posstypes,%usertypeshash);  
         my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);          my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
         my ($emailrules,$emailruleorder) =          my $usertypes = {};
             &Apache::lonnet::inst_userrules($dom,'email');          my $order = [];
         my $primary_id = &Apache::lonnet::domain($dom,'primary');          if ((ref($domdefaults{'inststatustypes'}) eq 'HASH') && (ref($domdefaults{'inststatusguest'}) eq 'ARRAY')) {
         my $intdom = &Apache::lonnet::internet_dom($primary_id);              $usertypes = $domdefaults{'inststatustypes'};
         if (ref($types) eq 'ARRAY') {              $order = $domdefaults{'inststatusguest'};
             @posstypes = @{$types};          }
         }          if (ref($order) eq 'ARRAY') {
         if (@posstypes) {              push(@{$order},'default');
             unless (grep(/^default$/,@posstypes)) {              if (@{$order} > 1) {
                 push(@posstypes,'default');                  $usertypes->{'default'} = &mt('Other users');
             }                  $additional .= '<table><tr>';
             if (ref($usertypes) eq 'HASH') {                  foreach my $status (@{$order}) {
                 %usertypeshash = %{$usertypes};                      $additional .= '<th>'.$usertypes->{$status}.'</th>';
             }                  }
             my $currassign;                  $additional .= '</tr><tr>';
             if (ref($domdefaults{'inststatusguest'}) eq 'ARRAY') {                  foreach my $status (@{$order}) {
                 $currassign = {                      $additional .= '<td>'.&email_as_username($rowtotal,$processing,$status).'</td>';
                                   selfassign => $domdefaults{'inststatusguest'},  
                               };  
                 @ordered = @{$domdefaults{'inststatusguest'}};  
             } else {  
                 $currassign = { selfassign => [] };  
             }  
             my $onclicktypes = "toggleDataRow(this.form,'selfassign','$customclass','$optionsprefix',);".  
                                "toggleDataRow(this.form,'selfassign','$customclass','$classprefix',1);";  
             $datatable .= &insttypes_row($currassign,$types,$usertypes,$dom,  
                                          $numinrow,$othertitle,'selfassign',  
                                          $rowtotal,$onclicktypes,$customclass,  
                                          $rowstyle);  
             $$rowtotal ++;  
             $usertypeshash{'default'} = $othertitle;  
             foreach my $status (@posstypes) {  
                 my $css_class;  
                 if ($$rowtotal%2) {  
                     $css_class = 'LC_odd_row ';  
                 }  
                 $css_class .= $customclass;  
                 my $rowid = $optionsprefix.$status;  
                 my $hidden = 1;  
                 my $currstyle = 'display:none';  
                 if (grep(/^\Q$status\E$/,@ordered)) {  
                     $currstyle = $rowstyle;  
                     $hidden = 0;  
                 }  
                 $datatable .= &noninst_users($processing,$emailverified,$emailoptions,$emaildomain,  
                                              $emailrules,$emailruleorder,$settings,$status,$rowid,  
                                              $usertypeshash{$status},$css_class,$currstyle,$intdom);  
                 unless ($hidden) {  
                     $$rowtotal ++;  
                 }                  }
                   $additional .= '</tr></table>';
               } else {
                   $usertypes->{'default'} = &mt('All users');
                   $additional .= &email_as_username($rowtotal,$processing);
             }              }
         } else {  
             my $css_class;  
             if ($$rowtotal%2) {  
                 $css_class = 'LC_odd_row ';  
             }  
             $css_class .= $customclass;  
             $usertypeshash{'default'} = $othertitle;  
             $datatable .= &noninst_users($processing,$emailverified,$emailoptions,$emaildomain,  
                                          $emailrules,$emailruleorder,$settings,'default','',  
                                          $othertitle,$css_class,$rowstyle,$intdom);  
             $$rowtotal ++;  
         }          }
           $additional .= '</div>'."\n";
   
           ($datatable,$itemcount) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,
                                                        \%choices,$$rowtotal,$onclick,$additional);
           $$rowtotal ++;
           $datatable .= &print_requestmail($dom,'selfcreation',$createsettings,$rowtotal);
           $$rowtotal ++;
         my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();          my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();
         $numinrow = 1;          $numinrow = 1;
         if (@posstypes) {          if (ref($order) eq 'ARRAY') {
             foreach my $status (@posstypes) {              foreach my $status (@{$order}) {
                 my $rowid = $classprefix.$status;  
                 my $datarowstyle = 'display:none';  
                 if (grep(/^\Q$status\E$/,@ordered)) {  
                     $datarowstyle = $rowstyle;  
                 }  
                 $datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,                  $datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,
                                                        $numinrow,$$rowtotal,\%usertypeshash,$infofields,                                                         $numinrow,$$rowtotal,$usertypes,$infofields,$infotitles);
                                                        $infotitles,$rowid,$customclass,$datarowstyle);                  $$rowtotal ++;
                 unless ($datarowstyle eq 'display:none') {  
                     $$rowtotal ++;  
                 }  
             }              }
         } else {  
             $datatable .= &modifiable_userdata_row('cancreate','emailusername_default',$settings,  
                                                    $numinrow,$$rowtotal,\%usertypeshash,$infofields,  
                                                    $infotitles,'',$customclass,$rowstyle);  
         }          }
     }          my ($emailrules,$emailruleorder) =
     return $datatable;              &Apache::lonnet::inst_userrules($dom,'email');
 }          if (ref($emailrules) eq 'HASH') {
               if (keys(%{$emailrules}) > 0) {
 sub selfcreate_javascript {                  $datatable .= &user_formats_row('email',$settings,$emailrules,
     return <<"ENDSCRIPT";                                                  $emailruleorder,$numinrow,$$rowtotal);
                   $$rowtotal ++;
 <script type="text/javascript">  
 // <![CDATA[  
   
 function toggleRows(form,radio,checkbox,target,prefix,altprefix) {  
     var x = document.getElementsByClassName(target);  
     var insttypes = 0;  
     var insttypeRegExp = new RegExp(prefix);  
     if ((x.length != undefined) && (x.length > 0)) {  
         if (form.elements[radio].length != undefined) {  
             for (var i=0; i<form.elements[radio].length; i++) {  
                 if (form.elements[radio][i].checked) {  
                     if (form.elements[radio][i].value == 1) {  
                         for (var j=0; j<x.length; j++) {  
                             if (x[j].id == 'undefined') {  
                                 x[j].style.display = 'table-row';  
                             } else if (insttypeRegExp.test(x[j].id)) {  
                                 insttypes ++;  
                             } else {  
                                 x[j].style.display = 'table-row';  
                             }  
                         }  
                     } else {  
                         for (var j=0; j<x.length; j++) {  
                             x[j].style.display = 'none';  
                         }  
                     }  
                     break;  
                 }  
             }  
             if (insttypes > 0) {  
                 toggleDataRow(form,checkbox,target,altprefix);  
                 toggleDataRow(form,checkbox,target,prefix,1);  
             }              }
         }          }
           $datatable .= &captcha_choice('cancreate',$createsettings,$$rowtotal);
     }      }
     return;      return $datatable;
 }  }
   
 function toggleDataRow(form,checkbox,target,prefix,docount) {  sub email_as_username {
     if (form.elements[checkbox].length != undefined) {      my ($rowtotal,$processing,$type) = @_;
         var count = 0;      my %choices =
         if (docount) {          &Apache::lonlocal::texthash (
             for (var i=0; i<form.elements[checkbox].length; i++) {                                        automatic => 'Automatic approval',
                 if (form.elements[checkbox][i].checked) {                                        approval  => 'Queued for approval',
                     count ++;                                      );
                 }      my $output;
             }      foreach my $option ('automatic','approval') {
         }          my $checked;
         for (var i=0; i<form.elements[checkbox].length; i++) {          if (ref($processing) eq 'HASH') {
             var type = form.elements[checkbox][i].value;              if ($type eq '') {   
             if (document.getElementById(prefix+type)) {                  if (!exists($processing->{'default'})) {
                 if (form.elements[checkbox][i].checked) {                      if ($option eq 'automatic') {
                     document.getElementById(prefix+type).style.display = 'table-row';                          $checked = ' checked="checked"';
                     if (count % 2 == 1) {  
                         document.getElementById(prefix+type).className = target+' LC_odd_row';  
                     } else {  
                         document.getElementById(prefix+type).className = target;  
                     }                      }
                     count ++;  
                 } else {                  } else {
                     document.getElementById(prefix+type).style.display = 'none';                      if ($processing->{'default'} eq $option) {
                 }                          $checked = ' checked="checked"';
             }  
         }  
     }  
     return;  
 }  
   
 function toggleEmailOptions(form,radio,prefix,altprefix,status) {  
     var caller = radio+'_'+status;  
     if (form.elements[caller].length != undefined) {  
         for (var i=0; i<form.elements[caller].length; i++) {  
             if (form.elements[caller][i].checked) {  
                 if (document.getElementById(altprefix+'_inst_'+status)) {  
                     var curr = form.elements[caller][i].value;  
                     if (prefix) {  
                         document.getElementById(prefix+'_'+status).style.display = 'none';  
                     }  
                     document.getElementById(altprefix+'_inst_'+status).style.display = 'none';  
                     document.getElementById(altprefix+'_noninst_'+status).style.display = 'none';  
                     if (curr == 'custom') {  
                         if (prefix) {  
                             document.getElementById(prefix+'_'+status).style.display = 'inline';  
                         }  
                     } else if (curr == 'inst') {  
                         document.getElementById(altprefix+'_inst_'+status).style.display = 'inline';  
                     } else if (curr == 'noninst') {  
                         document.getElementById(altprefix+'_noninst_'+status).style.display = 'inline';  
                     }  
                     break;  
                 }  
             }  
         }  
     }  
 }  
   
 // ]]>  
 </script>  
   
 ENDSCRIPT  
 }  
   
 sub noninst_users {  
     my ($processing,$emailverified,$emailoptions,$emaildomain,$emailrules,  
         $emailruleorder,$settings,$type,$rowid,$typetitle,$css_class,$rowstyle,$intdom) = @_;  
     my $class = 'LC_left_item';  
     if ($css_class) {  
         $css_class = ' class="'.$css_class.'"';  
     }  
     if ($rowid) {  
         $rowid = ' id="'.$rowid.'"';  
     }  
     if ($rowstyle) {  
         $rowstyle = ' style="'.$rowstyle.'"';  
     }  
     my ($output,$description);  
     if ($type eq 'default') {  
         $description = &mt('Requests for: [_1]',$typetitle);  
     } else {  
         $description = &mt('Requests for: [_1] (status self-reported)',$typetitle);  
     }  
     $output = '<tr'.$css_class.$rowid.$rowstyle.'>'.  
               "<td>$description</td>\n".  
               '<td class="'.$class.'" colspan="2">'.  
               '<table><tr>';  
     my %headers = &Apache::lonlocal::texthash(  
               approve  => 'Processing',  
               email    => 'E-mail',  
               username => 'Username',  
     );  
     foreach my $item ('approve','email','username') {  
         $output .= '<th>'.$headers{$item}.'</th>';  
     }  
     $output .= '</tr><tr>';  
     foreach my $item ('approve','email','username') {  
         $output .= '<td valign="top">';  
         my (%choices,@options,$hashref,$defoption,$name,$onclick,$hascustom);  
         if ($item eq 'approve') {  
             %choices = &Apache::lonlocal::texthash (  
                                                      automatic => 'Automatically approved',  
                                                      approval  => 'Queued for approval',  
                                                    );  
             @options = ('automatic','approval');  
             $hashref = $processing;  
             $defoption = 'automatic';  
             $name = 'cancreate_emailprocess_'.$type;  
         } elsif ($item eq 'email') {  
             %choices = &Apache::lonlocal::texthash (  
                                                      any     => 'Any e-mail',  
                                                      inst    => 'Institutional only',  
                                                      noninst => 'Non-institutional only',  
                                                      custom  => 'Custom restrictions',  
                                                    );  
             @options = ('any','inst','noninst');  
             my $showcustom;  
             if (ref($emailrules) eq 'HASH') {  
                 if (keys(%{$emailrules}) > 0) {  
                     push(@options,'custom');  
                     $showcustom = 'cancreate_emailrule';  
                     if (ref($settings) eq 'HASH') {  
                         if (ref($settings->{'email_rule'}) eq 'ARRAY') {  
                             foreach my $rule (@{$settings->{'email_rule'}}) {  
                                 if (exists($emailrules->{$rule})) {  
                                     $hascustom ++;  
                                 }  
                             }  
                         } elsif (ref($settings->{'email_rule'}) eq 'HASH') {  
                             if (ref($settings->{'email_rule'}{$type}) eq 'ARRAY') {  
                                 foreach my $rule (@{$settings->{'email_rule'}{$type}}) {  
                                     if (exists($emailrules->{$rule})) {  
                                         $hascustom ++;  
                                     }  
                                 }  
                             }  
                         }  
                     }                      }
                 }                  }
             }              } else {
             $onclick = ' onclick="toggleEmailOptions(this.form,'."'cancreate_emailoptions','$showcustom',".                  if (!exists($processing->{$type})) {
                                                      "'cancreate_emaildomain','$type'".');"';                      if ($option eq 'automatic') {
             $hashref = $emailoptions;                          $checked = ' checked="checked"';
             $defoption = 'any';  
             $name = 'cancreate_emailoptions_'.$type;  
         } elsif ($item eq 'username') {  
             %choices = &Apache::lonlocal::texthash (  
                                                      all    => 'Same as e-mail',  
                                                      first  => 'Omit @domain',  
                                                      free   => 'Free to choose',  
                                                    );  
             @options = ('all','first','free');  
             $hashref = $emailverified;  
             $defoption = 'all';  
             $name = 'cancreate_usernameoptions_'.$type;  
         }  
         foreach my $option (@options) {  
             my $checked;  
             if (ref($hashref) eq 'HASH') {  
                 if ($type eq '') {  
                     if (!exists($hashref->{'default'})) {  
                         if ($option eq $defoption) {  
                             $checked = ' checked="checked"';  
                         }  
                     } else {  
                         if ($hashref->{'default'} eq $option) {  
                             $checked = ' checked="checked"';  
                         }  
                     }                      }
                 } else {                  } else {
                     if (!exists($hashref->{$type})) {                      if ($processing->{$type} eq $option) {
                         if ($option eq $defoption) {                          $checked = ' checked="checked"';
                             $checked = ' checked="checked"';  
                         }  
                     } else {  
                         if ($hashref->{$type} eq $option) {  
                             $checked = ' checked="checked"';  
                         }  
                     }  
                 }  
             } elsif (($item eq 'email') && ($hascustom)) {  
                 if ($option eq 'custom') {  
                     $checked = ' checked="checked"';  
                 }  
             } elsif ($option eq $defoption) {  
                 $checked = ' checked="checked"';  
             }  
             $output .= '<span class="LC_nobreak"><label>'.  
                        '<input type="radio" name="'.$name.'"'.  
                        $checked.' value="'.$option.'"'.$onclick.' />'.  
                        $choices{$option}.'</label></span><br />';  
             if ($item eq 'email') {  
                 if ($option eq 'custom') {  
                     my $id = 'cancreate_emailrule_'.$type;  
                     my $display = 'none';  
                     if ($checked) {  
                         $display = 'inline';  
                     }  
                     my $numinrow = 2;  
                     $output .= '<fieldset id="'.$id.'" style="display:'.$display.';">'.  
                                '<legend>'.&mt('Disallow').'</legend><table>'.  
                                &user_formats_row('email',$settings,$emailrules,  
                                                  $emailruleorder,$numinrow,'',$type);  
                               '</table></fieldset>';  
                 } elsif (($option eq 'inst') || ($option eq 'noninst')) {  
                     my %text = &Apache::lonlocal::texthash (  
                                                              inst    => 'must end:',  
                                                              noninst => 'cannot end:',  
                                                            );  
                     my $value;  
                     if (ref($emaildomain) eq 'HASH') {  
                         if (ref($emaildomain->{$type}) eq 'HASH') {  
                             $value = $emaildomain->{$type}->{$option};  
                         }  
                     }  
                     if ($value eq '') {  
                         $value = '@'.$intdom;  
                     }  
                     my $condition = 'cancreate_emaildomain_'.$option.'_'.$type;  
                     my $display = 'none';  
                     if ($checked) {  
                         $display = 'inline';  
                     }                      }
                     $output .= '<div id="'.$condition.'" style="display:'.$display.';">'.  
                                '<span class="LC_domprefs_email">'.$text{$option}.'</span> '.  
                                '<input type="text" name="'.$condition.'" value="'.$value.'" size="10" />'.  
                                '</div>';  
                 }                  }
             }              }
           } elsif ($option eq 'automatic') {
               $checked = ' checked="checked"'; 
           }
           my $name = 'cancreate_emailprocess';
           if (($type ne '') && ($type ne 'default')) {
               $name .= '_'.$type;
           }
           $output .= '<span class="LC_nobreak"><label>'.
                      '<input type="radio" name="'.$name.'"'.
                      $checked.' value="'.$option.'" />'.
                      $choices{$option}.'</label></span>';
           if ($type eq '') {
               $output .= '&nbsp;';
           } else {
               $output .= '<br />';
         }          }
         $output .= '</td>'."\n";  
     }      }
     $output .= "</tr></table></td></tr>\n";      $$rowtotal ++;
     return $output;      return $output;
 }  }
   
 sub captcha_choice {  sub captcha_choice {
     my ($context,$settings,$itemcount,$customcss,$rowstyle) = @_;      my ($context,$settings,$itemcount) = @_;
     my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext,      my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext,
         $vertext,$currver);           $vertext,$currver);
     my %lt = &captcha_phrases();      my %lt = &captcha_phrases();
     $keyentry = 'hidden';      $keyentry = 'hidden';
     my $colspan=2;  
     if ($context eq 'cancreate') {      if ($context eq 'cancreate') {
         $rowname = &mt('CAPTCHA validation');          $rowname = &mt('CAPTCHA validation');
     } elsif ($context eq 'login') {      } elsif ($context eq 'login') {
         $rowname =  &mt('"Contact helpdesk" CAPTCHA validation');          $rowname =  &mt('"Contact helpdesk" CAPTCHA validation');
     } elsif ($context eq 'passwords') {  
         $rowname = &mt('"Forgot Password" CAPTCHA validation');  
         $colspan=1;  
     }      }
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if ($settings->{'captcha'}) {          if ($settings->{'captcha'}) {
Line 8279  sub captcha_choice { Line 5432  sub captcha_choice {
     } else {      } else {
         $checked{'original'} = ' checked="checked"';          $checked{'original'} = ' checked="checked"';
     }      }
     my $css_class;      my $css_class = $itemcount%2?' class="LC_odd_row"':'';
     if ($itemcount%2) {  
         $css_class = 'LC_odd_row';  
     }  
     if ($customcss) {  
         $css_class .= " $customcss";  
     }  
     $css_class =~ s/^\s+//;  
     if ($css_class) {  
         $css_class = ' class="'.$css_class.'"';  
     }  
     if ($rowstyle) {  
         $css_class .= ' style="'.$rowstyle.'"';  
     }  
     my $output = '<tr'.$css_class.'>'.      my $output = '<tr'.$css_class.'>'.
                  '<td class="LC_left_item">'.$rowname.'</td><td class="LC_left_item" colspan="'.$colspan.'">'."\n".                   '<td class="LC_left_item">'.$rowname.'</td><td class="LC_left_item" colspan="2">'."\n".
                  '<table><tr><td>'."\n";                   '<table><tr><td>'."\n";
     foreach my $option ('original','recaptcha','notused') {      foreach my $option ('original','recaptcha','notused') {
         $output .= '<span class="LC_nobreak"><label><input type="radio" name="'.$context.'_captcha" value="'.          $output .= '<span class="LC_nobreak"><label><input type="radio" name="'.$context.'_captcha" value="'.
Line 8311  sub captcha_choice { Line 5451  sub captcha_choice {
 # specified for use with the key should be broad enough to accommodate all servers in the LON-CAPA domain.  # specified for use with the key should be broad enough to accommodate all servers in the LON-CAPA domain.
 #  #
     $output .= '</td></tr>'."\n".      $output .= '</td></tr>'."\n".
                '<tr><td class="LC_zero_height">'."\n".                 '<tr><td>'."\n".
                '<span class="LC_nobreak"><span id="'.$context.'_recaptchapubtxt">'.$pubtext.'</span>&nbsp;'."\n".                 '<span class="LC_nobreak"><span id="'.$context.'_recaptchapubtxt">'.$pubtext.'</span>&nbsp;'."\n".
                '<input type="'.$keyentry.'" id="'.$context.'_recaptchapub" name="'.$context.'_recaptchapub" value="'.                 '<input type="'.$keyentry.'" id="'.$context.'_recaptchapub" name="'.$context.'_recaptchapub" value="'.
                $currpub.'" size="40" /></span><br />'."\n".                 $currpub.'" size="40" /></span><br />'."\n".
Line 8327  sub captcha_choice { Line 5467  sub captcha_choice {
 }  }
   
 sub user_formats_row {  sub user_formats_row {
     my ($type,$settings,$rules,$ruleorder,$numinrow,$rowcount,$status) = @_;      my ($type,$settings,$rules,$ruleorder,$numinrow,$rowcount) = @_;
     my $output;      my $output;
     my %text = (      my %text = (
                    'username' => 'new usernames',                     'username' => 'new usernames',
                    'id'       => 'IDs',                     'id'       => 'IDs',
                      'email'    => 'self-created accounts (e-mail)',
                );                 );
     unless (($type eq 'email') || ($type eq 'unamemap')) {      my $css_class = $rowcount%2?' class="LC_odd_row"':'';
         my $css_class = $rowcount%2?' class="LC_odd_row"':'';      $output = '<tr '.$css_class.'>'.
         $output = '<tr '.$css_class.'>'.                '<td><span class="LC_nobreak">';
                   '<td><span class="LC_nobreak">'.      if ($type eq 'email') {
                   &mt("Format rules to check for $text{$type}: ").          $output .= &mt("Formats disallowed for $text{$type}: ");
                   '</td><td class="LC_left_item" colspan="2"><table>';      } else {
           $output .= &mt("Format rules to check for $text{$type}: ");
     }      }
       $output .= '</span></td>'.
                  '<td class="LC_left_item" colspan="2"><table>';
     my $rem;      my $rem;
     if (ref($ruleorder) eq 'ARRAY') {      if (ref($ruleorder) eq 'ARRAY') {
         for (my $i=0; $i<@{$ruleorder}; $i++) {          for (my $i=0; $i<@{$ruleorder}; $i++) {
Line 8357  sub user_formats_row { Line 5501  sub user_formats_row {
                         if (grep(/^\Q$ruleorder->[$i]\E$/,@{$settings->{$type.'_rule'}})) {                          if (grep(/^\Q$ruleorder->[$i]\E$/,@{$settings->{$type.'_rule'}})) {
                             $check = ' checked="checked" ';                              $check = ' checked="checked" ';
                         }                          }
                     } elsif ((ref($settings->{$type.'_rule'}) eq 'HASH') && ($status ne '')) {  
                         if (ref($settings->{$type.'_rule'}->{$status}) eq 'ARRAY') {  
                             if (grep(/^\Q$ruleorder->[$i]\E$/,@{$settings->{$type.'_rule'}->{$status}})) {  
                                 $check = ' checked="checked" ';  
                             }  
                         }  
                     }                      }
                 }                  }
                 my $name = $type.'_rule';  
                 if ($type eq 'email') {  
                     $name .= '_'.$status;  
                 }  
                 $output .= '<td class="LC_left_item">'.                  $output .= '<td class="LC_left_item">'.
                            '<span class="LC_nobreak"><label>'.                             '<span class="LC_nobreak"><label>'.
                            '<input type="checkbox" name="'.$name.'" '.                             '<input type="checkbox" name="'.$type.'_rule" '.
                            'value="'.$ruleorder->[$i].'"'.$check.'/>'.                             'value="'.$ruleorder->[$i].'"'.$check.'/>'.
                            $rules->{$ruleorder->[$i]}{'name'}.'</label></span></td>';                             $rules->{$ruleorder->[$i]}{'name'}.'</label></span></td>';
             }              }
         }          }
         $rem = @{$ruleorder}%($numinrow);          $rem = @{$ruleorder}%($numinrow);
     }      }
     my $colsleft;      my $colsleft = $numinrow - $rem;
     if ($rem) {  
         $colsleft = $numinrow - $rem;  
     }  
     if ($colsleft > 1 ) {      if ($colsleft > 1 ) {
         $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.          $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                    '&nbsp;</td>';                     '&nbsp;</td>';
     } elsif ($colsleft == 1) {      } elsif ($colsleft == 1) {
         $output .= '<td class="LC_left_item">&nbsp;</td>';          $output .= '<td class="LC_left_item">&nbsp;</td>';
     }      }
     $output .= '</tr>';      $output .= '</tr></table></td></tr>';
     unless (($type eq 'email') || ($type eq 'unamemap')) {  
         $output .= '</table></td></tr>';  
     }  
     return $output;      return $output;
 }  }
   
Line 8468  sub print_usermodification { Line 5596  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,$titles);      my ($datatable,$css_class);
     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 8484  sub print_defaults { Line 5609  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 8520  sub print_defaults { Line 5646  sub print_defaults {
             } elsif ($item eq 'lang_def') {              } elsif ($item eq 'lang_def') {
                 my $includeempty = 1;                  my $includeempty = 1;
                 $datatable .= &Apache::loncommon::select_language($item,$defaults{$item},$includeempty);                  $datatable .= &Apache::loncommon::select_language($item,$defaults{$item},$includeempty);
             } elsif ($item eq 'portal_def') {  
                 $datatable .= '<input type="text" name="'.$item.'" value="'.  
                               $defaults{$item}.'" size="25" onkeyup="portalExtras(this);" />';  
                 my $portalsty = 'none';  
                 if ($defaults{$item}) {  
                     $portalsty = 'block';  
                 }  
                 foreach my $field ('email','web') {  
                     my $checkedoff = ' checked="checked"';  
                     my $checkedon;  
                     if ($defaults{$item.'_'.$field}) {  
                         $checkedon = $checkedoff;  
                         $checkedoff = '';  
                     }  
                     $datatable .= '<div id="'.$item.'_'.$field.'_div" style="display:'.$portalsty.'">'.  
                               '<span class="LC_nobreak">'.$titles->{$field}.'&nbsp;'.  
                               '<label><input type="radio" name="'.$item.'_'.$field.'" value="1"'.$checkedon.'/>'.&mt('Yes').'</label>'.  
                               ('&nbsp;'x2).  
                               '<label><input type="radio" name="'.$item.'_'.$field.'" value="0"'.$checkedoff.'/>'.&mt('No').'</label>'.  
                               '</div>';  
                 }  
             } else {              } else {
                 $datatable .= '<input type="text" name="'.$item.'" value="'.$defaults{$item}.'" />';                  my $size;
                   if ($item eq 'portal_def') {
                       $size = ' size="25"';
                   }
                   $datatable .= '<input type="text" name="'.$item.'" value="'.
                                 $defaults{$item}.'"'.$size.' />';
             }              }
             $datatable .= '</td></tr>';              $datatable .= '</td></tr>';
             $rownum ++;              $rownum ++;
         }          }
     } elsif ($position eq 'middle') {      } else {
         my %defaults;          my (%defaults);
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {              if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH') &&
                   (ref($settings->{'inststatusguest'}) eq 'ARRAY')) {
                 my $maxnum = @{$settings->{'inststatusorder'}};                  my $maxnum = @{$settings->{'inststatusorder'}};
                 for (my $i=0; $i<$maxnum; $i++) {                  for (my $i=0; $i<$maxnum; $i++) {
                     $css_class = $rownum%2?' class="LC_odd_row"':'';                      $css_class = $rownum%2?' class="LC_odd_row"':'';
                     my $item = $settings->{'inststatusorder'}->[$i];                      my $item = $settings->{'inststatusorder'}->[$i];
                     my $title = $settings->{'inststatustypes'}->{$item};                      my $title = $settings->{'inststatustypes'}->{$item};
                       my $guestok;
                       if (grep(/^\Q$item\E$/,@{$settings->{'inststatusguest'}})) {
                           $guestok = 1;
                       }
                     my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'$item'".');"';                      my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'$item'".');"';
                     $datatable .= '<tr'.$css_class.'>'.                      $datatable .= '<tr'.$css_class.'>'.
                                   '<td><span class="LC_nobreak">'.                                    '<td><span class="LC_nobreak">'.
Line 8568  sub print_defaults { Line 5683  sub print_defaults {
                         }                          }
                         $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';                          $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                     }                      }
                       my ($checkedon,$checkedoff);
                       $checkedoff = ' checked="checked"';
                       if ($guestok) {
                           $checkedon = $checkedoff;
                           $checkedoff = ''; 
                       }
                     $datatable .= '</select>&nbsp;'.&mt('Internal ID:').'&nbsp;<b>'.$item.'</b>&nbsp;'.                      $datatable .= '</select>&nbsp;'.&mt('Internal ID:').'&nbsp;<b>'.$item.'</b>&nbsp;'.
                                   '<input type="checkbox" name="inststatus_delete" value="'.$item.'" />'.                                    '<input type="checkbox" name="inststatus_delete" value="'.$item.'" />'.
                                   &mt('delete').'</span></td>'.                                    &mt('delete').'</span></td>'.
                                   '<td class="LC_left_item"><span class="LC_nobreak">'.&mt('Name displayed').':'.                                    '<td class="LC_left_item"><span class="LC_nobreak">'.&mt('Name displayed:').
                                   '<input type="text" size="20" name="inststatus_title_'.$item.'" value="'.$title.'" />'.                                    '<input type="text" size="20" name="inststatus_title_'.$item.'" value="'.$title.'" />'.
                                   '</span></td></tr>';                                    '</span></td>'.
                                     '<td class="LC_right_item"><span class="LC_nobreak">'.
                                     '<label><input type="radio" value="1" name="inststatus_guest_'.$item.'"'.$checkedon.' />'.
                                     &mt('Yes').'</label>'.('&nbsp;'x2).
                                     '<label><input type="radio" value="0" name="inststatus_guest_'.$item.'"'.$checkedoff.' />'.
                                     &mt('No').'</label></span></td></tr>';
                 }                  }
                 $css_class = $rownum%2?' class="LC_odd_row"':'';                  $css_class = $rownum%2?' class="LC_odd_row"':'';
                 my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'addinststatus_pos'".');"';                  my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'addinststatus_pos'".');"';
Line 8591  sub print_defaults { Line 5717  sub print_defaults {
                               '<input type="text" size="10" name="addinststatus" value="" />'.                                '<input type="text" size="10" name="addinststatus" value="" />'.
                               '&nbsp;'.&mt('(new)').                                '&nbsp;'.&mt('(new)').
                               '</span></td><td class="LC_left_item"><span class="LC_nobreak">'.                                '</span></td><td class="LC_left_item"><span class="LC_nobreak">'.
                               &mt('Name displayed').':'.                                &mt('Name displayed:').
                               '<input type="text" size="20" name="addinststatus_title" value="" /></span></td>'.                                '<input type="text" size="20" name="addinststatus_title" value="" /></span></td>'.
                                 '<td class="LC_right_item"><span class="LC_nobreak">'.
                                 '<label><input type="radio" value="1" name="addinststatus_guest" />'.
                                 &mt('Yes').'</label>'.('&nbsp;'x2).
                                 '<label><input type="radio" value="0" name="addinststatus_guest" />'.
                                 &mt('No').'</label></span></td></tr>';
                               '</tr>'."\n";                                '</tr>'."\n";
                 $rownum ++;                  $rownum ++;
             }              }
         }          }
     } else {  
         my ($unamemaprules,$ruleorder) =  
             &Apache::lonnet::inst_userrules($dom,'unamemap');  
         $css_class = $rownum%2?' class="LC_odd_row"':'';  
         if ((ref($unamemaprules) eq 'HASH') && (ref($ruleorder) eq 'ARRAY')) {  
             my $numinrow = 2;  
             $datatable .= '<tr'.$css_class.'><td>'.&mt('Available conversions').'</td><td><table>'.  
                           &user_formats_row('unamemap',$settings,$unamemaprules,  
                                             $ruleorder,$numinrow).  
                           '</table></td></tr>';  
         }  
         if ($datatable eq '') {  
             $datatable .= '<tr'.$css_class.'><td colspan="2">'.  
                           &mt('No rules set for domain in customized localenroll.pm').  
                           '</td></tr>';  
         }  
     }      }
     $$rowtotal += $rownum;      $$rowtotal += $rownum;
     return $datatable;      return $datatable;
Line 8638  sub defaults_titles { Line 5753  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',
                    'email'          => 'Email links use portal URL',  
                    'web'            => 'Public web links use portal 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 8657  sub defaults_titles { Line 5767  sub defaults_titles {
     return (\%titles);      return (\%titles);
 }  }
   
 sub print_scantron {  
     my ($r,$position,$dom,$confname,$settings,$rowtotal) = @_;  
     if ($position eq 'top') {  
         return &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);  
     } else {  
         return &print_scantronconfig($dom,$settings,\$rowtotal);  
     }  
 }  
   
 sub scantron_javascript {  
     return <<"ENDSCRIPT";  
   
 <script type="text/javascript">  
 // <![CDATA[  
   
 function toggleScantron(form) {  
     var csvfieldset = new Array();  
     if (document.getElementById('scantroncsv_cols')) {  
         csvfieldset.push(document.getElementById('scantroncsv_cols'));  
     }  
     if (document.getElementById('scantroncsv_options')) {  
         csvfieldset.push(document.getElementById('scantroncsv_options'));  
     }  
     if (csvfieldset.length) {  
         if (document.getElementById('scantronconfcsv')) {  
             var scantroncsv = document.getElementById('scantronconfcsv');  
             if (scantroncsv.checked) {  
                 for (var i=0; i<csvfieldset.length; i++) {  
                     csvfieldset[i].style.display = 'block';  
                 }  
             } else {  
                 for (var i=0; i<csvfieldset.length; i++) {  
                     csvfieldset[i].style.display = 'none';  
                 }  
                 var csvselects = document.getElementsByClassName('scantronconfig_csv');  
                 if (csvselects.length) {  
                     for (var j=0; j<csvselects.length; j++) {  
                         csvselects[j].selectedIndex = 0;  
                     }  
                 }  
             }  
         }  
     }  
     return;  
 }  
 // ]]>  
 </script>  
   
 ENDSCRIPT  
   
 }  
   
 sub print_scantronformat {  sub print_scantronformat {
     my ($r,$dom,$confname,$settings,$rowtotal) = @_;      my ($r,$dom,$confname,$settings,$rowtotal) = @_;
     my $itemcount = 1;      my $itemcount = 1;
Line 8735  sub print_scantronformat { Line 5793  sub print_scantronformat {
             if ($configuserok eq 'ok') {              if ($configuserok eq 'ok') {
                 if ($author_ok eq 'ok') {                  if ($author_ok eq 'ok') {
                     my %legacyfile = (                      my %legacyfile = (
  default => $Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab',   default => $Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab', 
  custom  => $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab',   custom  => $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab', 
                     );                      );
                     my %md5chk;                      my %md5chk;
                     foreach my $type (keys(%legacyfile)) {                      foreach my $type (keys(%legacyfile)) {
Line 8745  sub print_scantronformat { Line 5803  sub print_scantronformat {
                     }                      }
                     if ($md5chk{'default'} ne $md5chk{'custom'}) {                      if ($md5chk{'default'} ne $md5chk{'custom'}) {
                         foreach my $type (keys(%legacyfile)) {                          foreach my $type (keys(%legacyfile)) {
                             ($scantronurls{$type},my $error) =                              ($scantronurls{$type},my $error) = 
                                 &legacy_scantronformat($r,$dom,$confname,                                  &legacy_scantronformat($r,$dom,$confname,
                                                  $type,$legacyfile{$type},                                                   $type,$legacyfile{$type},
                                                  $scantronurls{$type},                                                   $scantronurls{$type},
Line 8756  sub print_scantronformat { Line 5814  sub print_scantronformat {
                         }                          }
                         if (keys(%error) == 0) {                          if (keys(%error) == 0) {
                             $is_custom = 1;                              $is_custom = 1;
                             $confhash{'scantron'}{'scantronformat'} =                              $confhash{'scantron'}{'scantronformat'} = 
                                 $scantronurls{'custom'};                                  $scantronurls{'custom'};
                             my $putresult =                              my $putresult = 
                                 &Apache::lonnet::put_dom('configuration',                                  &Apache::lonnet::put_dom('configuration',
                                                          \%confhash,$dom);                                                           \%confhash,$dom);
                             if ($putresult ne 'ok') {                              if ($putresult ne 'ok') {
                                 $error{'custom'} =                                  $error{'custom'} = 
                                     '<span class="LC_error">'.                                      '<span class="LC_error">'.
                                     &mt('An error occurred updating the domain configuration: [_1]',$putresult).'</span>';                                      &mt('An error occurred updating the domain configuration: [_1]',$putresult).'</span>';
                             }                              }
Line 8882  sub legacy_scantronformat { Line 5940  sub legacy_scantronformat {
     return ($url,$error);      return ($url,$error);
 }  }
   
 sub print_scantronconfig {  
     my ($dom,$settings,$rowtotal) = @_;  
     my $itemcount = 2;  
     my $is_checked = ' checked="checked"';  
     my %optionson = (  
                      hdr => ' checked="checked"',  
                      pad => ' checked="checked"',  
                      rem => ' checked="checked"',  
                     );  
     my %optionsoff = (  
                       hdr => '',  
                       pad => '',  
                       rem => '',  
                      );  
     my $currcsvsty = 'none';  
     my ($datatable,%csvfields,%checked,%onclick,%csvoptions);  
     my @fields = &scantroncsv_fields();  
     my %titles = &scantronconfig_titles();  
     if (ref($settings) eq 'HASH') {  
         if (ref($settings->{config}) eq 'HASH') {  
             if ($settings->{config}->{dat}) {  
                 $checked{'dat'} = $is_checked;  
             }  
             if (ref($settings->{config}->{csv}) eq 'HASH') {  
                 if (ref($settings->{config}->{csv}->{fields}) eq 'HASH') {  
                     %csvfields = %{$settings->{config}->{csv}->{fields}};  
                     if (keys(%csvfields) > 0) {  
                         $checked{'csv'} = $is_checked;  
                         $currcsvsty = 'block';  
                     }  
                 }  
                 if (ref($settings->{config}->{csv}->{options}) eq 'HASH') {  
                     %csvoptions = %{$settings->{config}->{csv}->{options}};  
                     foreach my $option (keys(%optionson)) {  
                         unless ($csvoptions{$option}) {  
                             $optionsoff{$option} = $optionson{$option};  
                             $optionson{$option} = '';  
                         }  
                     }  
                 }  
             }  
         } else {  
             $checked{'dat'} = $is_checked;  
         }  
     } else {  
         $checked{'dat'} = $is_checked;  
     }  
     $onclick{'csv'} = ' onclick="toggleScantron(this.form);"';  
     my $css_class = $itemcount%2? ' class="LC_odd_row"':'';  
     $datatable = '<tr '.$css_class.'><td>'.&mt('Supported formats').'</td>'.  
                  '<td class="LC_left_item" valign="top"><span class="LC_nobreak">';  
     foreach my $item ('dat','csv') {  
         my $id;  
         if ($item eq 'csv') {  
             $id = 'id="scantronconfcsv" ';  
         }  
         $datatable .= '<label><input type="checkbox" name="scantronconfig" '.$id.'value="'.$item.'"'.$checked{$item}.$onclick{$item}.' />'.  
                       $titles{$item}.'</label>'.('&nbsp;'x3);  
         if ($item eq 'csv') {  
             $datatable .= '<fieldset style="display:'.$currcsvsty.'" id="scantroncsv_cols">'.  
                           '<legend>'.&mt('CSV Column Mapping').'</legend>'.  
                           '<table><tr><th>'.&mt('Field').'</th><th>'.&mt('Location').'</th></tr>'."\n";  
             foreach my $col (@fields) {  
                 my $selnone;  
                 if ($csvfields{$col} eq '') {  
                     $selnone = ' selected="selected"';  
                 }  
                 $datatable .= '<tr><td>'.$titles{$col}.'</td>'.  
                               '<td><select name="scantronconfig_csv_'.$col.'" class="scantronconfig_csv">'.  
                               '<option value=""'.$selnone.'></option>';  
                 for (my $i=0; $i<20; $i++) {  
                     my $shown = $i+1;  
                     my $sel;  
                     unless ($selnone) {  
                         if (exists($csvfields{$col})) {  
                             if ($csvfields{$col} == $i) {  
                                 $sel = ' selected="selected"';  
                             }  
                         }  
                     }  
                     $datatable .= '<option value="'.$i.'"'.$sel.'>'.$shown.'</option>';  
                 }  
                 $datatable .= '</select></td></tr>';  
            }  
            $datatable .= '</table></fieldset>'.  
                          '<fieldset style="display:'.$currcsvsty.'" id="scantroncsv_options">'.  
                          '<legend>'.&mt('CSV Options').'</legend>';  
            foreach my $option ('hdr','pad','rem') {  
                $datatable .= '<span class="LC_nobreak">'.$titles{$option}.':'.  
                          '<label><input type="radio" name="scantroncsv_'.$option.'" value="1"'.$optionson{$option}.' />'.  
                          &mt('Yes').'</label>'.('&nbsp;'x2)."\n".  
                          '<label><input type="radio" name="scantroncsv_'.$option.'" value="0"'.$optionsoff{$option}.' />'.&mt('No').'</label></span><br />';  
            }  
            $datatable .= '</fieldset>';  
            $itemcount ++;  
         }  
     }  
     $datatable .= '</td></tr>';  
     $$rowtotal ++;  
     return $datatable;  
 }  
   
 sub scantronconfig_titles {  
     return &Apache::lonlocal::texthash(  
                                           dat => 'Standard format (.dat)',  
                                           csv => 'Comma separated values (.csv)',  
                                           hdr => 'Remove first line in file (contains column titles)',  
                                           pad => 'Prepend 0s to PaperID',  
                                           rem => 'Remove leading spaces (except Question Response columns)',  
                                           CODE => 'CODE',  
                                           ID   => 'Student ID',  
                                           PaperID => 'Paper ID',  
                                           FirstName => 'First Name',  
                                           LastName => 'Last Name',  
                                           FirstQuestion => 'First Question Response',  
                                           Section => 'Section',  
     );  
 }  
   
 sub scantroncsv_fields {  
     return ('PaperID','LastName','FirstName','ID','Section','CODE','FirstQuestion');  
 }  
   
 sub print_coursecategories {  sub print_coursecategories {
     my ($position,$dom,$hdritem,$settings,$rowtotal) = @_;      my ($position,$dom,$hdritem,$settings,$rowtotal) = @_;
     my $datatable;      my $datatable;
Line 9047  sub print_coursecategories { Line 5982  sub print_coursecategories {
                              '<input type="radio" name="coursecat_'.$item.'" value="'.$type.'"'.$ischecked.                               '<input type="radio" name="coursecat_'.$item.'" value="'.$type.'"'.$ischecked.
                              ' />'.$lt{$type}.'</label>&nbsp;';                               ' />'.$lt{$type}.'</label>&nbsp;';
            }             }
            $datatable .= '</span></td></tr>';             $datatable .= '</td></tr>';
            $itemcount ++;             $itemcount ++;
         }          }
         $$rowtotal += $itemcount;          $$rowtotal += $itemcount;
Line 9060  sub print_coursecategories { Line 5995  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 9078  sub print_coursecategories { Line 6017  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 9118  sub print_coursecategories { Line 6068  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 9144  sub print_coursecategories { Line 6108  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 9170  sub print_coursecategories { Line 6137  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 9193  sub print_coursecategories { Line 6160  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 9225  sub print_coursecategories { Line 6192  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 9258  sub print_coursecategories { Line 6225  sub print_coursecategories {
                 $datatable .= &initialize_categories($itemcount);                  $datatable .= &initialize_categories($itemcount);
             }              }
         } else {          } else {
             $datatable .= '<tr><td class="LC_right_item">'.$hdritem->{'header'}->[1]->{'col2'}.'</td></tr>'              $datatable .= '<td class="LC_right_item">'.$hdritem->{'header'}->[1]->{'col2'}.'</td>'
                           .&initialize_categories($itemcount);                            .&initialize_categories($itemcount);
         }          }
         $$rowtotal += $itemcount;          $$rowtotal += $itemcount;
Line 9306  sub print_serverstatuses { Line 6273  sub print_serverstatuses {
                       '<span class="LC_nobreak">'.                        '<span class="LC_nobreak">'.
                       '<input type="text" name="'.$type.'_machines" '.                        '<input type="text" name="'.$type.'_machines" '.
                       'value="'.$machineaccess{$type}.'" size="10" />'.                        'value="'.$machineaccess{$type}.'" size="10" />'.
                       '</span></td></tr>'."\n";                        '</td></tr>'."\n";
     }      }
     $$rowtotal += $rownum;      $$rowtotal += $rownum;
     return $datatable;      return $datatable;
Line 9314  sub print_serverstatuses { Line 6281  sub print_serverstatuses {
   
 sub serverstatus_pages {  sub serverstatus_pages {
     return ('userstatus','lonstatus','loncron','server-status','codeversions',      return ('userstatus','lonstatus','loncron','server-status','codeversions',
             'checksums','clusterstatus','metadata_keywords','metadata_harvest',              'checksums','clusterstatus','certstatus','metadata_keywords',
             'takeoffline','takeonline','showenv','toggledebug','ping','domconf',              'metadata_harvest','takeoffline','takeonline','showenv','toggledebug',
             'uniquecodes','diskusage','coursecatalog');              'ping','domconf','uniquecodes','diskusage','coursecatalog');
 }  }
   
 sub defaults_javascript {  sub defaults_javascript {
     my ($settings) = @_;      my ($settings) = @_;
     return unless (ref($settings) eq 'HASH');      return unless (ref($settings) eq 'HASH'); 
     my $portal_js = <<"ENDPORTAL";  
   
 function portalExtras(caller) {  
     var x = caller.value;  
     var y = new Array('email','web');  
     for (var i=0; i<y.length; i++) {  
         if (document.getElementById('portal_def_'+y[i]+'_div')) {  
             var z = document.getElementById('portal_def_'+y[i]+'_div');  
             if (x.length > 0) {  
                 z.style.display = 'block';  
             } else {  
                 z.style.display = 'none';  
             }  
         }  
     }  
 }  
 ENDPORTAL  
     if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {      if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {
         my $maxnum = scalar(@{$settings->{'inststatusorder'}});          my $maxnum = scalar(@{$settings->{'inststatusorder'}});
         if ($maxnum eq '') {          if ($maxnum eq '') {
Line 9392  $jstext Line 6342  $jstext
     return;      return;
 }  }
   
 $portal_js  
   
 // ]]>  
 </script>  
   
 ENDSCRIPT  
     } else {  
 return <<"ENDSCRIPT";  
 <script type="text/javascript">  
 // <![CDATA[  
 $portal_js  
 // ]]>  // ]]>
 </script>  </script>
   
Line 9410  ENDSCRIPT Line 6349  ENDSCRIPT
     }      }
 }  }
   
 sub passwords_javascript {  
     my ($prefix) = @_;  
     my %intalert;  
     if ($prefix eq 'passwords') {  
         %intalert = &Apache::lonlocal::texthash (  
             authcheck => 'Warning: disallowing login for an authenticated user if the stored cost is less than the default will require a password reset by/for the user.',  
             authcost => 'Warning: bcrypt encryption cost for internal authentication must be an integer.',  
             passmin => 'Warning: minimum password length must be a positive integer greater than 6.',  
             passmax => 'Warning: maximum password length must be a positive integer (or blank).',  
             passnum => 'Warning: number of previous passwords to save must be a positive integer (or blank).',  
         );  
     } elsif ($prefix eq 'secrets') {  
         %intalert = &Apache::lonlocal::texthash (  
             passmin => 'Warning: minimum secret length must be a positive integer greater than 6.',  
             passmax => 'Warning: maximum secret length must be a positive integer (or blank).',  
         );  
     }  
     &js_escape(\%intalert);  
     my $defmin = $Apache::lonnet::passwdmin;  
     my $intauthjs;  
     if ($prefix eq 'passwords') { $intauthjs = <<"ENDSCRIPT";  
   
 function warnIntAuth(field) {  
     if (field.name == 'intauth_check') {  
         if (field.value == '2') {  
             alert('$intalert{authcheck}');  
         }  
     }  
     if (field.name == 'intauth_cost') {  
         field.value.replace(/\s/g,'');  
         if (field.value != '') {  
             var regexdigit=/^\\d+\$/;  
             if (!regexdigit.test(field.value)) {  
                 alert('$intalert{authcost}');  
             }  
         }  
     }  
     return;  
 }  
   
 ENDSCRIPT  
   
      }  
   
      $intauthjs .= <<"ENDSCRIPT";  
   
 function warnInt$prefix(field) {  
     field.value.replace(/^\s+/,'');  
     field.value.replace(/\s+\$/,'');  
     var regexdigit=/^\\d+\$/;  
     if (field.name == '${prefix}_min') {  
         if (field.value == '') {  
             alert('$intalert{passmin}');  
             field.value = '$defmin';  
         } else {  
             if (!regexdigit.test(field.value)) {  
                 alert('$intalert{passmin}');  
                 field.value = '$defmin';  
             }  
             var minval = parseInt(field.value,10);  
             if (minval < $defmin) {  
                 alert('$intalert{passmin}');  
                 field.value = '$defmin';  
             }  
         }  
     } else {  
         if (field.value == '0') {  
             field.value = '';  
         }  
         if (field.value != '') {  
             if (!regexdigit.test(field.value)) {  
                 if (field.name == '${prefix}_max') {  
                     alert('$intalert{passmax}');  
                 } else {  
                     if (field.name == '${prefix}_numsaved') {  
                         alert('$intalert{passnum}');  
                     }  
                 }  
                 field.value = '';  
             }  
         }  
     }  
     return;  
 }  
   
 ENDSCRIPT  
     return &Apache::lonhtmlcommon::scripttag($intauthjs);  
 }  
   
 sub coursecategories_javascript {  sub coursecategories_javascript {
     my ($settings) = @_;      my ($settings) = @_;
     my ($output,$jstext,$cathash);      my ($output,$jstext,$cathash);
Line 9523  sub coursecategories_javascript { Line 6373  sub coursecategories_javascript {
     }      }
     my $instcode_reserved = &mt('The name: [_1] is a reserved category.','"instcode"');      my $instcode_reserved = &mt('The name: [_1] is a reserved category.','"instcode"');
     my $communities_reserved = &mt('The name: [_1] is a reserved category.','"communities"');      my $communities_reserved = &mt('The name: [_1] is a reserved category.','"communities"');
       my $placement_reserved = &mt('The name: [_1] is a reserved category.','"placement"');
     my $choose_again = "\n".&mt('Please use a different name for the new top level category.');       my $choose_again = "\n".&mt('Please use a different name for the new top level category.'); 
     &js_escape(\$instcode_reserved);      &js_escape(\$instcode_reserved);
     &js_escape(\$communities_reserved);      &js_escape(\$communities_reserved);
       &js_escape(\$placement_reserved);
     &js_escape(\$choose_again);      &js_escape(\$choose_again);
     $output = <<"ENDSCRIPT";      $output = <<"ENDSCRIPT";
 <script type="text/javascript">  <script type="text/javascript">
Line 9595  function categoryCheck(form) { Line 6447  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 9608  ENDSCRIPT Line 6464  ENDSCRIPT
 sub initialize_categories {  sub initialize_categories {
     my ($itemcount) = @_;      my ($itemcount) = @_;
     my ($datatable,$css_class,$chgstr);      my ($datatable,$css_class,$chgstr);
     my %default_names = &Apache::lonlocal::texthash (      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 9641  sub initialize_categories { Line 6498  sub initialize_categories {
                   .'<option value="0">1</option>'                    .'<option value="0">1</option>'
                   .'<option value="1">2</option>'                    .'<option value="1">2</option>'
                   .'<option value="2" selected="selected">3</option></select>&nbsp;'                    .'<option value="2" selected="selected">3</option></select>&nbsp;'
                   .&mt('Add category').'</span></td><td><span class="LC_nobreak">'.&mt('Name:')                    .&mt('Add category').'</td><td>'.&mt('Name:')
                   .'&nbsp;<input type="text" size="20" name="addcategory_name" value="" /></span>'                    .'&nbsp;<input type="text" size="20" name="addcategory_name" value="" /></td></tr>';
                   .'</td></tr>';  
     return $datatable;      return $datatable;
 }  }
   
Line 9698  sub build_category_rows { Line 6554  sub build_category_rows {
                             pop(@{$path});                              pop(@{$path});
                         }                          }
                     } else {                      } else {
                         $text .= &mt('Add subcategory:').'&nbsp;</span><input type="text" size="20" name="addcategory_name_';                          $text .= &mt('Add subcategory:').'&nbsp;</span><input type="textbox" size="20" name="addcategory_name_';
                         if ($j == $numchildren) {                          if ($j == $numchildren) {
                             $text .= $name;                              $text .= $name;
                         } else {                          } else {
Line 9721  sub build_category_rows { Line 6577  sub build_category_rows {
                 my $colspan;                  my $colspan;
                 if ($parent ne 'instcode') {                  if ($parent ne 'instcode') {
                     $colspan = $maxdepth - $depth - 1;                      $colspan = $maxdepth - $depth - 1;
                     $text .= '<td colspan="'.$colspan.'">'.&mt('Add subcategory:').'<input type="text" size="20" name="subcat_'.$name.'" value="" /></td>';                      $text .= '<td colspan="'.$colspan.'">'.&mt('Add subcategory:').'<input type="textbox" size="20" name="subcat_'.$name.'" value="" /></td>';
                 }                  }
             }              }
         }          }
Line 9730  sub build_category_rows { Line 6586  sub build_category_rows {
 }  }
   
 sub modifiable_userdata_row {  sub modifiable_userdata_row {
     my ($context,$item,$settings,$numinrow,$rowcount,$usertypes,$fieldsref,$titlesref,      my ($context,$item,$settings,$numinrow,$rowcount,$usertypes,$fieldsref,$titlesref) = @_;
         $rowid,$customcss,$rowstyle) = @_;  
     my ($role,$rolename,$statustype);      my ($role,$rolename,$statustype);
     $role = $item;      $role = $item;
     if ($context eq 'cancreate') {      if ($context eq 'cancreate') {
         if ($item =~ /^(emailusername)_(.+)$/) {          if ($item =~ /^emailusername_(.+)$/) {
             $role = $1;              $statustype = $1;
             $statustype = $2;              $role = 'emailusername';
             if (ref($usertypes) eq 'HASH') {              if (ref($usertypes) eq 'HASH') {
                 if ($usertypes->{$statustype}) {                  if ($usertypes->{$statustype}) {
                     $rolename = &mt('Data provided by [_1]',$usertypes->{$statustype});                      $rolename = &mt('Data provided by [_1]',$usertypes->{$statustype});
Line 9772  sub modifiable_userdata_row { Line 6627  sub modifiable_userdata_row {
         %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();          %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
     }      }
     my $output;      my $output;
     my $css_class;      my $css_class = $rowcount%2?' class="LC_odd_row"':'';
     if ($rowcount%2) {      $output = '<tr '.$css_class.'>'.
         $css_class = 'LC_odd_row';  
     }  
     if ($customcss) {  
         $css_class .= " $customcss";  
     }  
     $css_class =~ s/^\s+//;  
     if ($css_class) {  
         $css_class = ' class="'.$css_class.'"';  
     }  
     if ($rowstyle) {  
         $css_class .= ' style="'.$rowstyle.'"';  
     }  
     if ($rowid) {  
         $rowid = ' id="'.$rowid.'"';  
     }  
   
     $output = '<tr '.$css_class.$rowid.'>'.  
               '<td><span class="LC_nobreak">'.$rolename.'</span></td>'.                '<td><span class="LC_nobreak">'.$rolename.'</span></td>'.
               '<td class="LC_left_item" colspan="2"><table>';                '<td class="LC_left_item" colspan="2"><table>';
     my $rem;      my $rem;
Line 9824  sub modifiable_userdata_row { Line 6662  sub modifiable_userdata_row {
             }              }
         }          }
     }      }
        
     my $total = scalar(@fields);      for (my $i=0; $i<@fields; $i++) {
     for (my $i=0; $i<$total; $i++) {          my $rem = $i%($numinrow);
         $rem = $i%($numinrow);  
         if ($rem == 0) {          if ($rem == 0) {
             if ($i > 0) {              if ($i > 0) {
                 $output .= '</tr>';                  $output .= '</tr>';
Line 9837  sub modifiable_userdata_row { Line 6674  sub modifiable_userdata_row {
         my $check = ' ';          my $check = ' ';
         unless ($role eq 'emailusername') {          unless ($role eq 'emailusername') {
             if (exists($checks{$fields[$i]})) {              if (exists($checks{$fields[$i]})) {
                 $check = $checks{$fields[$i]};                  $check = $checks{$fields[$i]}
             } else {              } else {
                 if ($role eq 'st') {                  if ($role eq 'st') {
                     if (ref($settings) ne 'HASH') {                      if (ref($settings) ne 'HASH') {
Line 9869  sub modifiable_userdata_row { Line 6706  sub modifiable_userdata_row {
                        '</label>';                         '</label>';
         }          }
         $output .= '</span></td>';          $output .= '</span></td>';
           $rem = @fields%($numinrow);
     }      }
     $rem = $total%$numinrow;      my $colsleft = $numinrow - $rem;
     my $colsleft;      if ($colsleft > 1 ) {
     if ($rem) {  
         $colsleft = $numinrow - $rem;  
     }  
     if ($colsleft > 1) {  
         $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.          $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                    '&nbsp;</td>';                     '&nbsp;</td>';
     } elsif ($colsleft == 1) {      } elsif ($colsleft == 1) {
Line 9886  sub modifiable_userdata_row { Line 6720  sub modifiable_userdata_row {
 }  }
   
 sub insttypes_row {  sub insttypes_row {
     my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context,$rowtotal,$onclick,      my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context,$rownum) = @_;
         $customcss,$rowstyle) = @_;  
     my %lt = &Apache::lonlocal::texthash (      my %lt = &Apache::lonlocal::texthash (
                       cansearch => 'Users allowed to search',                        cansearch => 'Users allowed to search',
                       statustocreate => 'Institutional affiliation(s) able to create own account (login/SSO)',                        statustocreate => 'Institutional affiliation(s) able to create own account (login/SSO)',
                       lockablenames => 'User preference to lock name',                        lockablenames => 'User preference to lock name',
                       selfassign    => 'Self-reportable affiliations',  
                       overrides     => "Override domain's helpdesk settings based on requester's affiliation",  
              );               );
     my $showdom;      my $showdom;
     if ($context eq 'cansearch') {      if ($context eq 'cansearch') {
Line 9903  sub insttypes_row { Line 6734  sub insttypes_row {
     if ($context eq 'statustocreate') {      if ($context eq 'statustocreate') {
         $class = 'LC_right_item';          $class = 'LC_right_item';
     }      }
     my $css_class;      my $css_class = ' class="LC_odd_row"';
     if ($$rowtotal%2) {      if ($rownum ne '') { 
         $css_class = 'LC_odd_row';          $css_class = ($rownum%2? ' class="LC_odd_row"':'');
     }  
     if ($customcss) {  
         $css_class .= ' '.$customcss;  
     }  
     $css_class =~ s/^\s+//;  
     if ($css_class) {  
         $css_class = ' class="'.$css_class.'"';  
     }  
     if ($rowstyle) {  
         $css_class .= ' style="'.$rowstyle.'"';  
     }  
     if ($onclick) {  
         $onclick = 'onclick="'.$onclick.'" ';  
     }      }
     my $output = '<tr'.$css_class.'>'.      my $output = '<tr'.$css_class.'>'.
                  '<td>'.$lt{$context}.$showdom.                   '<td>'.$lt{$context}.$showdom.
Line 9940  sub insttypes_row { Line 6758  sub insttypes_row {
                         if (grep(/^\Q$types->[$i]\E$/,@{$settings->{$context}})) {                          if (grep(/^\Q$types->[$i]\E$/,@{$settings->{$context}})) {
                             $check = ' checked="checked" ';                              $check = ' checked="checked" ';
                         }                          }
                     } elsif (ref($settings->{$context}) eq 'HASH') {  
                         if (ref($settings->{$context}->{$types->[$i]}) eq 'HASH') {  
                             $check = ' checked="checked" ';  
                         }  
                     } elsif ($context eq 'statustocreate') {                      } elsif ($context eq 'statustocreate') {
                         $check = ' checked="checked" ';                          $check = ' checked="checked" ';
                     }                      }
Line 9951  sub insttypes_row { Line 6765  sub insttypes_row {
                 $output .= '<td class="LC_left_item">'.                  $output .= '<td class="LC_left_item">'.
                            '<span class="LC_nobreak"><label>'.                             '<span class="LC_nobreak"><label>'.
                            '<input type="checkbox" name="'.$context.'" '.                             '<input type="checkbox" name="'.$context.'" '.
                            'value="'.$types->[$i].'"'.$check.$onclick.'/>'.                             'value="'.$types->[$i].'"'.$check.'/>'.
                            $usertypes->{$types->[$i]}.'</label></span></td>';                             $usertypes->{$types->[$i]}.'</label></span></td>';
             }              }
         }          }
         $rem = @{$types}%($numinrow);          $rem = @{$types}%($numinrow);
     }      }
     my $colsleft = $numinrow - $rem;      my $colsleft = $numinrow - $rem;
     if ($context eq 'overrides') {      if (($rem == 0) && (@{$types} > 0)) {
         if ($colsleft > 1) {          $output .= '<tr>';
             $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">';      }
         } else {      if ($colsleft > 1) {
             $output .= '<td class="LC_left_item">';          $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
         }  
         $output .= '&nbsp;';  
     } else {      } else {
         if ($rem == 0) {          $output .= '<td class="LC_left_item">';
             $output .= '<tr>';      }
         }      my $defcheck = ' ';
         if ($colsleft > 1) {      if (ref($settings) eq 'HASH') {  
             $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">';          if (ref($settings->{$context}) eq 'ARRAY') {
         } else {              if (grep(/^default$/,@{$settings->{$context}})) {
             $output .= '<td class="LC_left_item">';  
         }  
         my $defcheck = ' ';  
         if (ref($settings) eq 'HASH') {    
             if (ref($settings->{$context}) eq 'ARRAY') {  
                 if (grep(/^default$/,@{$settings->{$context}})) {  
                     $defcheck = ' checked="checked" ';  
                 }  
             } elsif ($context eq 'statustocreate') {  
                 $defcheck = ' checked="checked" ';                  $defcheck = ' checked="checked" ';
             }              }
           } elsif ($context eq 'statustocreate') {
               $defcheck = ' checked="checked" ';
         }          }
         $output .= '<span class="LC_nobreak"><label>'.  
                    '<input type="checkbox" name="'.$context.'" '.  
                    'value="default"'.$defcheck.$onclick.' />'.  
                    $othertitle.'</label></span>';  
     }      }
     $output .= '</td></tr></table></td></tr>';      $output .= '<span class="LC_nobreak"><label>'.
                  '<input type="checkbox" name="'.$context.'" '.
                  'value="default"'.$defcheck.'/>'.
                  $othertitle.'</label></span></td>'.
                  '</tr></table></td></tr>';
     return $output;      return $output;
 }  }
   
Line 10066  sub usertype_update_row { Line 6871  sub usertype_update_row {
 sub modify_login {  sub modify_login {
     my ($r,$dom,$confname,$lastactref,%domconfig) = @_;      my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
     my ($resulttext,$errors,$colchgtext,%changes,%colchanges,%newfile,%newurl,      my ($resulttext,$errors,$colchgtext,%changes,%colchanges,%newfile,%newurl,
         %curr_loginvia,%loginhash,@currlangs,@newlangs,$addedfile,%title,@offon,          %curr_loginvia,%loginhash,@currlangs,@newlangs,$addedfile,%title,@offon);
         %currsaml,%saml,%samltext,%samlimg,%samlalt,%samlurl,%samltitle,%samlwindow,%samlnotsso);  
     %title = ( coursecatalog => 'Display course catalog',      %title = ( coursecatalog => 'Display course catalog',
                adminmail => 'Display administrator E-mail address',                 adminmail => 'Display administrator E-mail address',
                helpdesk  => 'Display "Contact Helpdesk" link',                 helpdesk  => 'Display "Contact Helpdesk" link',
                newuser => 'Link for visitors to create a user account',                 newuser => 'Link for visitors to create a user account',
                loginheader => 'Log-in box header',                 loginheader => 'Log-in box header');
                saml => 'Dual SSO and non-SSO login');  
     @offon = ('off','on');      @offon = ('off','on');
     if (ref($domconfig{login}) eq 'HASH') {      if (ref($domconfig{login}) eq 'HASH') {
         if (ref($domconfig{login}{loginvia}) eq 'HASH') {          if (ref($domconfig{login}{loginvia}) eq 'HASH') {
Line 10081  sub modify_login { Line 6884  sub modify_login {
                 $curr_loginvia{$lonhost} = $domconfig{login}{loginvia}{$lonhost};                  $curr_loginvia{$lonhost} = $domconfig{login}{loginvia}{$lonhost};
             }              }
         }          }
         if (ref($domconfig{login}{'saml'}) eq 'HASH') {  
             foreach my $lonhost (keys(%{$domconfig{login}{'saml'}})) {  
                 if (ref($domconfig{login}{'saml'}{$lonhost}) eq 'HASH') {  
                     $currsaml{$lonhost} = $domconfig{login}{'saml'}{$lonhost};  
                     $saml{$lonhost} = 1;  
                     $samltext{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'text'};  
                     $samlurl{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'url'};  
                     $samlalt{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'alt'};  
                     $samlimg{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'img'};  
                     $samltitle{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'title'};  
                     $samlwindow{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'window'};  
                     $samlnotsso{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'notsso'};  
                 }  
             }  
         }  
     }      }
     ($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'],      ($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'],
                                            \%domconfig,\%loginhash);                                             \%domconfig,\%loginhash);
Line 10291  sub modify_login { Line 7079  sub modify_login {
             } elsif ($currheadtagurls{$lonhost}) {              } elsif ($currheadtagurls{$lonhost}) {
                 $loginhash{'login'}{'headtag'}{$lonhost}{'url'} = $currheadtagurls{$lonhost};                  $loginhash{'login'}{'headtag'}{$lonhost}{'url'} = $currheadtagurls{$lonhost};
                 if ($currexempt{$lonhost}) {                  if ($currexempt{$lonhost}) {
                     if ((!exists($possexempt{$lonhost})) || ($possexempt{$lonhost} ne $currexempt{$lonhost})) {                      if ((!exists($possexempt{$lonhost})) || ($possexempt{$lonhost} ne $currexempt{$lonhost})) { 
                         $changes{'headtag'}{$lonhost} = 1;                          $changes{'headtag'}{$lonhost} = 1;
                     }                      }
                 } elsif ($possexempt{$lonhost}) {                  } elsif ($possexempt{$lonhost}) {
Line 10342  sub modify_login { Line 7130  sub modify_login {
             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';              $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
         }          }
     }      }
     my @delsamlimg = &Apache::loncommon::get_env_multiple('form.saml_img_del');  
     my @newsamlimgs;  
     foreach my $lonhost (keys(%domservers)) {  
         if ($env{'form.saml_'.$lonhost}) {  
             if ($env{'form.saml_img_'.$lonhost.'.filename'}) {  
                 push(@newsamlimgs,$lonhost);  
             }  
             foreach my $item ('text','alt','url','title','window','notsso') {  
                 $env{'form.saml_'.$item.'_'.$lonhost} =~ s/^\s+|\s+$//g;  
             }  
             if ($saml{$lonhost}) {  
                 if ($env{'form.saml_window_'.$lonhost} ne '1') {  
                     $env{'form.saml_window_'.$lonhost} = '';  
                 }  
                 if (grep(/^\Q$lonhost\E$/,@delsamlimg)) {  
 #FIXME Need to obsolete published image  
                     delete($currsaml{$lonhost}{'img'});  
                     $changes{'saml'}{$lonhost} = 1;  
                 }  
                 if ($env{'form.saml_alt_'.$lonhost} ne $samlalt{$lonhost}) {  
                     $changes{'saml'}{$lonhost} = 1;  
                 }  
                 if ($env{'form.saml_text_'.$lonhost} ne $samltext{$lonhost}) {  
                     $changes{'saml'}{$lonhost} = 1;  
                 }  
                 if ($env{'form.saml_url_'.$lonhost} ne $samlurl{$lonhost}) {  
                     $changes{'saml'}{$lonhost} = 1;  
                 }  
                 if ($env{'form.saml_title_'.$lonhost} ne $samltitle{$lonhost}) {  
                     $changes{'saml'}{$lonhost} = 1;  
                 }  
                 if ($env{'form.saml_window_'.$lonhost} ne $samlwindow{$lonhost}) {  
                     $changes{'saml'}{$lonhost} = 1;  
                 }  
                 if ($env{'form.saml_notsso_'.$lonhost} ne $samlnotsso{$lonhost}) {  
                     $changes{'saml'}{$lonhost} = 1;  
                 }  
             } else {  
                 $changes{'saml'}{$lonhost} = 1;  
             }  
             foreach my $item ('text','alt','url','title','window','notsso') {  
                 $currsaml{$lonhost}{$item} = $env{'form.saml_'.$item.'_'.$lonhost};  
             }  
         } else {  
             if ($saml{$lonhost}) {  
                 $changes{'saml'}{$lonhost} = 1;  
                 delete($currsaml{$lonhost});  
             }  
         }  
     }  
     foreach my $posshost (keys(%currsaml)) {  
         unless (exists($domservers{$posshost})) {  
             delete($currsaml{$posshost});  
         }  
     }  
     %{$loginhash{'login'}{'saml'}} = %currsaml;  
     if (@newsamlimgs) {  
         my $error;  
         my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);  
         if ($configuserok eq 'ok') {  
             if ($switchserver) {  
                 $error = &mt("Upload of SSO Button Image is not permitted to this server: [_1].",$switchserver);  
             } elsif ($author_ok eq 'ok') {  
                 foreach my $lonhost (@newsamlimgs) {  
                     my $formelem = 'saml_img_'.$lonhost;  
                     my ($result,$imgurl) = &publishlogo($r,'upload',$formelem,$dom,$confname,  
                                                         "login/saml/$lonhost",'','',  
                                                         $env{'form.saml_img_'.$lonhost.'.filename'});  
                     if ($result eq 'ok') {  
                         $currsaml{$lonhost}{'img'} = $imgurl;  
                         $loginhash{'login'}{'saml'}{$lonhost}{'img'} = $imgurl;  
                         $changes{'saml'}{$lonhost} = 1;  
                     } else {  
                         my $puberror = &mt("Upload of SSO button image failed for [_1] because an error occurred publishing the file in RES space. Error was: [_2].",  
                                            $lonhost,$result);  
                         $errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';  
                     }  
                 }  
             } else {  
                 $error = &mt("Upload of SSO button image 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 SSO button image 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 10471  sub modify_login { Line 7170  sub modify_login {
         }          }
         if (keys(%changes) > 0 || $colchgtext) {          if (keys(%changes) > 0 || $colchgtext) {
             &Apache::loncommon::devalidate_domconfig_cache($dom);              &Apache::loncommon::devalidate_domconfig_cache($dom);
             if (exists($changes{'saml'})) {  
                 my $hostid_in_use;  
                 my @hosts = &Apache::lonnet::current_machine_ids();  
                 if (@hosts > 1) {  
                     foreach my $hostid (@hosts) {  
                         if (&Apache::lonnet::host_domain($hostid) eq $dom) {  
                             $hostid_in_use = $hostid;  
                             last;  
                         }  
                     }  
                 } else {  
                     $hostid_in_use = $r->dir_config('lonHostID');  
                 }  
                 if (($hostid_in_use) &&  
                     (&Apache::lonnet::host_domain($hostid_in_use) eq $dom)) {  
                     &Apache::lonnet::devalidate_cache_new('samllanding',$hostid_in_use);  
                 }  
                 if (ref($lastactref) eq 'HASH') {  
                     if (ref($changes{'saml'}) eq 'HASH') {  
                         my %updates;  
                         map { $updates{$_} = 1; } keys(%{$changes{'saml'}});  
                         $lastactref->{'samllanding'} = \%updates;  
                     }  
                 }  
             }  
             if (ref($lastactref) eq 'HASH') {              if (ref($lastactref) eq 'HASH') {
                 $lastactref->{'domainconfig'} = 1;                  $lastactref->{'domainconfig'} = 1;
             }              }
Line 10575  sub modify_login { Line 7249  sub modify_login {
                             }                              }
                         }                          }
                     }                      }
                 } elsif ($item eq 'saml') {  
                     if (ref($changes{$item}) eq 'HASH') {  
                         my %notlt = (  
                                        text   => 'Text for log-in by SSO',  
                                        img    => 'SSO button image',  
                                        alt    => 'Alt text for button image',  
                                        url    => 'SSO URL',  
                                        title  => 'Tooltip for SSO link',  
                                        window => 'Pop-up window if iframe',  
                                        notsso => 'Text for non-SSO log-in',  
                                     );  
                         foreach my $lonhost (sort(keys(%{$changes{$item}}))) {  
                             if (ref($currsaml{$lonhost}) eq 'HASH') {  
                                 $resulttext .= '<li>'.&mt("$title{$item} in use for [_1]","<b>$lonhost</b>").  
                                                '<ul>';  
                                 foreach my $key ('text','img','alt','url','title','window','notsso') {  
                                     if ($currsaml{$lonhost}{$key} eq '') {  
                                         $resulttext .= '<li>'.&mt("$notlt{$key} not in use").'</li>';  
                                     } else {  
                                         my $value = "'$currsaml{$lonhost}{$key}'";  
                                         if ($key eq 'img') {  
                                             $value = '<img src="'.$currsaml{$lonhost}{$key}.'" />';  
                                         } elsif ($key eq 'window') {  
                                             $value = 'On';  
                                         }  
                                         $resulttext .= '<li>'.&mt("$notlt{$key} set to: [_1]",  
                                                                   $value).'</li>';  
                                     }  
                                 }  
                                 $resulttext .= '</ul></li>';  
                             } else {  
                                 $resulttext .= '<li>'.&mt("$title{$item} not in use for [_1]",$lonhost).'</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 10672  sub modify_login { Line 7311  sub modify_login {
     return $resulttext;      return $resulttext;
 }  }
   
   
 sub check_exempt_addresses {  sub check_exempt_addresses {
     my ($iplist) = @_;      my ($iplist) = @_;
     $iplist =~ s/^\s+//;      $iplist =~ s/^\s+//;
Line 10712  sub color_font_choices { Line 7352  sub color_font_choices {
     return %choices;      return %choices;
 }  }
   
 sub modify_ipaccess {  
     my ($dom,$lastactref,%domconfig) = @_;  
     my (@allpos,%changes,%confhash,$errors,$resulttext);  
     my (@items,%deletions,%itemids,@warnings);  
     my ($typeorder,$types) = &commblocktype_text();  
     if ($env{'form.ipaccess_add'}) {  
         my $name = $env{'form.ipaccess_name_add'};  
         my ($newid,$error) = &get_ipaccess_id($dom,$name);  
         if ($newid) {  
             $itemids{'add'} = $newid;  
             push(@items,'add');  
             $changes{$newid} = 1;  
         } else {  
             $error = &mt('Failed to acquire unique ID for new IP access control item');  
             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';  
         }  
     }  
     if (ref($domconfig{'ipaccess'}) eq 'HASH') {  
         my @todelete = &Apache::loncommon::get_env_multiple('form.ipaccess_del');  
         if (@todelete) {  
             map { $deletions{$_} = 1; } @todelete;  
         }  
         my $maxnum = $env{'form.ipaccess_maxnum'};  
         for (my $i=0; $i<$maxnum; $i++) {  
             my $itemid = $env{'form.ipaccess_id_'.$i};  
             $itemid =~ s/\D+//g;  
             if (ref($domconfig{'ipaccess'}{$itemid}) eq 'HASH') {  
                 if ($deletions{$itemid}) {  
                     $changes{$itemid} = $domconfig{'ipaccess'}{$itemid}{'name'};  
                 } else {  
                     push(@items,$i);  
                     $itemids{$i} = $itemid;  
                 }  
             }  
         }  
     }  
     foreach my $idx (@items) {  
         my $itemid = $itemids{$idx};  
         next unless ($itemid);  
         my %current;  
         unless ($idx eq 'add') {  
             if (ref($domconfig{'ipaccess'}{$itemid}) eq 'HASH') {  
                 %current = %{$domconfig{'ipaccess'}{$itemid}};  
             }  
         }  
         my $position = $env{'form.ipaccess_pos_'.$itemid};  
         $position =~ s/\D+//g;  
         if ($position ne '') {  
             $allpos[$position] = $itemid;  
         }  
         my $name = $env{'form.ipaccess_name_'.$idx};  
         $name =~ s/^\s+|\s+$//g;  
         $confhash{$itemid}{'name'} = $name;  
         my $possrange = $env{'form.ipaccess_range_'.$idx};  
         $possrange =~ s/^\s+|\s+$//g;  
         unless ($possrange eq '') {  
             $possrange =~ s/[\r\n]+/\s/g;  
             $possrange =~ s/\s*-\s*/-/g;  
             $possrange =~ s/\s+/,/g;  
             $possrange =~ s/,+/,/g;  
             if ($possrange ne '') {  
                 my (@ok,$count);  
                 $count = 0;  
                 foreach my $poss (split(/\,/,$possrange)) {  
                     $count ++;  
                     $poss = &validate_ip_pattern($poss);  
                     if ($poss ne '') {  
                         push(@ok,$poss);  
                     }  
                 }  
                 my $diff = $count - scalar(@ok);  
                 if ($diff) {  
                     $errors .= '<li><span class="LC_error">'.  
                                &mt('[quant,_1,IP] invalid and excluded from saved value for IP range(s) for [_2]',  
                                    $diff,$name).  
                                '</span></li>';  
                 }  
                 if (@ok) {  
                     my @cidr_list;  
                     foreach my $item (@ok) {  
                         @cidr_list = &Net::CIDR::cidradd($item,@cidr_list);  
                     }  
                     $confhash{$itemid}{'ip'} = join(',',@cidr_list);  
                 }  
             }  
         }  
         foreach my $field ('name','ip') {  
             unless (($idx eq 'add') || ($changes{$itemid})) {  
                 if ($current{$field} ne $confhash{$itemid}{$field}) {  
                     $changes{$itemid} = 1;  
                     last;  
                 }  
             }  
         }  
         $confhash{$itemid}{'commblocks'} = {};  
   
         my %commblocks;  
         map { $commblocks{$_} = 1; } &Apache::loncommon::get_env_multiple('form.ipaccess_block_'.$idx);  
         foreach my $type (@{$typeorder}) {  
             if ($commblocks{$type}) {  
                 $confhash{$itemid}{'commblocks'}{$type} = 'on';  
             }  
             unless (($idx eq 'add') || ($changes{$itemid})) {  
                 if (ref($current{'commblocks'}) eq 'HASH') {  
                     if ($confhash{$itemid}{'commblocks'}{$type} ne $current{'commblocks'}{$type}) {  
                         $changes{$itemid} = 1;  
                     }  
                 } elsif ($confhash{$itemid}{'commblocks'}{$type}) {  
                     $changes{$itemid} = 1;  
                 }  
             }  
         }  
         $confhash{$itemid}{'courses'} = {};  
         my %crsdeletions;  
         my @delcrs = &Apache::loncommon::get_env_multiple('form.ipaccess_course_delete_'.$idx);  
         if (@delcrs) {  
             map { $crsdeletions{$_} = 1; } @delcrs;  
         }  
         if (ref($current{'courses'}) eq 'HASH') {  
             foreach my $cid (sort(keys(%{$current{'courses'}}))) {  
                 if ($crsdeletions{$cid}) {  
                     $changes{$itemid} = 1;  
                 } else {  
                     $confhash{$itemid}{'courses'}{$cid} = 1;  
                 }  
             }  
         }  
         $env{'form.ipaccess_cnum_'.$idx} =~ s/^\s+|\s+$//g;  
         $env{'form.ipaccess_cdom_'.$idx} =~ s/^\s+|\s+$//g;  
         if (($env{'form.ipaccess_cnum_'.$idx} =~ /^$match_courseid$/) &&  
             ($env{'form.ipaccess_cdom_'.$idx} =~ /^$match_domain$/)) {  
             if (&Apache::lonnet::homeserver($env{'form.ipaccess_cnum_'.$idx},  
                                             $env{'form.ipaccess_cdom_'.$idx}) eq 'no_host') {  
                 $errors .= '<li><span class="LC_error">'.  
                            &mt('Invalid courseID [_1] omitted from list of allowed courses',  
                                $env{'form.ipaccess_cdom_'.$idx}.'_'.$env{'form.ipaccess_cnum_'.$idx}).  
                            '</span></li>';  
             } else {  
                 $confhash{$itemid}{'courses'}{$env{'form.ipaccess_cdom_'.$idx}.'_'.$env{'form.ipaccess_cnum_'.$idx}} = 1;  
                 $changes{$itemid} = 1;  
             }  
         }  
     }  
     if (@allpos > 0) {  
         my $idx = 0;  
         foreach my $itemid (@allpos) {  
             if ($itemid ne '') {  
                 $confhash{$itemid}{'order'} = $idx;  
                 unless ($changes{$itemid}) {  
                     if (ref($domconfig{'ipaccess'}) eq 'HASH') {  
                         if (ref($domconfig{'ipaccess'}{$itemid}) eq 'HASH') {  
                             if ($domconfig{'ipaccess'}{$itemid}{'order'} ne $idx) {  
                                 $changes{$itemid} = 1;  
                             }  
                         }  
                     }  
                 }  
                 $idx ++;  
             }  
         }  
     }  
     if (keys(%changes)) {  
         my %defaultshash = (  
                               ipaccess => \%confhash,  
                            );  
         my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,  
                                                  $dom);  
         if ($putresult eq 'ok') {  
             my $cachetime = 1800;  
             &Apache::lonnet::do_cache_new('ipaccess',$dom,\%confhash,$cachetime);  
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'ipaccess'} = 1;  
             }  
             $resulttext = &mt('Changes made:').'<ul>';  
             my %bynum;  
             foreach my $itemid (sort(keys(%changes))) {  
                 if (ref($confhash{$itemid}) eq 'HASH') {  
                     my $position = $confhash{$itemid}{'order'};  
                     if ($position =~ /^\d+$/) {  
                         $bynum{$position} = $itemid;  
                     }  
                 }  
             }  
             if (keys(%deletions)) {  
                 foreach my $itemid (sort { $a <=> $b } keys(%deletions)) {  
                     $resulttext .= '<li>'.&mt('Deleted: [_1]',$changes{$itemid}).'</li>';  
                 }  
             }  
             foreach my $pos (sort { $a <=> $b } keys(%bynum)) {  
                 my $itemid = $bynum{$pos};  
                 if (ref($confhash{$itemid}) eq 'HASH') {  
                     $resulttext .= '<li><b>'.$confhash{$itemid}{'name'}.'</b><ul>';  
                     my $position = $pos + 1;  
                     $resulttext .= '<li>'.&mt('Order: [_1]',$position).'</li>';  
                     if ($confhash{$itemid}{'ip'} eq '') {  
                         $resulttext .= '<li>'.&mt('No IP Range(s) set').'</li>';  
                     } else {  
                         $resulttext .= '<li>'.&mt('IP Range(s): [_1]',$confhash{$itemid}{'ip'}).'</li>';  
                     }  
                     if (keys(%{$confhash{$itemid}{'commblocks'}})) {  
                         $resulttext .= '<li>'.&mt('Functionality Blocked: [_1]',  
                                                   join(', ', map { $types->{$_}; } sort(keys(%{$confhash{$itemid}{'commblocks'}})))).  
                                        '</li>';  
                     } else {  
                         $resulttext .= '<li>'.&mt('No functionality blocked').'</li>';  
                     }  
                     if (keys(%{$confhash{$itemid}{'courses'}})) {  
                         my @courses;  
                         foreach my $cid (sort(keys(%{$confhash{$itemid}{'courses'}}))) {  
                             my %courseinfo = &Apache::lonnet::coursedescription($cid,{'one_time' => 1});  
                             push(@courses,$courseinfo{'description'}.' ('.$cid.')');  
                         }  
                         $resulttext .= '<li>'.&mt('Courses/Communities allowed').':<ul><li>'.  
                                              join('</li><li>',@courses).'</li></ul>';  
                     } else {  
                         $resulttext .= '<li>'.&mt('No courses allowed').'</li>';  
                     }  
                     $resulttext .= '</ul></li>';  
                 }  
             }  
             $resulttext .= '</ul>';  
         } else {  
             $errors .= '<li><span class="LC_error">'.&mt('Failed to save changes').'</span></li>';  
         }  
     } else {  
         $resulttext = &mt('No changes made');  
     }  
     if ($errors) {  
         $resulttext .= '<p>'.&mt('The following errors occurred: ').'<ul>'.  
                        $errors.'</ul></p>';  
     }  
     return $resulttext;  
 }  
   
 sub get_ipaccess_id {  
     my ($domain,$location) = @_;  
     # get lock on ipaccess db  
     my $lockhash = {  
                       lock => $env{'user.name'}.  
                               ':'.$env{'user.domain'},  
                    };  
     my $tries = 0;  
     my $gotlock = &Apache::lonnet::newput_dom('ipaccess',$lockhash,$domain);  
     my ($id,$error);  
   
     while (($gotlock ne 'ok') && ($tries<10)) {  
         $tries ++;  
         sleep (0.1);  
         $gotlock = &Apache::lonnet::newput_dom('ipaccess',$lockhash,$domain);  
     }  
     if ($gotlock eq 'ok') {  
         my %currids = &Apache::lonnet::dump_dom('ipaccess',$domain);  
         if ($currids{'lock'}) {  
             delete($currids{'lock'});  
             if (keys(%currids)) {  
                 my @curr = sort { $a <=> $b } keys(%currids);  
                 if ($curr[-1] =~ /^\d+$/) {  
                     $id = 1 + $curr[-1];  
                 }  
             } else {  
                 $id = 1;  
             }  
             if ($id) {  
                 unless (&Apache::lonnet::newput_dom('ipaccess',{ $id => $location },$domain) eq 'ok') {  
                     $error = 'nostore';  
                 }  
             } else {  
                 $error = 'nonumber';  
             }  
         }  
         my $dellockoutcome = &Apache::lonnet::del_dom('ipaccess',['lock'],$domain);  
     } else {  
         $error = 'nolock';  
     }  
     return ($id,$error);  
 }  
   
 sub modify_rolecolors {  sub modify_rolecolors {
     my ($r,$dom,$confname,$roles,$lastactref,%domconfig) = @_;      my ($r,$dom,$confname,$roles,$lastactref,%domconfig) = @_;
     my ($resulttext,%rolehash);      my ($resulttext,%rolehash);
Line 11096  sub modify_colors { Line 7459  sub modify_colors {
             $domconfig->{$role} = {};              $domconfig->{$role} = {};
         }          }
         foreach my $img (@images) {          foreach my $img (@images) {
             if ($role eq 'login') {              if (($role eq 'login') && (($img eq 'img') || ($img eq 'logo'))) {  
                 if (($img eq 'img') || ($img eq 'logo')) {                    if (defined($env{'form.login_showlogo_'.$img})) {
                     if (defined($env{'form.login_showlogo_'.$img})) {                      $confhash->{$role}{'showlogo'}{$img} = 1;
                         $confhash->{$role}{'showlogo'}{$img} = 1;                  } else { 
                     } else {                       $confhash->{$role}{'showlogo'}{$img} = 0;
                         $confhash->{$role}{'showlogo'}{$img} = 0;  
                     }  
                 }  
                 if ($env{'form.login_alt_'.$img} ne '') {  
                     $confhash->{$role}{'alttext'}{$img} = $env{'form.login_alt_'.$img};  
                 }                  }
             }              } 
     if ( ! $env{'form.'.$role.'_'.$img.'.filename'}       if ( ! $env{'form.'.$role.'_'.$img.'.filename'} 
  && !defined($domconfig->{$role}{$img})   && !defined($domconfig->{$role}{$img})
  && !$env{'form.'.$role.'_del_'.$img}   && !$env{'form.'.$role.'_del_'.$img}
Line 11182  sub modify_colors { Line 7540  sub modify_colors {
                             $changes{$role}{'images'}{$img} = 1;                              $changes{$role}{'images'}{$img} = 1;
                         }                           } 
                     }                      }
                     if ($role eq 'login') {                      if (($role eq 'login') && (($img eq 'logo') || ($img eq 'img'))) {
                         if (($img eq 'logo') || ($img eq 'img')) {                          if (ref($domconfig->{'login'}{'showlogo'}) eq 'HASH') {
                             if (ref($domconfig->{'login'}{'showlogo'}) eq 'HASH') {                              if ($confhash->{$role}{'showlogo'}{$img} ne 
                                 if ($confhash->{$role}{'showlogo'}{$img} ne                                   $domconfig->{$role}{'showlogo'}{$img}) {
                                     $domconfig->{$role}{'showlogo'}{$img}) {                                  $changes{$role}{'showlogo'}{$img} = 1; 
                                     $changes{$role}{'showlogo'}{$img} = 1;   
                                 }  
                             } else {  
                                 if ($confhash->{$role}{'showlogo'}{$img} == 0) {  
                                     $changes{$role}{'showlogo'}{$img} = 1;  
                                 }  
                             }                              }
                         }                          } else {
                         if ($img ne 'login') {                              if ($confhash->{$role}{'showlogo'}{$img} == 0) {
                             if (ref($domconfig->{$role}{'alttext'}) eq 'HASH') {                                  $changes{$role}{'showlogo'}{$img} = 1;
                                 if ($confhash->{$role}{'alttext'}{$img} ne  
                                     $domconfig->{$role}{'alttext'}{$img}) {  
                                     $changes{$role}{'alttext'}{$img} = 1;  
                                 }  
                             } else {  
                                 if ($confhash->{$role}{'alttext'}{$img} ne '') {  
                                     $changes{$role}{'alttext'}{$img} = 1;  
                                 }  
                             }                              }
                         }                          }
                     }                      }
Line 11315  sub default_change_checker { Line 7659  sub default_change_checker {
             if ($confhash->{$role}{'showlogo'}{$img} == 0) {              if ($confhash->{$role}{'showlogo'}{$img} == 0) {
                 $changes->{$role}{'showlogo'}{$img} = 1;                  $changes->{$role}{'showlogo'}{$img} = 1;
             }              }
             if (ref($confhash->{$role}{'alttext'}) eq 'HASH') {  
                 if ($confhash->{$role}{'alttext'}{$img} ne '') {  
                     $changes->{$role}{'alttext'}{$img} = 1;  
                 }  
             }  
         }          }
     }      }
     if ($confhash->{$role}{'font'}) {      if ($confhash->{$role}{'font'}) {
Line 11358  sub display_colorchgs { Line 7697  sub display_colorchgs {
                             } else {                              } else {
                                 $resulttext .= '<li>'.&mt("$choices{$item} set to not be displayed").'</li>';                                  $resulttext .= '<li>'.&mt("$choices{$item} set to not be displayed").'</li>';
                             }                              }
                         } elsif (($role eq 'login') && ($key eq 'alttext')) {  
                             if ($confhash->{$role}{$key}{$item} ne '') {  
                                 $resulttext .= '<li>'.&mt("$choices{$key} for $choices{$item} set to [_1].",  
                                                $confhash->{$role}{$key}{$item}).'</li>';  
                             } else {  
                                 $resulttext .= '<li>'.&mt("$choices{$key} for $choices{$item} deleted.").'</li>';  
                             }  
                         } elsif ($confhash->{$role}{$item} eq '') {                          } elsif ($confhash->{$role}{$item} eq '') {
                             $resulttext .= '<li>'.&mt("$choices{$item} set to default").'</li>';                              $resulttext .= '<li>'.&mt("$choices{$item} set to default").'</li>';
                         } else {                          } else {
Line 11423  sub check_configuser { Line 7755  sub check_configuser {
     my ($configuserok,%currroles);      my ($configuserok,%currroles);
     if ($uhome eq 'no_host') {      if ($uhome eq 'no_host') {
         srand( time() ^ ($$ + ($$ << 15))  ); # Seed rand.          srand( time() ^ ($$ + ($$ << 15))  ); # Seed rand.
         my $configpass = &LONCAPA::Enrollment::create_password($dom);          my $configpass = &LONCAPA::Enrollment::create_password();
         $configuserok =           $configuserok = 
             &Apache::lonnet::modifyuser($dom,$confname,'','internal',              &Apache::lonnet::modifyuser($dom,$confname,'','internal',
                              $configpass,'','','','','',undef,$servadm);                               $configpass,'','','','','',undef,$servadm);
Line 11452  sub check_authorstatus { Line 7784  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 11497  sub publishlogo { Line 7829  sub publishlogo {
     } else {      } else {
         my $source = $filepath.'/'.$file;          my $source = $filepath.'/'.$file;
         my $logfile;          my $logfile;
         if (!open($logfile,">>",$source.'.log')) {          if (!open($logfile,">>$source".'.log')) {
             return (&mt('No write permission to Authoring Space'));              return (&mt('No write permission to Authoring Space'));
         }          }
         print $logfile          print $logfile
 "\n================= Publish ".localtime()." ================\n".  "\n================= Publish ".localtime()." ================\n".
 $env{'user.name'}.':'.$env{'user.domain'}."\n";  $env{'user.name'}.':'.$env{'user.domain'}."\n";
 # Save the file  # Save the file
         if (!open(FH,">",$source)) {          if (!open(FH,'>'.$source)) {
             &Apache::lonnet::logthis('Failed to create '.$source);              &Apache::lonnet::logthis('Failed to create '.$source);
             return (&mt('Failed to create file'));              return (&mt('Failed to create file'));
         }          }
Line 11565  $env{'user.name'}.':'.$env{'user.domain' Line 7897  $env{'user.name'}.':'.$env{'user.domain'
                 if ($fullwidth ne '' && $fullheight ne '') {                   if ($fullwidth ne '' && $fullheight ne '') { 
                     if ($fullwidth > $thumbwidth && $fullheight > $thumbheight) {                      if ($fullwidth > $thumbwidth && $fullheight > $thumbheight) {
                         my $thumbsize = $thumbwidth.'x'.$thumbheight;                          my $thumbsize = $thumbwidth.'x'.$thumbheight;
                         my @args = ('convert','-sample',$thumbsize,$inputfile,$outfile);                          system("convert -sample $thumbsize $inputfile $outfile");
                         system({$args[0]} @args);  
                         chmod(0660, $filepath.'/tn-'.$file);                          chmod(0660, $filepath.'/tn-'.$file);
                         if (-e $outfile) {                          if (-e $outfile) {
                             my $copyfile=$targetdir.'/tn-'.$file;                              my $copyfile=$targetdir.'/tn-'.$file;
Line 11581  $env{'user.name'}.':'.$env{'user.domain' Line 7912  $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 11593  $env{'user.name'}.':'.$env{'user.domain' Line 7925  $env{'user.name'}.':'.$env{'user.domain'
             $output = $versionresult;              $output = $versionresult;
         }          }
     }      }
     return ($output,$logourl);      return ($output,$logourl,$madethumb);
 }  }
   
 sub logo_versioning {  sub logo_versioning {
Line 11645  sub write_metadata { Line 7977  sub write_metadata {
     {      {
         print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file;          print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file;
         my $mfh;          my $mfh;
         if (open($mfh,">",$targetdir.'/'.$file.'.meta')) {          if (open($mfh,'>'.$targetdir.'/'.$file.'.meta')) {
             foreach (sort(keys(%metadatafields))) {              foreach (sort(keys(%metadatafields))) {
                 unless ($_=~/\./) {                  unless ($_=~/\./) {
                     my $unikey=$_;                      my $unikey=$_;
Line 11679  sub notifysubscribed { Line 8011  sub notifysubscribed {
         next unless (ref($targetsource) eq 'ARRAY');          next unless (ref($targetsource) eq 'ARRAY');
         my ($target,$source)=@{$targetsource};          my ($target,$source)=@{$targetsource};
         if ($source ne '') {          if ($source ne '') {
             if (open(my $logfh,">>",$source.'.log')) {              if (open(my $logfh,'>>'.$source.'.log')) {
                 print $logfh "\nCleanup phase: Notifications\n";                  print $logfh "\nCleanup phase: Notifications\n";
                 my @subscribed=&subscribed_hosts($target);                  my @subscribed=&subscribed_hosts($target);
                 foreach my $subhost (@subscribed) {                  foreach my $subhost (@subscribed) {
Line 11705  sub notifysubscribed { Line 8037  sub notifysubscribed {
 sub subscribed_hosts {  sub subscribed_hosts {
     my ($target) = @_;      my ($target) = @_;
     my @subscribed;      my @subscribed;
     if (open(my $fh,"<","$target.subscription")) {      if (open(my $fh,"<$target.subscription")) {
         while (my $subline=<$fh>) {          while (my $subline=<$fh>) {
             if ($subline =~ /^($match_lonid):/) {              if ($subline =~ /^($match_lonid):/) {
                 my $host = $1;                  my $host = $1;
Line 11747  sub modify_quotas { Line 8079  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 11762  sub modify_quotas { Line 8094  sub modify_quotas {
         @usertools = ('author');          @usertools = ('author');
         %titles = &authorrequest_titles();          %titles = &authorrequest_titles();
     } else {      } else {
         @usertools = ('aboutme','blog','webdav','portfolio','timezone');          @usertools = ('aboutme','blog','webdav','portfolio');
         %titles = &tool_titles();          %titles = &tool_titles();
     }      }
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
Line 11796  sub modify_quotas { Line 8128  sub modify_quotas {
         my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval');          my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval');
         @approvalnotify = sort(@approvalnotify);          @approvalnotify = sort(@approvalnotify);
         $confhash{'notify'}{'approval'} = join(',',@approvalnotify);          $confhash{'notify'}{'approval'} = join(',',@approvalnotify);
         my @crstypes = ('official','unofficial','community','textbook');          my @crstypes = ('official','unofficial','community','textbook','placement');
         my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');          my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');
         foreach my $type (@hasuniquecode) {          foreach my $type (@hasuniquecode) {
             if (grep(/^\Q$type\E$/,@crstypes)) {              if (grep(/^\Q$type\E$/,@crstypes)) {
Line 11890  sub modify_quotas { Line 8222  sub modify_quotas {
                                     my $newpos = $env{'form.'.$itemid};                                      my $newpos = $env{'form.'.$itemid};
                                     $newpos =~ s/\D+//g;                                      $newpos =~ s/\D+//g;
                                     foreach my $item ('subject','title','publisher','author') {                                      foreach my $item ('subject','title','publisher','author') {
                                         next if ((($item eq 'author') || ($item eq 'publisher')) &&                                          next if ((($item eq 'author') || ($item eq 'publisher')) && 
                                                  ($type eq 'templates'));                                                   ($type eq 'templates'));
                                         $confhash{$type}{$key}{$item} = $env{'form.'.$type.'_'.$item.'_'.$i};                                          $confhash{$type}{$key}{$item} = $env{'form.'.$type.'_'.$item.'_'.$i};
                                         if ($domconfig{$action}{$type}{$key}{$item} ne $confhash{$type}{$key}{$item}) {                                          if ($domconfig{$action}{$type}{$key}{$item} ne $confhash{$type}{$key}{$item}) {
Line 11904  sub modify_quotas { Line 8236  sub modify_quotas {
                                     #FIXME need to obsolete item in RES space                                      #FIXME need to obsolete item in RES space
                                 } elsif ($env{'form.'.$type.'_image_'.$i.'.filename'}) {                                  } elsif ($env{'form.'.$type.'_image_'.$i.'.filename'}) {
                                     my ($cdom,$cnum) = split(/_/,$key);                                      my ($cdom,$cnum) = split(/_/,$key);
                                     if (&Apache::lonnet::homeserver($cnum,$cdom) eq 'no_host') {                                      my ($imgurl,$error) = &process_textbook_image($r,$dom,$confname,$type.'_image_'.$i,
                                         $errors .= '<li><span class="LC_error">'.&mt('Image not saved: could not find textbook course').'</li>';                                                                                    $cdom,$cnum,$type,$configuserok,
                                     } else {                                                                                    $switchserver,$author_ok);
                                         my ($imgurl,$error) = &process_textbook_image($r,$dom,$confname,$type.'_image_'.$i,                                      if ($imgurl) {
                                                                                       $cdom,$cnum,$type,$configuserok,                                          $confhash{$type}{$key}{'image'} = $imgurl;
                                                                                       $switchserver,$author_ok);                                          $changes{$type}{$key} = 1; 
                                         if ($imgurl) {                                      }
                                             $confhash{$type}{$key}{'image'} = $imgurl;                                      if ($error) {
                                             $changes{$type}{$key} = 1;                                           &Apache::lonnet::logthis($error);
                                         }                                          $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                                         if ($error) {  
                                             &Apache::lonnet::logthis($error);  
                                             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';  
                                         }  
                                     }                                       } 
                                 } elsif ($domconfig{$action}{$type}{$key}{'image'}) {                                  } elsif ($domconfig{$action}{$type}{$key}{'image'}) {
                                     $confhash{$type}{$key}{'image'} =                                       $confhash{$type}{$key}{'image'} = 
Line 11951  sub modify_quotas { Line 8279  sub modify_quotas {
                     if ($type eq 'textbooks') {                      if ($type eq 'textbooks') {
                         if ($env{'form.'.$type.'_addbook_image.filename'} ne '') {                          if ($env{'form.'.$type.'_addbook_image.filename'} ne '') {
                             my ($cdom,$cnum) = split(/_/,$newbook{$type});                              my ($cdom,$cnum) = split(/_/,$newbook{$type});
                             if (&Apache::lonnet::homeserver($cnum,$cdom) eq 'no_host') {                              my ($imageurl,$error) =
                                 $errors .= '<li><span class="LC_error">'.&mt('Image not saved: could not find textbook course').'</li>';                                  &process_textbook_image($r,$dom,$confname,$type.'_addbook_image',$cdom,$cnum,$type,
                             } else {                                                          $configuserok,$switchserver,$author_ok);
                                 my ($imageurl,$error) =                              if ($imageurl) {
                                     &process_textbook_image($r,$dom,$confname,$type.'_addbook_image',$cdom,$cnum,$type,                                  $confhash{$type}{$newbook{$type}}{'image'} = $imageurl;
                                                             $configuserok,$switchserver,$author_ok);                              }
                                 if ($imageurl) {                              if ($error) {
                                     $confhash{$type}{$newbook{$type}}{'image'} = $imageurl;                                  &Apache::lonnet::logthis($error);
                                 }                                  $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                                 if ($error) {  
                                     &Apache::lonnet::logthis($error);  
                                     $errors .= '<li><span class="LC_error">'.$error.'</span></li>';  
                                 }  
                             }                              }
                         }                          }
                     }                      }
Line 12043  sub modify_quotas { Line 8367  sub modify_quotas {
             }              }
             if ($env{'form.validationdc'}) {              if ($env{'form.validationdc'}) {
                 my $newval = $env{'form.validationdc'};                  my $newval = $env{'form.validationdc'};
                 my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);                  my %domcoords = &get_active_dcs($dom);
                 if (exists($domcoords{$newval})) {                  if (exists($domcoords{$newval})) {
                     $confhash{'validation'}{'dc'} = $newval;                      $confhash{'validation'}{'dc'} = $newval;
                 }                  }
Line 12067  sub modify_quotas { Line 8391  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'};
                 }                  }  
             } else {              } else {
                 if (ref($domconfig{'requestcourses'}) eq 'HASH') {                  if (ref($domconfig{'requestcourses'}) eq 'HASH') {
                     if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {                      if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
Line 12455  sub process_textbook_image { Line 8779  sub process_textbook_image {
         } elsif ($author_ok eq 'ok') {          } elsif ($author_ok eq 'ok') {
             my ($result,$imageurl) =              my ($result,$imageurl) =
                 &publishlogo($r,'upload',$caller,$dom,$confname,                  &publishlogo($r,'upload',$caller,$dom,$confname,
                              "$type/$cdom/$cnum/cover",$width,$height);                               "$type/$dom/$cnum/cover",$width,$height);
             if ($result eq 'ok') {              if ($result eq 'ok') {
                 $url = $imageurl;                  $url = $imageurl;
             } else {              } else {
Line 12473  sub process_textbook_image { Line 8797  sub process_textbook_image {
 sub modify_ltitools {  sub modify_ltitools {
     my ($r,$dom,$action,$lastactref,%domconfig) = @_;      my ($r,$dom,$action,$lastactref,%domconfig) = @_;
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
     my ($newid,@allpos,%changes,%confhash,%encconfig,$errors,$resulttext);      my ($newid,@allpos,%changes,%confhash,$errors,$resulttext);
     my $confname = $dom.'-domainconfig';      my $confname = $dom.'-domainconfig';
     my $servadm = $r->dir_config('lonAdmEMail');      my $servadm = $r->dir_config('lonAdmEMail');
     my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);      my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
Line 12483  sub modify_ltitools { Line 8807  sub modify_ltitools {
     map { $posslti{$_} = 1; } @ltiroles;      map { $posslti{$_} = 1; } @ltiroles;
     my @allfields = ('fullname','firstname','lastname','email','user','roles');      my @allfields = ('fullname','firstname','lastname','email','user','roles');
     map { $possfield{$_} = 1; } @allfields;      map { $possfield{$_} = 1; } @allfields;
     my %lt = &ltitools_names();      my %lt = &ltitools_names(); 
     if ($env{'form.ltitools_add'}) {      if ($env{'form.ltitools_add'}) {
         my $title = $env{'form.ltitools_add_title'};          my $title = $env{'form.ltitools_add_title'};
         $title =~ s/(`)/'/g;          $title =~ s/(`)/'/g;
Line 12495  sub modify_ltitools { Line 8819  sub modify_ltitools {
                 $allpos[$position] = $newid;                  $allpos[$position] = $newid;
             }              }
             $changes{$newid} = 1;              $changes{$newid} = 1;
             foreach my $item ('title','url','key','secret','lifetime') {              foreach my $item ('title','url','key','secret') {
                 $env{'form.ltitools_add_'.$item} =~ s/(`)/'/g;                  $env{'form.ltitools_add_'.$item} =~ s/(`)/'/g;
                 if ($item eq 'lifetime') {  
                     $env{'form.ltitools_add_'.$item} =~ s/[^\d.]//g;  
                 }  
                 if ($env{'form.ltitools_add_'.$item}) {                  if ($env{'form.ltitools_add_'.$item}) {
                     if (($item eq 'key') || ($item eq 'secret')) {                      $confhash{$newid}{$item} = $env{'form.ltitools_add_'.$item};
                         $encconfig{$newid}{$item} = $env{'form.ltitools_add_'.$item};  
                     } else {  
                         $confhash{$newid}{$item} = $env{'form.ltitools_add_'.$item};  
                     }  
                 }                  }
             }              }
             if ($env{'form.ltitools_add_version'} eq 'LTI-1p0') {              if ($env{'form.ltitools_add_version'} eq 'LTI-1p0') {
Line 12514  sub modify_ltitools { Line 8831  sub modify_ltitools {
             if ($env{'form.ltitools_add_msgtype'} eq 'basic-lti-launch-request') {              if ($env{'form.ltitools_add_msgtype'} eq 'basic-lti-launch-request') {
                 $confhash{$newid}{'msgtype'} = $env{'form.ltitools_add_msgtype'};                  $confhash{$newid}{'msgtype'} = $env{'form.ltitools_add_msgtype'};
             }              }
             if ($env{'form.ltitools_add_sigmethod'} eq 'HMAC-SHA256') {              foreach my $item ('width','height') {
                 $confhash{$newid}{'sigmethod'} = $env{'form.ltitools_add_sigmethod'};  
             } else {  
                 $confhash{$newid}{'sigmethod'} = 'HMAC-SHA1';  
             }  
             foreach my $item ('width','height','linktext','explanation') {  
                 $env{'form.ltitools_add_'.$item} =~ s/^\s+//;                  $env{'form.ltitools_add_'.$item} =~ s/^\s+//;
                 $env{'form.ltitools_add_'.$item} =~ s/\s+$//;                  $env{'form.ltitools_add_'.$item} =~ s/\s+$//;
                 if (($item eq 'width') || ($item eq 'height')) {                  if ($env{'form.ltitools_add_'.$item} =~ /^\d+$/) {
                     if ($env{'form.ltitools_add_'.$item} =~ /^\d+$/) {                      $confhash{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item};
                         $confhash{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item};  
                     }  
                 } else {  
                     if ($env{'form.ltitools_add_'.$item} ne '') {  
                         $confhash{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item};  
                     }  
                 }                  }
             }              }
             if ($env{'form.ltitools_add_target'} eq 'window') {              if ($env{'form.ltitools_add_target'} eq 'window') {
                 $confhash{$newid}{'display'}{'target'} = $env{'form.ltitools_add_target'};                  $confhash{$newid}{'display'}{'target'} = $env{'form.ltitools_add_target'};
             } elsif ($env{'form.ltitools_add_target'} eq 'tab') {  
                 $confhash{$newid}{'display'}{'target'} = $env{'form.ltitools_add_target'};  
             } else {              } else {
                 $confhash{$newid}{'display'}{'target'} = 'iframe';                  $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 '') {              if ($env{'form.ltitools_add_image.filename'} ne '') {
                 my ($imageurl,$error) =                  my ($imageurl,$error) =
                     &process_ltitools_image($r,$dom,$confname,'ltitools_add_image',$newid,                      &process_ltitools_image($r,$dom,$confname,'ltitools_add_image',$dom,
                                             $configuserok,$switchserver,$author_ok);                                              $configuserok,$switchserver,$author_ok);
                 if ($imageurl) {                  if ($imageurl) {
                     $confhash{$newid}{'image'} = $imageurl;                      $confhash{$newid}{'image'} = $imageurl;
Line 12560  sub modify_ltitools { Line 8869  sub modify_ltitools {
                             if (($choice ne '') && ($posslti{$choice})) {                              if (($choice ne '') && ($posslti{$choice})) {
                                 $confhash{$newid}{'roles'}{$role} = $choice;                                  $confhash{$newid}{'roles'}{$role} = $choice;
                                 if ($role eq 'cc') {                                  if ($role eq 'cc') {
                                     $confhash{$newid}{'roles'}{'co'} = $choice;                                      $confhash{$newid}{'roles'}{'co'} = $choice; 
                                 }                                  }
                             }                              }
                         }                          }
Line 12569  sub modify_ltitools { Line 8878  sub modify_ltitools {
                     }                      }
                 }                  }
             }              }
             if (ref($confhash{$newid}{'fields'}) eq 'HASH') {  
                 if ($confhash{$newid}{'fields'}{'user'}) {  
                     if ($env{'form.ltitools_userincdom_add'}) {  
                         $confhash{$newid}{'incdom'} = 1;  
                     }  
                 }  
             }  
             my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig');              my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig');
             foreach my $item (@courseconfig) {              foreach my $item (@courseconfig) {
                 $confhash{$newid}{'crsconf'}{$item} = 1;                  $confhash{$newid}{'crsconf'}{$item} = 1;
Line 12588  sub modify_ltitools { Line 8890  sub modify_ltitools {
                 $confhash{$newid}{'custom'}{$name} = $value;                  $confhash{$newid}{'custom'}{$name} = $value;
             }              }
         } else {          } else {
             my $error = &mt('Failed to acquire unique ID for new external tool');              my $error = &mt('Failed to acquire unique ID for new external tool');   
             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';              $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
         }          }
     }      }
Line 12602  sub modify_ltitools { Line 8904  sub modify_ltitools {
         my @newcustom = &Apache::loncommon::get_env_multiple('form.ltitools_customadd');          my @newcustom = &Apache::loncommon::get_env_multiple('form.ltitools_customadd');
         if (@newcustom) {          if (@newcustom) {
             map { $customadds{$_} = 1; } @newcustom;              map { $customadds{$_} = 1; } @newcustom;
         }          } 
         my %imgdeletions;          my %imgdeletions;
         my @todeleteimages = &Apache::loncommon::get_env_multiple('form.ltitools_image_del');          my @todeleteimages = &Apache::loncommon::get_env_multiple('form.ltitools_image_del');
         if (@todeleteimages) {          if (@todeleteimages) {
Line 12611  sub modify_ltitools { Line 8913  sub modify_ltitools {
         my $maxnum = $env{'form.ltitools_maxnum'};          my $maxnum = $env{'form.ltitools_maxnum'};
         for (my $i=0; $i<=$maxnum; $i++) {          for (my $i=0; $i<=$maxnum; $i++) {
             my $itemid = $env{'form.ltitools_id_'.$i};              my $itemid = $env{'form.ltitools_id_'.$i};
             $itemid =~ s/\D+//g;  
             if (ref($domconfig{$action}{$itemid}) eq 'HASH') {              if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
                 if ($deletions{$itemid}) {                  if ($deletions{$itemid}) {
                     if ($domconfig{$action}{$itemid}{'image'}) {                      if ($domconfig{$action}{$itemid}{'image'}) {
Line 12622  sub modify_ltitools { Line 8923  sub modify_ltitools {
                 } else {                  } else {
                     my $newpos = $env{'form.ltitools_'.$itemid};                      my $newpos = $env{'form.ltitools_'.$itemid};
                     $newpos =~ s/\D+//g;                      $newpos =~ s/\D+//g;
                     foreach my $item ('title','url','lifetime') {                      foreach my $item ('title','url','key','secret') {
                         $confhash{$itemid}{$item} = $env{'form.ltitools_'.$item.'_'.$i};                          $confhash{$itemid}{$item} = $env{'form.ltitools_'.$item.'_'.$i};
                         if ($domconfig{$action}{$itemid}{$item} ne $confhash{$itemid}{$item}) {                          if ($domconfig{$action}{$itemid}{$item} ne $confhash{$itemid}{$item}) {
                             $changes{$itemid} = 1;                              $changes{$itemid} = 1;
                         }                          }
                     }                      }
                     foreach my $item ('key','secret') {  
                         $encconfig{$itemid}{$item} = $env{'form.ltitools_'.$item.'_'.$i};  
                         if ($domconfig{$action}{$itemid}{$item} ne $encconfig{$itemid}{$item}) {  
                             $changes{$itemid} = 1;  
                         }  
                     }  
                     if ($env{'form.ltitools_version_'.$i} eq 'LTI-1p0') {                      if ($env{'form.ltitools_version_'.$i} eq 'LTI-1p0') {
                         $confhash{$itemid}{'version'} = $env{'form.ltitools_version_'.$i};                          $confhash{$itemid}{'version'} = $env{'form.ltitools_version_'.$i};
                     }                      }
                     if ($env{'form.ltitools_msgtype_'.$i} eq 'basic-lti-launch-request') {                      if ($env{'form.ltitools_msgtype_'.$i} eq 'basic-lti-launch-request') {
                         $confhash{$itemid}{'msgtype'} = $env{'form.ltitools_msgtype_'.$i};                          $confhash{$itemid}{'msgtype'} = $env{'form.ltitools_msgtype_'.$i};
                     }                      }
                     if ($env{'form.ltitools_sigmethod_'.$i} eq 'HMAC-SHA256') {  
                         $confhash{$itemid}{'sigmethod'} = $env{'form.ltitools_sigmethod_'.$i};  
                     } else {  
                         $confhash{$itemid}{'sigmethod'} = 'HMAC-SHA1';  
                     }  
                     if ($domconfig{$action}{$itemid}{'sigmethod'} eq '') {  
                         if ($confhash{$itemid}{'sigmethod'} ne 'HMAC-SHA1') {  
                             $changes{$itemid} = 1;  
                         }  
                     } elsif ($domconfig{$action}{$itemid}{'sigmethod'} ne $confhash{$itemid}{'sigmethod'}) {  
                         $changes{$itemid} = 1;  
                     }  
                     foreach my $size ('width','height') {                      foreach my $size ('width','height') {
                         $env{'form.ltitools_'.$size.'_'.$i} =~ s/^\s+//;                          $env{'form.ltitools_'.$size.'_'.$i} =~ s/^\s+//;
                         $env{'form.ltitools_'.$size.'_'.$i} =~ s/\s+$//;                          $env{'form.ltitools_'.$size.'_'.$i} =~ s/\s+$//;
Line 12664  sub modify_ltitools { Line 8947  sub modify_ltitools {
                             } else {                              } else {
                                 $changes{$itemid} = 1;                                  $changes{$itemid} = 1;
                             }                              }
                         } elsif (ref($domconfig{$action}{$itemid}{'display'}) eq 'HASH') {  
                             if ($domconfig{$action}{$itemid}{'display'}{$size} ne '') {  
                                 $changes{$itemid} = 1;  
                             }  
                         }  
                     }  
                     foreach my $item ('linktext','explanation') {  
                         $env{'form.ltitools_'.$item.'_'.$i} =~ s/^\s+//;  
                         $env{'form.ltitools_'.$item.'_'.$i} =~ s/\s+$//;  
                         if ($env{'form.ltitools_'.$item.'_'.$i} ne '') {  
                             $confhash{$itemid}{'display'}{$item} = $env{'form.ltitools_'.$item.'_'.$i};  
                             if (ref($domconfig{$action}{$itemid}{'display'}) eq 'HASH') {  
                                 if ($domconfig{$action}{$itemid}{'display'}{$item} ne $confhash{$itemid}{'display'}{$item}) {  
                                     $changes{$itemid} = 1;  
                                 }  
                             } else {  
                                 $changes{$itemid} = 1;  
                             }  
                         } elsif (ref($domconfig{$action}{$itemid}{'display'}) eq 'HASH') {  
                             if ($domconfig{$action}{$itemid}{'display'}{$item} ne '') {  
                                 $changes{$itemid} = 1;  
                             }  
                         }                          }
                     }                      }
                     if ($env{'form.ltitools_target_'.$i} eq 'window') {                      if ($env{'form.ltitools_target_'.$i} eq 'window') {
                         $confhash{$itemid}{'display'}{'target'} = $env{'form.ltitools_target_'.$i};                          $confhash{$itemid}{'display'}{'target'} = $env{'form.ltitools_target_'.$i};
                     } elsif ($env{'form.ltitools_target_'.$i} eq 'tab') {  
                         $confhash{$itemid}{'display'}{'target'} = $env{'form.ltitools_target_'.$i};  
                     } else {                      } else {
                         $confhash{$itemid}{'display'}{'target'} = 'iframe';                          $confhash{$itemid}{'display'}{'target'} = 'iframe';
                     }                      }
Line 12702  sub modify_ltitools { Line 8961  sub modify_ltitools {
                     } else {                      } else {
                         $changes{$itemid} = 1;                          $changes{$itemid} = 1;
                     }                      }
                       foreach my $extra ('passback','roster') {
                           if ($env{'form.ltitools_'.$extra.'_'.$i}) {
                               $confhash{$itemid}{$extra} = 1;
                           }
                           if ($domconfig{$action}{$itemid}{$extra} ne $confhash{$itemid}{$extra}) {
                               $changes{$itemid} = 1;
                           }
                       }
                     my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig_'.$i);                      my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig_'.$i);
                     foreach my $item ('label','title','target','linktext','explanation','append') {                      foreach my $item ('label','title','target') {
                         if (grep(/^\Q$item\E$/,@courseconfig)) {                          if (grep(/^\Q$item\E$/,@courseconfig)) {
                             $confhash{$itemid}{'crsconf'}{$item} = 1;                              $confhash{$itemid}{'crsconf'}{$item} = 1;
                             if (ref($domconfig{$action}{$itemid}{'crsconf'}) eq 'HASH') {                              if (ref($domconfig{$action}{$itemid}{'crsconf'}) eq 'HASH') {
Line 12747  sub modify_ltitools { Line 9014  sub modify_ltitools {
                             }                              }
                         }                          }
                     }                      }
                     if (ref($confhash{$itemid}{'fields'}) eq 'HASH') {  
                         if ($confhash{$itemid}{'fields'}{'user'}) {  
                             if ($env{'form.ltitools_userincdom_'.$i}) {  
                                 $confhash{$itemid}{'incdom'} = 1;  
                             }  
                             if ($domconfig{$action}{$itemid}{'incdom'} ne $confhash{$itemid}{'incdom'}) {  
                                 $changes{$itemid} = 1;  
                             }  
                         }  
                     }  
                     $allpos[$newpos] = $itemid;                      $allpos[$newpos] = $itemid;
                 }                  }
                 if ($imgdeletions{$itemid}) {                  if ($imgdeletions{$itemid}) {
Line 12793  sub modify_ltitools { Line 9050  sub modify_ltitools {
                     }                      }
                 }                  }
                 my %customdels;                  my %customdels;
                 my @customdeletions = &Apache::loncommon::get_env_multiple('form.ltitools_customdel_'.$i);                  my @customdeletions = &Apache::loncommon::get_env_multiple('form.ltitools_customdel_'.$i); 
                 if (@customdeletions) {                  if (@customdeletions) {
                     $changes{$itemid} = 1;                      $changes{$itemid} = 1;
                 }                  }
Line 12802  sub modify_ltitools { Line 9059  sub modify_ltitools {
                     foreach my $key (keys(%{$domconfig{$action}{$itemid}{'custom'}})) {                      foreach my $key (keys(%{$domconfig{$action}{$itemid}{'custom'}})) {
                         unless ($customdels{$key}) {                          unless ($customdels{$key}) {
                             if ($env{'form.ltitools_customval_'.$key.'_'.$i} ne '') {                              if ($env{'form.ltitools_customval_'.$key.'_'.$i} ne '') {
                                 $confhash{$itemid}{'custom'}{$key} = $env{'form.ltitools_customval_'.$key.'_'.$i};                                  $confhash{$itemid}{'custom'}{$key} = $env{'form.ltitools_customval_'.$key.'_'.$i}; 
                             }                              }
                             if ($domconfig{$action}{$itemid}{'custom'}{$key} ne $env{'form.ltitools_customval_'.$key.'_'.$i}) {                              if ($domconfig{$action}{$itemid}{'custom'}{$key} ne $env{'form.ltitools_customval_'.$key.'_'.$i}) {
                                 $changes{$itemid} = 1;                                  $changes{$itemid} = 1;
Line 12852  sub modify_ltitools { Line 9109  sub modify_ltitools {
     my $putresult = &Apache::lonnet::put_dom('configuration',\%ltitoolshash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%ltitoolshash,
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         my %ltienchash = (  
                              $action => { %encconfig }  
                          );  
         &Apache::lonnet::put_dom('encconfig',\%ltienchash,$dom,undef,1);  
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             my $cachetime = 24*60*60;              my $cachetime = 24*60*60;
             my %ltiall = %confhash;              &Apache::lonnet::do_cache_new('ltitools',$dom,\%confhash,$cachetime);
             foreach my $id (keys(%ltiall)) {  
                 if (ref($encconfig{$id}) eq 'HASH') {  
                     foreach my $item ('key','secret') {  
                         $ltiall{$id}{$item} = $encconfig{$id}{$item};  
                     }  
                 }  
             }  
             &Apache::lonnet::do_cache_new('ltitools',$dom,\%ltiall,$cachetime);  
             if (ref($lastactref) eq 'HASH') {              if (ref($lastactref) eq 'HASH') {
                 $lastactref->{'ltitools'} = 1;                  $lastactref->{'ltitools'} = 1;
             }              }
Line 12877  sub modify_ltitools { Line 9122  sub modify_ltitools {
                 $bynum{$position} = $itemid;                  $bynum{$position} = $itemid;
             }              }
             foreach my $pos (sort { $a <=> $b } keys(%bynum)) {              foreach my $pos (sort { $a <=> $b } keys(%bynum)) {
                 my $itemid = $bynum{$pos};                  my $itemid = $bynum{$pos}; 
                 if (ref($confhash{$itemid}) ne 'HASH') {                  if (ref($confhash{$itemid}) ne 'HASH') {
                     $resulttext .= '<li>'.&mt('Deleted: [_1]',$changes{$itemid}).'</li>';                      $resulttext .= '<li>'.&mt('Deleted: [_1]',$changes{$itemid}).'</li>';
                 } else {                  } else {
Line 12890  sub modify_ltitools { Line 9135  sub modify_ltitools {
                     $resulttext .= '</li><ul>';                      $resulttext .= '</li><ul>';
                     my $position = $pos + 1;                      my $position = $pos + 1;
                     $resulttext .= '<li>'.&mt('Order: [_1]',$position).'</li>';                      $resulttext .= '<li>'.&mt('Order: [_1]',$position).'</li>';
                     foreach my $item ('version','msgtype','sigmethod','url','lifetime') {                      foreach my $item ('version','msgtype','url','key') {
                         if ($confhash{$itemid}{$item} ne '') {                          if ($confhash{$itemid}{$item} ne '') {
                             $resulttext .= '<li>'.$lt{$item}.':&nbsp;'.$confhash{$itemid}{$item}.'</li>';                              $resulttext .= '<li>'.$lt{$item}.':&nbsp;'.$confhash{$itemid}{$item}.'</li>';
                         }                          }
                     }                      }
                     if ($encconfig{$itemid}{'key'} ne '') {                      if ($confhash{$itemid}{'secret'} ne '') {
                         $resulttext .= '<li>'.$lt{'key'}.':&nbsp;'.$encconfig{$itemid}{'key'}.'</li>';  
                     }  
                     if ($encconfig{$itemid}{'secret'} ne '') {  
                         $resulttext .= '<li>'.$lt{'secret'}.':&nbsp;';                          $resulttext .= '<li>'.$lt{'secret'}.':&nbsp;';
                         my $num = length($encconfig{$itemid}{'secret'});                          my $num = length($confhash{$itemid}{'secret'});
                         $resulttext .= ('*'x$num).'</li>';                          $resulttext .= ('*'x$num).'</li>';
                     }                      }
                     $resulttext .= '<li>'.&mt('Configurable in course:');                      $resulttext .= '<li>'.&mt('Configurable in course:');
                     my @possconfig = ('label','title','target','linktext','explanation','append');                      my @possconfig = ('label','title','target');
                     my $numconfig = 0;                      my $numconfig = 0; 
                     if (ref($confhash{$itemid}{'crsconf'}) eq 'HASH') {                      if (ref($confhash{$itemid}{'crsconf'}) eq 'HASH') { 
                         foreach my $item (@possconfig) {                          foreach my $item (@possconfig) {
                             if ($confhash{$itemid}{'crsconf'}{$item}) {                              if ($confhash{$itemid}{'crsconf'}{$item}) {
                                 $numconfig ++;                                  $numconfig ++;
                                 $resulttext .= ' "'.$lt{'crs'.$item}.'"';                                  $resulttext .= ' '.$lt{'crs'.$item};
                             }                              }
                         }                          }
                     }                      }
Line 12918  sub modify_ltitools { Line 9160  sub modify_ltitools {
                         $resulttext .= &mt('None');                          $resulttext .= &mt('None');
                     }                      }
                     $resulttext .= '</li>';                      $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') {                      if (ref($confhash{$itemid}{'display'}) eq 'HASH') {
                         my $displaylist;                          my $displaylist;
                         if ($confhash{$itemid}{'display'}{'target'}) {                          if ($confhash{$itemid}{'display'}{'target'}) {
                             $displaylist = &mt('Display target').':&nbsp;'.                              $displaylist = &mt('Display target').':&nbsp;'.
                                            $confhash{$itemid}{'display'}{'target'}.',';                                             $confhash{$itemid}{'display'}{'target'}.',';
                         }                          }
                         foreach my $size ('width','height') {                          foreach my $size ('width','height') { 
                             if ($confhash{$itemid}{'display'}{$size}) {                              if ($confhash{$itemid}{'display'}{$size}) {
                                 $displaylist .= ('&nbsp;'x2).$lt{$size}.':&nbsp;'.                                  $displaylist .= ('&nbsp;'x2).$lt{$size}.':&nbsp;'.
                                                 $confhash{$itemid}{'display'}{$size}.',';                                                  $confhash{$itemid}{'display'}{$size}.',';
Line 12934  sub modify_ltitools { Line 9185  sub modify_ltitools {
                             $displaylist =~ s/,$//;                              $displaylist =~ s/,$//;
                             $resulttext .= '<li>'.$displaylist.'</li>';                              $resulttext .= '<li>'.$displaylist.'</li>';
                         }                          }
                         foreach my $item ('linktext','explanation') {                      } 
                             if ($confhash{$itemid}{'display'}{$item}) {  
                                 $resulttext .= '<li>'.$lt{$item}.':&nbsp;'.$confhash{$itemid}{'display'}{$item}.'</li>';  
                             }  
                         }  
                     }  
                     if (ref($confhash{$itemid}{'fields'}) eq 'HASH') {                      if (ref($confhash{$itemid}{'fields'}) eq 'HASH') {
                         my $fieldlist;                          my $fieldlist;
                         foreach my $field (@allfields) {                          foreach my $field (@allfields) {
Line 12949  sub modify_ltitools { Line 9195  sub modify_ltitools {
                         }                          }
                         if ($fieldlist) {                          if ($fieldlist) {
                             $fieldlist =~ s/,$//;                              $fieldlist =~ s/,$//;
                             if ($confhash{$itemid}{'fields'}{'user'}) {  
                                 if ($confhash{$itemid}{'incdom'}) {  
                                     $fieldlist .= ' ('.&mt('username:domain').')';  
                                 } else {  
                                     $fieldlist .= ' ('.&mt('username').')';  
                                 }  
                             }  
                             $resulttext .= '<li>'.&mt('Data sent').':'.$fieldlist.'</li>';                              $resulttext .= '<li>'.&mt('Data sent').':'.$fieldlist.'</li>';
                         }                          }
                     }                      }
Line 12968  sub modify_ltitools { Line 9207  sub modify_ltitools {
                             }                              }
                         }                          }
                         if ($rolemaps) {                          if ($rolemaps) {
                             $rolemaps =~ s/,$//;                              $rolemaps =~ s/,$//; 
                             $resulttext .= '<li>'.&mt('Role mapping:').$rolemaps.'</li>';                              $resulttext .= '<li>'.&mt('Role mapping:').$rolemaps.'</li>';
                         }                          }
                     }                      }
Line 12977  sub modify_ltitools { Line 9216  sub modify_ltitools {
                         if (keys(%{$confhash{$itemid}{'custom'}})) {                          if (keys(%{$confhash{$itemid}{'custom'}})) {
                             foreach my $key (sort(keys(%{$confhash{$itemid}{'custom'}}))) {                              foreach my $key (sort(keys(%{$confhash{$itemid}{'custom'}}))) {
                                 $customlist .= $key.':'.$confhash{$itemid}{'custom'}{$key}.('&nbsp;'x2);                                  $customlist .= $key.':'.$confhash{$itemid}{'custom'}{$key}.('&nbsp;'x2);
                             }                              } 
                         }                          }
                         if ($customlist) {                          if ($customlist) {
                             $resulttext .= '<li>'.&mt('Custom items').': '.$customlist.'</li>';                              $resulttext .= '<li>'.&mt('Custom items').':'.$customlist.'</li>';
                         }                          }
                     }                      } 
                     $resulttext .= '</ul></li>';                      $resulttext .= '</ul></li>';
                 }                  }
             }              }
Line 13043  sub get_ltitools_id { Line 9282  sub get_ltitools_id {
     my $tries = 0;      my $tries = 0;
     my $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);      my $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
     my ($id,$error);      my ($id,$error);
    
     while (($gotlock ne 'ok') && ($tries<10)) {      while (($gotlock ne 'ok') && ($tries<10)) {
         $tries ++;          $tries ++;
         sleep (0.1);          sleep (0.1);
Line 13076  sub get_ltitools_id { Line 9315  sub get_ltitools_id {
     return ($id,$error);      return ($id,$error);
 }  }
   
 sub modify_lti {  
     my ($r,$dom,$action,$lastactref,%domconfig) = @_;  
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);  
     my (%encconfig,$errors,$resulttext);  
   
     my (%currltisec,%secchanges,%newltisec,%newltienc,%keyset,%newkeyset);  
     $newltisec{'private'}{'keys'} = [];  
     $newltisec{'encrypt'} = {};  
     $newltisec{'rules'} = {};  
     $newltisec{'linkprot'} = {};  
     if (ref($domconfig{'ltisec'}) eq 'HASH') {  
         %currltisec = %{$domconfig{'ltisec'}};  
         if (ref($currltisec{'linkprot'}) eq 'HASH') {  
             foreach my $id (keys(%{$currltisec{'linkprot'}})) {  
                 unless ($id =~ /^\d+$/) {  
                     delete($currltisec{'linkprot'}{$id});  
                 }  
             }  
         }  
         if (ref($currltisec{'private'}) eq 'HASH') {  
             if (ref($currltisec{'private'}{'keys'}) eq 'ARRAY') {  
                 $newltisec{'private'}{'keys'} = $currltisec{'private'}{'keys'};  
                 map { $keyset{$_} = 1; } @{$currltisec{'private'}{'keys'}};  
             }  
         }  
     }  
     foreach my $item ('crs','dom') {  
         my $formelement = 'form.ltisec_'.$item.'linkprot';  
         if ($env{$formelement}) {  
             $newltisec{'encrypt'}{$item} = 1;  
             if (ref($currltisec{'encrypt'}) eq 'HASH') {  
                 unless ($currltisec{'encrypt'}{$item}) {  
                     $secchanges{'encrypt'} = 1;  
                 }  
             } else {  
                 $secchanges{'encrypt'} = 1;  
             }  
         } elsif (ref($currltisec{'encrypt'}) eq 'HASH') {  
             if ($currltisec{'encrypt'}{$item}) {  
                 $secchanges{'encrypt'} = 1;  
             }  
         }  
     }  
     unless (exists($currltisec{'rules'})) {  
         $currltisec{'rules'} = {};  
     }  
     &password_rule_changes('secrets',$newltisec{'rules'},$currltisec{'rules'},\%secchanges);  
   
     my @ids=&Apache::lonnet::current_machine_ids();  
     my %servers = &Apache::lonnet::get_servers($dom,'library');  
   
     foreach my $hostid (keys(%servers)) {  
         if (($hostid ne '') && (grep(/^\Q$hostid\E$/,@ids))) {  
             my $newkey;  
             my $keyitem = 'form.ltisec_privkey_'.$hostid;  
             if (exists($env{$keyitem})) {  
                 $env{$keyitem} =~ s/(`)/'/g;  
                 if ($keyset{$hostid}) {  
                     if ($env{'form.ltisec_changeprivkey_'.$hostid}) {  
                         if ($env{$keyitem} ne '') {  
                             $secchanges{'private'} = 1;  
                             $newkeyset{$hostid} = $env{$keyitem};  
                         }  
                     }  
                 } elsif ($env{$keyitem} ne '') {  
                     unless (grep(/^\Q$hostid\E$/,@{$newltisec{'private'}{'keys'}})) {  
                         push(@{$newltisec{'private'}{'keys'}},$hostid);  
                     }  
                     $secchanges{'private'} = 1;  
                     $newkeyset{$hostid} = $env{$keyitem};  
                 }  
             }  
         }  
     }  
   
     my (%linkprotchg,$linkprotoutput,$is_home);  
     my $proterror = &Apache::courseprefs::process_linkprot($dom,'',$currltisec{'linkprot'},  
                                                            \%linkprotchg,'domain');  
     my $home = &Apache::lonnet::domain($dom,'primary');  
     unless (($home eq 'no_host') || ($home eq '')) {  
         my @ids=&Apache::lonnet::current_machine_ids();  
         foreach my $id (@ids) { if ($id eq $home) { $is_home=1; } }  
     }  
   
     if (keys(%linkprotchg)) {  
         $secchanges{'linkprot'} = 1;  
         my %oldlinkprot;  
         if (ref($currltisec{'linkprot'}) eq 'HASH') {  
             %oldlinkprot = %{$currltisec{'linkprot'}};  
         }  
         foreach my $id (keys(%linkprotchg)) {  
             if (ref($linkprotchg{$id}) eq 'HASH') {  
                 foreach my $inner (keys(%{$linkprotchg{$id}})) {  
                     if (($inner eq 'secret') || ($inner eq 'key')) {  
                         if ($is_home) {  
                             $newltienc{$id}{$inner} = $linkprotchg{$id}{$inner};  
                         }  
                     }  
                 }  
             } else {  
                 $newltisec{'linkprot'}{$id} = $linkprotchg{$id};  
             }  
         }  
         $linkprotoutput = &Apache::courseprefs::store_linkprot($dom,'','domain',\%linkprotchg,\%oldlinkprot);  
         if (keys(%linkprotchg)) {  
             %{$newltisec{'linkprot'}} = %linkprotchg;  
         }  
     }  
     if (ref($currltisec{'linkprot'}) eq 'HASH') {  
         foreach my $id (%{$currltisec{'linkprot'}}) {  
             next if ($id !~ /^\d+$/);  
             unless (exists($linkprotchg{$id})) {  
                 if (ref($currltisec{'linkprot'}{$id}) eq 'HASH') {  
                     foreach my $inner (keys(%{$currltisec{'linkprot'}{$id}})) {  
                         if (($inner eq 'secret') || ($inner eq 'key')) {  
                             if ($is_home) {  
                                 $newltienc{$id}{$inner} = $currltisec{'linkprot'}{$id}{$inner};  
                             }  
                         } else {  
                             $newltisec{'linkprot'}{$id}{$inner} = $currltisec{'linkprot'}{$id}{$inner};  
                         }  
                     }  
                 } else {  
                     $newltisec{'linkprot'}{$id} = $currltisec{'linkprot'}{$id};  
                 }  
             }  
         }  
     }  
     if ($proterror) {  
         $errors .= '<li>'.$proterror.'</li>';  
     }  
   
     my ($putresult,%keystore);  
     if (keys(%secchanges)) {  
         my %ltienchash;  
         my %ltihash = (  
                           'ltisec' => { %newltisec }  
                       );  
         $putresult = &Apache::lonnet::put_dom('configuration',\%ltihash,$dom);  
         if ($putresult eq 'ok') {  
             if ($secchanges{'private'}) {  
                 my $who = &escape($env{'user.name'}.':'.$env{'user.domain'});  
                 foreach my $hostid (keys(%newkeyset)) {  
                     my $storehash = {  
                                        key => $newkeyset{$hostid},  
                                        who => $env{'user.name'}.':'.$env{'user.domain'},  
                                     };  
                     $keystore{$hostid} = &Apache::lonnet::store_dom($storehash,'lti','private',  
                                                                     $dom,$hostid);  
                 }  
             }  
             if (ref($lastactref) eq 'HASH') {  
                 if (($secchanges{'encrypt'}) || ($secchanges{'private'})) {  
                     $lastactref->{'domdefaults'} = 1;  
                 }  
             }  
             if (($secchanges{'linkprot'}) && ($is_home)) {  
                 my %ltienchash = (  
                                      'linkprot' =>  { %newltienc }  
                                  );  
                 &Apache::lonnet::put_dom('encconfig',\%ltienchash,$dom,undef,1);  
             }  
         }  
     } else {  
         return &mt('No changes made.');  
     }  
     if ($putresult eq 'ok') {  
         $resulttext = &mt('Changes made:').'<ul>';  
         foreach my $item (keys(%secchanges)) {  
             if ($item eq 'encrypt') {  
                 my %encrypted = (  
                           crs  => {  
                                     on => &mt('Encryption of stored link protection secrets defined in courses enabled'),  
                                     off => &mt('Encryption of stored link protection secrets defined in courses disabled'),  
                                   },  
                           dom => {  
                                    on => &mt('Encryption of stored link protection secrets defined in domain enabled'),  
                                    off => &mt('Encryption of stored link protection secrets defined in domain disabled'),  
                                  },  
                 );  
                 foreach my $type ('crs','dom') {  
                     my $shown = $encrypted{$type}{'off'};  
                     if (ref($newltisec{$item}) eq 'HASH') {  
                         if ($newltisec{$item}{$type}) {  
                             $shown = $encrypted{$type}{'on'};  
                         }  
                     }  
                     $resulttext .= '<li>'.$shown.'</li>';  
                 }  
             } elsif ($item eq 'rules') {  
                 my %titles = &Apache::lonlocal::texthash(  
                                   min   => 'Minimum password length',  
                                   max   => 'Maximum password length',  
                                   chars => 'Required characters',  
                 );  
                 foreach my $rule ('min','max') {  
                     if ($newltisec{rules}{$rule} eq '') {  
                         if ($rule eq 'min') {  
                             $resulttext .= '<li>'.&mt('[_1] not set.',$titles{$rule});  
                                            ' '.&mt('Default of [_1] will be used',  
                                                        $Apache::lonnet::passwdmin).'</li>';  
                         } else {  
                             $resulttext .= '<li>'.&mt('[_1] set to none',$titles{$rule}).'</li>';  
                         }  
                     } else {  
                         $resulttext .= '<li>'.&mt('[_1] set to [_2]',$titles{$rule},$newltisec{rules}{$rule}).'</li>';  
                     }  
                 }  
                 if (ref($newltisec{'rules'}{'chars'}) eq 'ARRAY') {  
                     if (@{$newltisec{'rules'}{'chars'}} > 0) {  
                         my %rulenames = &Apache::lonlocal::texthash(  
                                             uc => 'At least one upper case letter',  
                                             lc => 'At least one lower case letter',  
                                             num => 'At least one number',  
                                             spec => 'At least one non-alphanumeric',  
                                             );  
                         my $needed = '<ul><li>'.  
                                      join('</li><li>',map {$rulenames{$_} } @{$newltisec{'rules'}{'chars'}}).  
                                      '</li></ul>';  
                         $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$titles{'chars'},$needed).'</li>';  
                     } else {  
                         $resulttext .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';  
                     }  
                 } else {  
                     $resulttext .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';  
                 }  
             } elsif ($item eq 'private') {  
                 if (keys(%newkeyset)) {  
                     foreach my $hostid (sort(keys(%newkeyset))) {  
                         if ($keystore{$hostid} eq 'ok') {  
                             $resulttext .= '<li>'.&mt('Encryption key for storage of shared secrets saved for [_1]',$hostid).'</li>';  
                         }  
                     }  
                 }  
             } elsif ($item eq 'linkprot') {  
                 $resulttext .= $linkprotoutput;  
             }  
         }  
         $resulttext .= '</ul>';  
     } 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 modify_autoenroll {  sub modify_autoenroll {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,%changes);      my ($resulttext,%changes);
Line 13338  sub modify_autoenroll { Line 9328  sub modify_autoenroll {
     my %title = ( run => 'Auto-enrollment active',      my %title = ( run => 'Auto-enrollment active',
                   sender => 'Sender for notification messages',                    sender => 'Sender for notification messages',
                   coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)',                    coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)',
                   autofailsafe => 'Failsafe for no drops if institutional data missing for a section');                    failsafe => 'Failsafe for no drops if institutional data missing for a section');
     my @offon = ('off','on');      my @offon = ('off','on');
     my $sender_uname = $env{'form.sender_uname'};      my $sender_uname = $env{'form.sender_uname'};
     my $sender_domain = $env{'form.sender_domain'};      my $sender_domain = $env{'form.sender_domain'};
Line 13348  sub modify_autoenroll { Line 9338  sub modify_autoenroll {
         $sender_domain = '';          $sender_domain = '';
     }      }
     my $coowners = $env{'form.autoassign_coowners'};      my $coowners = $env{'form.autoassign_coowners'};
     my $autofailsafe = $env{'form.autoenroll_autofailsafe'};  
     $autofailsafe =~ s{^\s+|\s+$}{}g;  
     if ($autofailsafe =~ /\D/) {  
         undef($autofailsafe);  
     }  
     my $failsafe = $env{'form.autoenroll_failsafe'};      my $failsafe = $env{'form.autoenroll_failsafe'};
     unless (($failsafe eq 'zero') || ($failsafe eq 'any')) {      $failsafe =~ s{^\s+|\s+$}{}g;
         $failsafe = 'off';      if ($failsafe =~ /\D/) {
         undef($autofailsafe);          undef($failsafe);
     }      }
     my %autoenrollhash =  (      my %autoenrollhash =  (
                        autoenroll => { 'run' => $env{'form.autoenroll_run'},                         autoenroll => { 'run' => $env{'form.autoenroll_run'},
                                        'sender_uname' => $sender_uname,                                         'sender_uname' => $sender_uname,
                                        'sender_domain' => $sender_domain,                                         'sender_domain' => $sender_domain,
                                        'co-owners' => $coowners,                                         'co-owners' => $coowners,
                                        'autofailsafe' => $autofailsafe,                                         'autofailsafe' => $failsafe,
                                        'failsafe' => $failsafe,  
                                 }                                  }
                      );                       );
     my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,
Line 13392  sub modify_autoenroll { Line 9376  sub modify_autoenroll {
         } elsif ($coowners) {          } elsif ($coowners) {
             $changes{'coowners'} = 1;              $changes{'coowners'} = 1;
         }          }
         if ($currautoenroll{'autofailsafe'} ne $autofailsafe) {          if ($currautoenroll{'autofailsafe'} ne $failsafe) {
             $changes{'autofailsafe'} = 1;              $changes{'autofailsafe'} = 1;
         }          }
         if ($currautoenroll{'failsafe'} ne $failsafe) {  
             $changes{'failsafe'} = 1;  
         }  
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if ($changes{'run'}) {              if ($changes{'run'}) {
Line 13418  sub modify_autoenroll { Line 9399  sub modify_autoenroll {
                 }                  }
             }              }
             if ($changes{'autofailsafe'}) {              if ($changes{'autofailsafe'}) {
                 if ($autofailsafe ne '') {                  if ($failsafe ne '') {
                     $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section set to: [_1]',$autofailsafe).'</li>';                      $resulttext .= '<li>'.&mt("$title{'failsafe'} set to [_1]",$failsafe).'</li>';
                 } else {                  } else {
                     $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section not in use').'</li>';                      $resulttext .= '<li>'.&mt("$title{'failsafe'} deleted");
                 }                  }
             }  
             if ($changes{'failsafe'}) {  
                 if ($failsafe eq 'off') {  
                     unless ($changes{'autofailsafe'}) {  
                         $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section not in use').'</li>';  
                     }  
                 } elsif ($failsafe eq 'zero') {  
                     $resulttext .= '<li>'.&mt('Failsafe applies if retrieved section enrollment is zero').'</li>';  
                 } else {  
                     $resulttext .= '<li>'.&mt('Failsafe applies if retrieved section enrollment is zero or greater').'</li>';  
                 }  
             }  
             if (($changes{'autofailsafe'}) || ($changes{'failsafe'})) {  
                 &Apache::lonnet::get_domain_defaults($dom,1);                  &Apache::lonnet::get_domain_defaults($dom,1);
                 if (ref($lastactref) eq 'HASH') {                  if (ref($lastactref) eq 'HASH') {
                     $lastactref->{'domdefaults'} = 1;                      $lastactref->{'domdefaults'} = 1;
Line 13462  sub modify_autoupdate { Line 9430  sub modify_autoupdate {
     }      }
     my @offon = ('off','on');      my @offon = ('off','on');
     my %title = &Apache::lonlocal::texthash (      my %title = &Apache::lonlocal::texthash (
                     run        => 'Auto-update:',                     run => 'Auto-update:',
                     classlists => 'Updates to user information in classlists?',                     classlists => 'Updates to user information in classlists?'
                     unexpired  => 'Skip updates for users without active or future roles?',  
                     lastactive => 'Skip updates for inactive users?',  
                 );                  );
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);      my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
     my %fieldtitles = &Apache::lonlocal::texthash (      my %fieldtitles = &Apache::lonlocal::texthash (
Line 13509  sub modify_autoupdate { Line 9475  sub modify_autoupdate {
     my %updatehash = (      my %updatehash = (
                       autoupdate => { run => $env{'form.autoupdate_run'},                        autoupdate => { run => $env{'form.autoupdate_run'},
                                       classlists => $env{'form.classlists'},                                        classlists => $env{'form.classlists'},
                                       unexpired  => $env{'form.unexpired'},  
                                       fields => {%fields},                                        fields => {%fields},
                                       lockablenames => \@lockablenames,                                        lockablenames => \@lockablenames,
                                     }                                      }
                      );                       );
     my $lastactivedays;  
     if ($env{'form.lastactive'}) {  
         $lastactivedays = $env{'form.lastactivedays'};  
         $lastactivedays =~ s/^\s+|\s+$//g;  
         unless ($lastactivedays =~ /^\d+$/) {  
             undef($lastactivedays);  
             $env{'form.lastactive'} = 0;  
         }  
     }  
     $updatehash{'autoupdate'}{'lastactive'} = $lastactivedays;  
     foreach my $key (keys(%currautoupdate)) {      foreach my $key (keys(%currautoupdate)) {
         if (($key eq 'run') || ($key eq 'classlists') || ($key eq 'unexpired') || ($key eq 'lastactive')) {          if (($key eq 'run') || ($key eq 'classlists')) {
             if (exists($updatehash{autoupdate}{$key})) {              if (exists($updatehash{autoupdate}{$key})) {
                 if ($currautoupdate{$key} ne $updatehash{autoupdate}{$key}) {                  if ($currautoupdate{$key} ne $updatehash{autoupdate}{$key}) {
                     $changes{$key} = 1;                      $changes{$key} = 1;
Line 13571  sub modify_autoupdate { Line 9526  sub modify_autoupdate {
             $changes{'lockablenames'} = 1;              $changes{'lockablenames'} = 1;
         }          }
     }      }
     unless (grep(/^unexpired$/,keys(%currautoupdate))) {  
         if ($updatehash{'autoupdate'}{'unexpired'}) {  
             $changes{'unexpired'} = 1;  
         }  
     }  
     unless (grep(/^lastactive$/,keys(%currautoupdate))) {  
         if ($updatehash{'autoupdate'}{'lastactive'} ne '') {  
             $changes{'lastactive'} = 1;  
         }  
     }  
     foreach my $item (@{$types},'default') {      foreach my $item (@{$types},'default') {
         if (defined($fields{$item})) {          if (defined($fields{$item})) {
             if (ref($currautoupdate{'fields'}) eq 'HASH') {              if (ref($currautoupdate{'fields'}) eq 'HASH') {
Line 13643  sub modify_autoupdate { Line 9588  sub modify_autoupdate {
                     my $newvalue;                      my $newvalue;
                     if ($key eq 'run') {                      if ($key eq 'run') {
                         $newvalue = $offon[$env{'form.autoupdate_run'}];                          $newvalue = $offon[$env{'form.autoupdate_run'}];
                     } elsif ($key eq 'lastactive') {  
                         $newvalue = $offon[$env{'form.lastactive'}];  
                         unless ($lastactivedays eq '') {  
                             $newvalue .= '; '.&mt('inactive = no activity in last [quant,_1,day]',$lastactivedays);  
                         }  
                     } else {                      } else {
                         $newvalue = $offon[$env{'form.'.$key}];                          $newvalue = $offon[$env{'form.'.$key}];
                     }                      }
Line 13684  sub modify_autocreate { Line 9624  sub modify_autocreate {
         $newvals{$item} = 0 if ($newvals{$item} eq '');          $newvals{$item} = 0 if ($newvals{$item} eq '');
     }      }
     $newvals{'xmldc'} = $env{'form.autocreate_xmldc'};      $newvals{'xmldc'} = $env{'form.autocreate_xmldc'};
     my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);      my %domcoords = &get_active_dcs($dom);
     unless (exists($domcoords{$newvals{'xmldc'}})) {      unless (exists($domcoords{$newvals{'xmldc'}})) {
         $newvals{'xmldc'} = '';          $newvals{'xmldc'} = '';
     }       } 
Line 13741  sub modify_autocreate { Line 9681  sub modify_autocreate {
 }  }
   
 sub modify_directorysrch {  sub modify_directorysrch {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%changes);      my ($resulttext,%changes);
     my %currdirsrch;      my %currdirsrch;
     if (ref($domconfig{'directorysrch'}) eq 'HASH') {      if (ref($domconfig{'directorysrch'}) eq 'HASH') {
Line 13752  sub modify_directorysrch { Line 9692  sub modify_directorysrch {
     my %title = ( available => 'Institutional directory search available',      my %title = ( available => 'Institutional directory search available',
                   localonly => 'Other domains can search institution',                    localonly => 'Other domains can search institution',
                   lcavailable => 'LON-CAPA directory search available',                    lcavailable => 'LON-CAPA directory search available',
                   lclocalonly => 'Other domains can search LON-CAPA domain',                    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 13846  sub modify_directorysrch { Line 9786  sub modify_directorysrch {
             }              }
         }          }
         if (exists($currdirsrch{'lcavailable'})) {          if (exists($currdirsrch{'lcavailable'})) {
             if ($currdirsrch{'lcavailable'} ne $env{'form.dirsrch_domavailable'}) {               if ($currdirsrch{'lcavailable'} ne $env{'form.dirsrch_domavailable'}) {
                 $changes{'lcavailable'} = 1;                   $changes{'lcavailable'} = 1;
             }               }
         } else {          } else {
             if ($env{'form.dirsrch_lcavailable'} eq '1') {              if ($env{'form.dirsrch_lcavailable'} eq '1') {
                 $changes{'lcavailable'} = 1;                  $changes{'lcavailable'} = 1;
             }              }
         }          }
         if (exists($currdirsrch{'localonly'})) {          if (exists($currdirsrch{'localonly'})) {
             if ($currdirsrch{'localonly'} ne $env{'form.dirsrch_instlocalonly'}) {               if ($currdirsrch{'localonly'} ne $env{'form.dirsrch_instlocalonly'}) {
                 $changes{'localonly'} = 1;                   $changes{'localonly'} = 1;
             }               }
         } else {          } else {
             if ($env{'form.dirsrch_instlocalonly'} eq '1') {              if ($env{'form.dirsrch_instlocalonly'} eq '1') {
                 $changes{'localonly'} = 1;                  $changes{'localonly'} = 1;
             }              }
         }          }
         if (exists($currdirsrch{'lclocalonly'})) {          if (exists($currdirsrch{'lclocalonly'})) {
             if ($currdirsrch{'lclocalonly'} ne $env{'form.dirsrch_domlocalonly'}) {               if ($currdirsrch{'lclocalonly'} ne $env{'form.dirsrch_domlocalonly'}) {
                 $changes{'lclocalonly'} = 1;                   $changes{'lclocalonly'} = 1;
             }               }
         } else {          } else {
             if ($env{'form.dirsrch_domlocalonly'} eq '1') {              if ($env{'form.dirsrch_domlocalonly'} eq '1') {
                 $changes{'lclocalonly'} = 1;                  $changes{'lclocalonly'} = 1;
Line 13885  sub modify_directorysrch { Line 9825  sub modify_directorysrch {
             }              }
             if ($changes{'lclocalonly'}) {              if ($changes{'lclocalonly'}) {
                 $resulttext .= '<li>'.&mt("$title{'lclocalonly'} set to: $otherdoms[$env{'form.dirsrch_domlocalonly'}]").'</li>';                  $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 13935  sub modify_directorysrch { Line 9875  sub modify_directorysrch {
                 $resulttext .= '<li>'.&mt($title{'searchtypes'}.' set to: "[_1]"',$chgtext).'</li>';                  $resulttext .= '<li>'.&mt($title{'searchtypes'}.' set to: "[_1]"',$chgtext).'</li>';
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
             &Apache::lonnet::do_cache_new('directorysrch',$dom,$dirsrch_hash{'directorysrch'},3600);  
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'directorysrch'} = 1;  
             }  
         } else {          } else {
             $resulttext = &mt('No changes made to directory search settings');              $resulttext = &mt('No changes made to directory search settings');
         }          }
Line 13957  sub modify_contacts { Line 9893  sub modify_contacts {
             $currsetting{$key} = $domconfig{'contacts'}{$key};              $currsetting{$key} = $domconfig{'contacts'}{$key};
         }          }
     }      }
     my (%others,%to,%bcc,%includestr,%includeloc);      my (%others,%to,%bcc);
     my @contacts = ('supportemail','adminemail');      my @contacts = ('supportemail','adminemail');
     my @mailings = ('errormail','packagesmail','helpdeskmail','otherdomsmail',      my @mailings = ('errormail','packagesmail','helpdeskmail','lonstatusmail',
                     'lonstatusmail','requestsmail','updatesmail','idconflictsmail','hostipmail');                      'requestsmail','updatesmail','idconflictsmail');
     my @toggles = ('reporterrors','reportupdates','reportstatus');      my @toggles = ('reporterrors','reportupdates');
     my @lonstatus = ('threshold','sysmail','weights','excluded');  
     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 13973  sub modify_contacts { Line 9907  sub modify_contacts {
             } else {              } else {
                 $contacts_hash{contacts}{$type}{$item} = 0;                  $contacts_hash{contacts}{$type}{$item} = 0;
             }              }
         }          }  
         $others{$type} = $env{'form.'.$type.'_others'};          $others{$type} = $env{'form.'.$type.'_others'};
         $contacts_hash{contacts}{$type}{'others'} = $others{$type};          $contacts_hash{contacts}{$type}{'others'} = $others{$type};
         if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {          if ($type eq 'helpdeskmail') {
             $bcc{$type} = $env{'form.'.$type.'_bcc'};              $bcc{$type} = $env{'form.'.$type.'_bcc'};
             $contacts_hash{contacts}{$type}{'bcc'} = $bcc{$type};              $contacts_hash{contacts}{$type}{'bcc'} = $bcc{$type};
             if (($env{'form.'.$type.'_includestr'} ne '') && ($env{'form.'.$type.'_includeloc'} =~ /^s|b$/)) {  
                 $includestr{$type} = $env{'form.'.$type.'_includestr'};  
                 $includeloc{$type} = $env{'form.'.$type.'_includeloc'};  
                 $contacts_hash{contacts}{$type}{'include'} = $includeloc{$type}.':'.&escape($includestr{$type});  
             }  
         }          }
     }      }
     foreach my $item (@contacts) {      foreach my $item (@contacts) {
Line 13995  sub modify_contacts { Line 9924  sub modify_contacts {
             $contacts_hash{'contacts'}{$item} = $env{'form.'.$item};              $contacts_hash{'contacts'}{$item} = $env{'form.'.$item};
         }          }
     }      }
     my ($lonstatus_defs,$lonstatus_names) = &Apache::loncommon::lon_status_items();  
     foreach my $item (@lonstatus) {  
         if ($item eq 'excluded') {  
             my (%serverhomes,@excluded);  
             map { $serverhomes{$_} = 1; } values(%Apache::lonnet::serverhomeIDs);  
             my @possexcluded = &Apache::loncommon::get_env_multiple('form.errorexcluded');  
             if (@possexcluded) {  
                 foreach my $id (sort(@possexcluded)) {  
                     if ($serverhomes{$id}) {  
                         push(@excluded,$id);  
                     }  
                 }  
             }  
             if (@excluded) {  
                 $contacts_hash{'contacts'}{'lonstatus'}{$item} = \@excluded;  
             }  
         } elsif ($item eq 'weights') {  
             foreach my $type ('E','W','N','U') {  
                 $env{'form.error'.$item.'_'.$type} =~ s/^\s+|\s+$//g;  
                 if ($env{'form.error'.$item.'_'.$type} =~ /^\d+$/) {  
                     unless ($env{'form.error'.$item.'_'.$type} == $lonstatus_defs->{$type}) {  
                         $contacts_hash{'contacts'}{'lonstatus'}{$item}{$type} =  
                             $env{'form.error'.$item.'_'.$type};  
                     }  
                 }  
             }  
         } elsif (($item eq 'threshold') || ($item eq 'sysmail')) {  
             $env{'form.error'.$item} =~ s/^\s+|\s+$//g;  
             if ($env{'form.error'.$item} =~ /^\d+$/) {  
                 unless ($env{'form.error'.$item} == $lonstatus_defs->{$item}) {  
                     $contacts_hash{'contacts'}{'lonstatus'}{$item} = $env{'form.error'.$item};  
                 }  
             }  
         }  
     }  
     if ((ref($fields) eq 'ARRAY') && (ref($possoptions) eq 'HASH')) {  
         foreach my $field (@{$fields}) {  
             if (ref($possoptions->{$field}) eq 'ARRAY') {  
                 my $value = $env{'form.helpform_'.$field};  
                 $value =~ s/^\s+|\s+$//g;  
                 if (grep(/^\Q$value\E$/,@{$possoptions->{$field}})) {  
                     $contacts_hash{'contacts'}{'helpform'}{$field} = $value;  
                     if ($field eq 'screenshot') {  
                         $env{'form.helpform_maxsize'} =~ s/^\s+|\s+$//g;  
                         if ($env{'form.helpform_maxsize'} =~ /^\d+\.?\d*$/) {  
                             $contacts_hash{'contacts'}{'helpform'}{'maxsize'} = $env{'form.helpform_maxsize'};  
                         }  
                     }  
                 }  
             }  
         }  
     }  
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
     my (@statuses,%usertypeshash,@overrides);  
     if ((ref($types) eq 'ARRAY') && (@{$types} > 0)) {  
         @statuses = @{$types};  
         if (ref($usertypes) eq 'HASH') {  
             %usertypeshash = %{$usertypes};  
         }  
     }  
     if (@statuses) {  
         my @possoverrides = &Apache::loncommon::get_env_multiple('form.overrides');  
         foreach my $type (@possoverrides) {  
             if (($type ne '') && (grep(/^\Q$type\E$/,@statuses))) {  
                 push(@overrides,$type);  
             }  
         }  
         if (@overrides) {  
             foreach my $type (@overrides) {  
                 my @standard = &Apache::loncommon::get_env_multiple('form.override_'.$type);  
                 foreach my $item (@contacts) {  
                     if (grep(/^\Q$item\E$/,@standard)) {  
                         $contacts_hash{'contacts'}{'overrides'}{$type}{$item} = 1;  
                         $newsetting{'override_'.$type}{$item} = 1;  
                     } else {  
                         $contacts_hash{'contacts'}{'overrides'}{$type}{$item} = 0;  
                         $newsetting{'override_'.$type}{$item} = 0;  
                     }  
                 }  
                 $contacts_hash{'contacts'}{'overrides'}{$type}{'others'} = $env{'form.override_'.$type.'_others'};  
                 $contacts_hash{'contacts'}{'overrides'}{$type}{'bcc'} = $env{'form.override_'.$type.'_bcc'};  
                 $newsetting{'override_'.$type}{'others'} = $env{'form.override_'.$type.'_others'};  
                 $newsetting{'override_'.$type}{'bcc'} = $env{'form.override_'.$type.'_bcc'};  
                 if (($env{'form.override_'.$type.'_includestr'} ne '') && ($env{'form.override_'.$type.'_includeloc'} =~ /^s|b$/)) {  
                     $includestr{$type} = $env{'form.override_'.$type.'_includestr'};  
                     $includeloc{$type} = $env{'form.override_'.$type.'_includeloc'};  
                     $contacts_hash{'contacts'}{'overrides'}{$type}{'include'} = $includeloc{$type}.':'.&escape($includestr{$type});  
                     $newsetting{'override_'.$type}{'include'} = $contacts_hash{'contacts'}{'overrides'}{$type}{'include'};  
                 }  
             }      
         }  
     }  
     if (keys(%currsetting) > 0) {      if (keys(%currsetting) > 0) {
         foreach my $item (@contacts) {          foreach my $item (@contacts) {
             if ($to{$item} ne $currsetting{$item}) {              if ($to{$item} ne $currsetting{$item}) {
Line 14106  sub modify_contacts { Line 9943  sub modify_contacts {
             if ($others{$type} ne $currsetting{$type}{'others'}) {              if ($others{$type} ne $currsetting{$type}{'others'}) {
                 push(@{$changes{$type}},'others');                  push(@{$changes{$type}},'others');
             }              }
             if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {              if ($type eq 'helpdeskmail') {   
                 if ($bcc{$type} ne $currsetting{$type}{'bcc'}) {                  if ($bcc{$type} ne $currsetting{$type}{'bcc'}) {
                     push(@{$changes{$type}},'bcc');                       push(@{$changes{$type}},'bcc'); 
                 }                  }
                 my ($currloc,$currstr) = split(/:/,$currsetting{$type}{'include'},2);  
                 if (($includeloc{$type} ne $currloc) || (&escape($includestr{$type}) ne $currstr)) {  
                     push(@{$changes{$type}},'include');  
                 }  
             }  
         }  
         if (ref($fields) eq 'ARRAY') {  
             if (ref($currsetting{'helpform'}) eq 'HASH') {  
                 foreach my $field (@{$fields}) {  
                     if ($currsetting{'helpform'}{$field} ne $contacts_hash{'contacts'}{'helpform'}{$field}) {  
                         push(@{$changes{'helpform'}},$field);  
                     }  
                     if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {  
                         if ($currsetting{'helpform'}{'maxsize'} ne $contacts_hash{'contacts'}{'helpform'}{'maxsize'}) {  
                             push(@{$changes{'helpform'}},'maxsize');  
                         }  
                     }  
                 }  
             } else {  
                 foreach my $field (@{$fields}) {  
                     if ($contacts_hash{'contacts'}{'helpform'}{$field} ne 'yes') {  
                         push(@{$changes{'helpform'}},$field);  
                     }  
                     if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {  
                         if ($contacts_hash{'contacts'}{'helpform'}{'maxsize'} != 1) {  
                             push(@{$changes{'helpform'}},'maxsize');  
                         }  
                     }  
                 }  
             }  
         }  
         if (@statuses) {  
             if (ref($currsetting{'overrides'}) eq 'HASH') {  
                 foreach my $key (keys(%{$currsetting{'overrides'}})) {  
                     if (ref($currsetting{'overrides'}{$key}) eq 'HASH') {  
                         if (ref($newsetting{'override_'.$key}) eq 'HASH') {  
                             foreach my $item (@contacts,'bcc','others','include') {  
                                 if ($currsetting{'overrides'}{$key}{$item} ne $newsetting{'override_'.$key}{$item}) {  
                                     push(@{$changes{'overrides'}},$key);  
                                     last;  
                                 }  
                             }  
                         } else {  
                             push(@{$changes{'overrides'}},$key);  
                         }  
                     }  
                 }  
                 foreach my $key (@overrides) {  
                     unless (exists($currsetting{'overrides'}{$key})) {  
                         push(@{$changes{'overrides'}},$key);  
                     }  
                 }  
             } else {  
                 foreach my $key (@overrides) {  
                     push(@{$changes{'overrides'}},$key);  
                 }  
             }  
         }  
         if (ref($currsetting{'lonstatus'}) eq 'HASH') {  
             foreach my $key ('excluded','weights','threshold','sysmail') {  
                 if ($key eq 'excluded') {  
                     if ((ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') &&  
                         (ref($contacts_hash{contacts}{lonstatus}{excluded}) eq 'ARRAY')) {  
                         if ((ref($currsetting{'lonstatus'}{$key}) eq 'ARRAY') &&  
                             (@{$currsetting{'lonstatus'}{$key}})) {  
                             my @diffs =  
                                 &Apache::loncommon::compare_arrays($contacts_hash{contacts}{lonstatus}{excluded},  
                                                                    $currsetting{'lonstatus'}{$key});  
                             if (@diffs) {  
                                 push(@{$changes{'lonstatus'}},$key);  
                             }  
                         } elsif (@{$contacts_hash{contacts}{lonstatus}{excluded}}) {  
                             push(@{$changes{'lonstatus'}},$key);  
                         }  
                     } elsif ((ref($currsetting{'lonstatus'}{$key}) eq 'ARRAY') &&  
                              (@{$currsetting{'lonstatus'}{$key}})) {  
                         push(@{$changes{'lonstatus'}},$key);  
                     }  
                 } elsif ($key eq 'weights') {  
                     if ((ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') &&  
                         (ref($contacts_hash{contacts}{lonstatus}{$key}) eq 'HASH')) {  
                         if (ref($currsetting{'lonstatus'}{$key}) eq 'HASH') {  
                             foreach my $type ('E','W','N','U') {  
                                 unless ($contacts_hash{contacts}{lonstatus}{$key}{$type} eq  
                                         $currsetting{'lonstatus'}{$key}{$type}) {  
                                     push(@{$changes{'lonstatus'}},$key);  
                                     last;  
                                 }  
                             }  
                         } else {  
                             foreach my $type ('E','W','N','U') {  
                                 if ($contacts_hash{contacts}{lonstatus}{$key}{$type} ne '') {  
                                     push(@{$changes{'lonstatus'}},$key);  
                                     last;  
                                 }  
                             }  
                         }  
                     } elsif (ref($currsetting{'lonstatus'}{$key}) eq 'HASH') {  
                         foreach my $type ('E','W','N','U') {  
                             if ($currsetting{'lonstatus'}{$key}{$type} ne '') {  
                                 push(@{$changes{'lonstatus'}},$key);  
                                 last;  
                             }  
                         }  
                     }  
                 } elsif (($key eq 'threshold') || ($key eq 'sysmail')) {  
                     if (ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') {  
                         if ($currsetting{'lonstatus'}{$key} =~ /^\d+$/) {  
                             if ($currsetting{'lonstatus'}{$key} != $contacts_hash{contacts}{lonstatus}{$key}) {  
                                 push(@{$changes{'lonstatus'}},$key);  
                             }  
                         } elsif ($contacts_hash{contacts}{lonstatus}{$key} =~ /^\d+$/) {  
                             push(@{$changes{'lonstatus'}},$key);  
                         }  
                     } elsif ($currsetting{'lonstatus'}{$key} =~ /^\d+$/) {  
                         push(@{$changes{'lonstatus'}},$key);  
                     }  
                 }  
             }  
         } else {  
             if (ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') {  
                 foreach my $key ('excluded','weights','threshold','sysmail') {  
                     if (exists($contacts_hash{contacts}{lonstatus}{$key})) {  
                         push(@{$changes{'lonstatus'}},$key);  
                     }  
                 }  
             }              }
         }          }
     } else {      } else {
Line 14245  sub modify_contacts { Line 9956  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';
         $default{'hostipmail'} = 'adminemail';  
         foreach my $item (@contacts) {          foreach my $item (@contacts) {
            if ($to{$item} ne $default{$item}) {             if ($to{$item} ne $default{$item}) {
                $changes{$item} = 1;                $changes{$item} = 1;
            }             }
         }          }
         foreach my $type (@mailings) {          foreach my $type (@mailings) {
             if ((@{$newsetting{$type}} != 1) || ($newsetting{$type}[0] ne $default{$type})) {              if ((@{$newsetting{$type}} != 1) || ($newsetting{$type}[0] ne $default{$type})) {
                  
                 push(@{$changes{$type}},@{$newsetting{$type}});                  push(@{$changes{$type}},@{$newsetting{$type}});
             }              }
             if ($others{$type} ne '') {              if ($others{$type} ne '') {
                 push(@{$changes{$type}},'others');                  push(@{$changes{$type}},'others');
             }              }
             if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {              if ($type eq 'helpdeskmail') {
                 if ($bcc{$type} ne '') {                  if ($bcc{$type} ne '') {
                     push(@{$changes{$type}},'bcc');                      push(@{$changes{$type}},'bcc');
                 }                  }
                 if (($includeloc{$type} =~ /^b|s$/) && ($includestr{$type} ne '')) {  
                     push(@{$changes{$type}},'include');  
                 }  
             }  
         }  
         if (ref($fields) eq 'ARRAY') {  
             foreach my $field (@{$fields}) {  
                 if ($contacts_hash{'contacts'}{'helpform'}{$field} ne 'yes') {  
                     push(@{$changes{'helpform'}},$field);  
                 }  
                 if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {  
                     if ($contacts_hash{'contacts'}{'helpform'}{'maxsize'} != 1) {  
                         push(@{$changes{'helpform'}},'maxsize');  
                     }  
                 }  
             }  
         }  
         if (ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') {  
             foreach my $key ('excluded','weights','threshold','sysmail') {  
                 if (exists($contacts_hash{contacts}{lonstatus}{$key})) {  
                     push(@{$changes{'lonstatus'}},$key);  
                 }  
             }              }
         }          }
     }      }
Line 14319  sub modify_contacts { Line 10007  sub modify_contacts {
             }              }
             foreach my $type (@mailings) {              foreach my $type (@mailings) {
                 if (ref($changes{$type}) eq 'ARRAY') {                  if (ref($changes{$type}) eq 'ARRAY') {
                     if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {                      $resulttext .= '<li>'.$titles->{$type}.': ';
                         $resulttext .= '<li>'.$titles->{$type}.' -- '.&mt('sent to').': ';  
                     } else {  
                         $resulttext .= '<li>'.$titles->{$type}.': ';  
                     }  
                     my @text;                      my @text;
                     foreach my $item (@{$newsetting{$type}}) {                      foreach my $item (@{$newsetting{$type}}) {
                         push(@text,$short_titles->{$item});                          push(@text,$short_titles->{$item});
Line 14331  sub modify_contacts { Line 10015  sub modify_contacts {
                     if ($others{$type} ne '') {                      if ($others{$type} ne '') {
                         push(@text,$others{$type});                          push(@text,$others{$type});
                     }                      }
                     if (@text) {                      $resulttext .= '<span class="LC_cusr_emph">'.
                         $resulttext .= '<span class="LC_cusr_emph">'.                                     join(', ',@text).'</span>';
                                        join(', ',@text).'</span>';                      if ($type eq 'helpdeskmail') {
                     }  
                     if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {  
                         if ($bcc{$type} ne '') {                          if ($bcc{$type} ne '') {
                             my $bcctext;                              $resulttext .= '&nbsp;'.&mt('with Bcc to').': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';
                             if (@text) {  
                                 $bcctext = '&nbsp;'.&mt('with Bcc to');  
                             } else {  
                                 $bcctext = '(Bcc)';  
                             }  
                             $resulttext .= $bcctext.': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';  
                         } elsif (!@text) {  
                             $resulttext .= &mt('No one');  
                         }                          }
                         if ($includestr{$type} ne '') {  
                             if ($includeloc{$type} eq 'b') {  
                                 $resulttext .= '<br />'.&mt('Text automatically added to e-mail body:').' '.$includestr{$type};  
                             } elsif ($includeloc{$type} eq 's') {  
                                 $resulttext .= '<br />'.&mt('Text automatically added to e-mail subject:').' '.$includestr{$type};  
                             }  
                         }  
                     } elsif (!@text) {  
                         $resulttext .= &mt('No recipients');  
                     }                      }
                     $resulttext .= '</li>';                      $resulttext .= '</li>';
                 }                  }
             }              }
             if (ref($changes{'overrides'}) eq 'ARRAY') {  
                 my @deletions;  
                 foreach my $type (@{$changes{'overrides'}}) {  
                     if ($usertypeshash{$type}) {  
                         if (grep(/^\Q$type\E/,@overrides)) {  
                             $resulttext .= '<li>'.&mt("Overrides based on requester's affiliation set for [_1]",  
                                                       $usertypeshash{$type}).'<ul><li>';  
                             if (ref($newsetting{'override_'.$type}) eq 'HASH') {  
                                 my @text;  
                                 foreach my $item (@contacts) {  
                                     if ($newsetting{'override_'.$type}{$item}) {  
                                         push(@text,$short_titles->{$item});  
                                     }  
                                 }  
                                 if ($newsetting{'override_'.$type}{'others'} ne '') {  
                                     push(@text,$newsetting{'override_'.$type}{'others'});  
                                 }  
   
                                 if (@text) {  
                                     $resulttext .= &mt('Helpdesk e-mail sent to: [_1]',  
                                                        '<span class="LC_cusr_emph">'.join(', ',@text).'</span>');  
                                 }  
                                 if ($newsetting{'override_'.$type}{'bcc'} ne '') {  
                                     my $bcctext;  
                                     if (@text) {  
                                         $bcctext = '&nbsp;'.&mt('with Bcc to');  
                                     } else {  
                                         $bcctext = '(Bcc)';  
                                     }  
                                     $resulttext .= $bcctext.': <span class="LC_cusr_emph">'.$newsetting{'override_'.$type}{'bcc'}.'</span>';  
                                 } elsif (!@text) {  
                                      $resulttext .= &mt('Helpdesk e-mail sent to no one');  
                                 }  
                                 $resulttext .= '</li>';  
                                 if ($newsetting{'override_'.$type}{'include'} ne '') {  
                                     my ($loc,$str) = split(/:/,$newsetting{'override_'.$type}{'include'});  
                                     if ($loc eq 'b') {  
                                         $resulttext .= '<li>'.&mt('Text automatically added to e-mail body:').' '.&unescape($str).'</li>';  
                                     } elsif ($loc eq 's') {  
                                         $resulttext .= '<li>'.&mt('Text automatically added to e-mail subject:').' '.&unescape($str).'</li>';  
                                     }  
                                 }  
                             }  
                             $resulttext .= '</li></ul></li>';  
                         } else {  
                             push(@deletions,$usertypeshash{$type});  
                         }  
                     }  
                 }  
                 if (@deletions) {  
                     $resulttext .= '<li>'.&mt("Overrides based on requester's affiliation discontinued for: [_1]",  
                                               join(', ',@deletions)).'</li>';  
                 }  
             }  
             my @offon = ('off','on');              my @offon = ('off','on');
             my $corelink = &core_link_msu();  
             if ($changes{'reporterrors'}) {              if ($changes{'reporterrors'}) {
                 $resulttext .= '<li>'.                  $resulttext .= '<li>'.
                                &mt('E-mail error reports to [_1] set to "'.                                 &mt('E-mail error reports to [_1] set to "'.
                                    $offon[$env{'form.reporterrors'}].'".',                                     $offon[$env{'form.reporterrors'}].'".',
                                    $corelink).                                     &Apache::loncommon::modal_link('http://loncapa.org/core.html',
                                          &mt('LON-CAPA core group - MSU'),600,500)).
                                '</li>';                                 '</li>';
             }              }
             if ($changes{'reportupdates'}) {              if ($changes{'reportupdates'}) {
                 $resulttext .= '<li>'.                  $resulttext .= '<li>'.
                                 &mt('E-mail record of completed LON-CAPA updates to [_1] set to "'.                                  &mt('E-mail record of completed LON-CAPA updates to [_1] set to "'.
                                     $offon[$env{'form.reportupdates'}].'".',                                      $offon[$env{'form.reportupdates'}].'".',
                                     $corelink).                                      &Apache::loncommon::modal_link('http://loncapa.org/core.html',
                                 '</li>';                                          &mt('LON-CAPA core group - MSU'),600,500)).
             }  
             if ($changes{'reportstatus'}) {  
                 $resulttext .= '<li>'.  
                                 &mt('E-mail status if errors above threshold to [_1] set to "'.  
                                     $offon[$env{'form.reportstatus'}].'".',  
                                     $corelink).  
                                 '</li>';                                  '</li>';
             }              }
             if (ref($changes{'lonstatus'}) eq 'ARRAY') {  
                 $resulttext .= '<li>'.  
                                &mt('Nightly status check e-mail settings').':<ul>';  
                 my (%defval,%use_def,%shown);  
                 $defval{'threshold'} = $lonstatus_defs->{'threshold'};  
                 $defval{'sysmail'} = $lonstatus_defs->{'sysmail'};  
                 $defval{'weights'} =  
                     join(', ',map { $lonstatus_names->{$_}.'='.$lonstatus_defs->{$_}; } ('E','W','N','U'));  
                 $defval{'excluded'} = &mt('None');  
                 if (ref($contacts_hash{'contacts'}{'lonstatus'}) eq 'HASH') {  
                     foreach my $item ('threshold','sysmail','weights','excluded') {  
                         if (exists($contacts_hash{'contacts'}{'lonstatus'}{$item})) {  
                             if (($item eq 'threshold') || ($item eq 'sysmail')) {  
                                 $shown{$item} = $contacts_hash{'contacts'}{'lonstatus'}{$item};  
                             } elsif ($item eq 'weights') {  
                                 if (ref($contacts_hash{'contacts'}{'lonstatus'}{$item}) eq 'HASH') {  
                                     foreach my $type ('E','W','N','U') {  
                                         $shown{$item} .= $lonstatus_names->{$type}.'=';  
                                         if (exists($contacts_hash{'contacts'}{'lonstatus'}{$item}{$type})) {  
                                             $shown{$item} .= $contacts_hash{'contacts'}{'lonstatus'}{$item}{$type};  
                                         } else {  
                                             $shown{$item} .= $lonstatus_defs->{$type};  
                                         }  
                                         $shown{$item} .= ', ';  
                                     }  
                                     $shown{$item} =~ s/, $//;  
                                 } else {  
                                     $shown{$item} = $defval{$item};  
                                 }  
                             } elsif ($item eq 'excluded') {  
                                 if (ref($contacts_hash{'contacts'}{'lonstatus'}{$item}) eq 'ARRAY') {  
                                     $shown{$item} = join(', ',@{$contacts_hash{'contacts'}{'lonstatus'}{$item}});  
                                 } else {  
                                     $shown{$item} = $defval{$item};  
                                 }  
                             }  
                         } else {  
                             $shown{$item} = $defval{$item};  
                         }  
                     }  
                 } else {  
                     foreach my $item ('threshold','weights','excluded','sysmail') {  
                         $shown{$item} = $defval{$item};  
                     }  
                 }  
                 foreach my $item ('threshold','weights','excluded','sysmail') {  
                     $resulttext .= '<li>'.&mt($titles->{'error'.$item}.' -- [_1]',  
                                           $shown{$item}).'</li>';  
                 }  
                 $resulttext .= '</ul></li>';  
             }  
             if ((ref($changes{'helpform'}) eq 'ARRAY') && (ref($fields) eq 'ARRAY')) {  
                 my (@optional,@required,@unused,$maxsizechg);  
                 foreach my $field (@{$changes{'helpform'}}) {  
                     if ($field eq 'maxsize') {  
                         $maxsizechg = 1;  
                         next;  
                     }  
                     if ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'yes') {  
                         push(@optional,$field);  
                     } elsif ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'no') {  
                         push(@unused,$field);  
                     } elsif ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'req') {  
                         push(@required,$field);  
                     }  
                 }  
                 if (@optional) {  
                     $resulttext .= '<li>'.  
                                    &mt('Help form fields changed to "Optional": [_1].',  
                                        '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @optional)).'</span>'.  
                                    '</li>';  
                 }  
                 if (@required) {  
                     $resulttext .= '<li>'.  
                                    &mt('Help form fields changed to "Required": [_1].',  
                                        '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @required)).'</span>'.  
                                    '</li>';  
                 }  
                 if (@unused) {  
                     $resulttext .= '<li>'.  
                                    &mt('Help form fields changed to "Not shown": [_1].',  
                                        '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @unused)).'</span>'.  
                                    '</li>';  
                 }  
                 if ($maxsizechg) {  
                     $resulttext .= '<li>'.  
                                    &mt('Max size for file uploaded to help form by logged-in user set to [_1] MB.',  
                                        $contacts_hash{'contacts'}{'helpform'}{'maxsize'}).  
                                    '</li>';  
                 }  
             }  
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
             $resulttext = &mt('No changes made to contacts and form settings');              $resulttext = &mt('No changes made to contact information');
         }          }
     } else {      } else {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
Line 14539  sub modify_contacts { Line 10053  sub modify_contacts {
     return $resulttext;      return $resulttext;
 }  }
   
 sub modify_passwords {  
     my ($r,$dom,$confname,$lastactref,%domconfig) = @_;  
     my ($resulttext,%current,%changes,%newvalues,@oktypes,$errors,  
         $updatedefaults,$updateconf);  
     my $customfn = 'resetpw.html';  
     if (ref($domconfig{'passwords'}) eq 'HASH') {  
         %current = %{$domconfig{'passwords'}};  
     }  
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);  
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
     if (ref($types) eq 'ARRAY') {  
         @oktypes = @{$types};  
     }  
     push(@oktypes,'default');  
   
     my %titles = &Apache::lonlocal::texthash (  
         intauth_cost   => 'Encryption cost for bcrypt (positive integer)',  
         intauth_check  => 'Check bcrypt cost if authenticated',  
         intauth_switch => 'Existing crypt-based switched to bcrypt on authentication',  
         permanent      => 'Permanent e-mail address',  
         critical       => 'Critical notification address',  
         notify         => 'Notification address',  
         min            => 'Minimum password length',  
         max            => 'Maximum password length',  
         chars          => 'Required characters',  
         numsaved       => 'Number of previous passwords to save',  
         reset          => 'Resetting Forgotten Password',  
         intauth        => 'Encryption of Stored Passwords (Internal Auth)',  
         rules          => 'Rules for LON-CAPA Passwords',  
         crsownerchg    => 'Course Owner Changing Student Passwords',  
         username       => 'Username',  
         email          => 'E-mail address',  
     );  
   
 #  
 # Retrieve current domain configuration for internal authentication from $domconfig{'defaults'}.  
 #  
     my (%curr_defaults,%save_defaults);  
     if (ref($domconfig{'defaults'}) eq 'HASH') {  
         foreach my $key (keys(%{$domconfig{'defaults'}})) {  
             if ($key =~ /^intauth_(cost|check|switch)$/) {  
                 $curr_defaults{$key} = $domconfig{'defaults'}{$key};  
             } else {  
                 $save_defaults{$key} = $domconfig{'defaults'}{$key};  
             }  
         }  
     }  
     my %staticdefaults = (  
         'resetlink'      => 2,  
         'resetcase'      => \@oktypes,  
         'resetprelink'   => 'both',  
         'resetemail'     => ['critical','notify','permanent'],  
         'intauth_cost'   => 10,  
         'intauth_check'  => 0,  
         'intauth_switch' => 0,  
     );  
     $staticdefaults{'min'} = $Apache::lonnet::passwdmin;  
     foreach my $type (@oktypes) {  
         $staticdefaults{'resetpostlink'}{$type} = ['email','username'];  
     }  
     my $linklife = $env{'form.passwords_link'};  
     $linklife =~ s/^\s+|\s+$//g;  
     if (($linklife =~ /^\d+(|\.\d*)$/) && ($linklife > 0)) {  
         $newvalues{'resetlink'} = $linklife;  
         if ($current{'resetlink'}) {  
             if ($current{'resetlink'} ne $linklife) {  
                 $changes{'reset'} = 1;  
             }  
         } elsif (!ref($domconfig{passwords}) eq 'HASH') {  
             if ($staticdefaults{'resetlink'} ne $linklife) {  
                 $changes{'reset'} = 1;  
             }  
         }  
     } elsif ($current{'resetlink'}) {  
         $changes{'reset'} = 1;  
     }  
     my @casesens;  
     my @posscase = &Apache::loncommon::get_env_multiple('form.passwords_case_sensitive');  
     foreach my $case (sort(@posscase)) {  
         if (grep(/^\Q$case\E$/,@oktypes)) {  
             push(@casesens,$case);  
         }  
     }  
     $newvalues{'resetcase'} = \@casesens;  
     if (ref($current{'resetcase'}) eq 'ARRAY') {  
         my @diffs = &Apache::loncommon::compare_arrays($current{'resetcase'},\@casesens);  
         if (@diffs > 0) {  
             $changes{'reset'} = 1;  
         }  
     } elsif (!ref($domconfig{passwords}) eq 'HASH') {  
         my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetcase'},\@casesens);  
         if (@diffs > 0) {  
             $changes{'reset'} = 1;  
         }  
     }  
     if ($env{'form.passwords_prelink'} =~ /^(both|either)$/) {  
         $newvalues{'resetprelink'} = $env{'form.passwords_prelink'};  
         if (exists($current{'resetprelink'})) {  
             if ($current{'resetprelink'} ne $newvalues{'resetprelink'}) {  
                 $changes{'reset'} = 1;  
             }  
         } elsif (!ref($domconfig{passwords}) eq 'HASH') {  
             if ($staticdefaults{'resetprelink'} ne $newvalues{'resetprelink'}) {  
                 $changes{'reset'} = 1;  
             }  
         }  
     } elsif ($current{'resetprelink'}) {  
         $changes{'reset'} = 1;  
     }  
     foreach my $type (@oktypes) {  
         my @possplink = &Apache::loncommon::get_env_multiple('form.passwords_postlink_'.$type);  
         my @postlink;  
         foreach my $item (sort(@possplink)) {  
             if ($item =~ /^(email|username)$/) {  
                 push(@postlink,$item);  
             }  
         }  
         $newvalues{'resetpostlink'}{$type} = \@postlink;  
         unless ($changes{'reset'}) {  
             if (ref($current{'resetpostlink'}) eq 'HASH') {  
                 if (ref($current{'resetpostlink'}{$type}) eq 'ARRAY') {  
                     my @diffs = &Apache::loncommon::compare_arrays($current{'resetpostlink'}{$type},\@postlink);  
                     if (@diffs > 0) {  
                         $changes{'reset'} = 1;  
                     }  
                 } else {  
                     $changes{'reset'} = 1;  
                 }  
             } elsif (!ref($domconfig{passwords}) eq 'HASH') {  
                 my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetpostlink'}{$type},\@postlink);  
                 if (@diffs > 0) {  
                     $changes{'reset'} = 1;  
                 }  
             }  
         }  
     }  
     my @possemailsrc = &Apache::loncommon::get_env_multiple('form.passwords_emailsrc');  
     my @resetemail;  
     foreach my $item (sort(@possemailsrc)) {  
         if ($item =~ /^(permanent|critical|notify)$/) {  
             push(@resetemail,$item);  
         }  
     }  
     $newvalues{'resetemail'} = \@resetemail;  
     unless ($changes{'reset'}) {  
         if (ref($current{'resetemail'}) eq 'ARRAY') {  
             my @diffs = &Apache::loncommon::compare_arrays($current{'resetemail'},\@resetemail);  
             if (@diffs > 0) {  
                 $changes{'reset'} = 1;  
             }  
         } elsif (!ref($domconfig{passwords}) eq 'HASH') {  
             my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetemail'},\@resetemail);  
             if (@diffs > 0) {  
                 $changes{'reset'} = 1;  
             }  
         }  
     }  
     if ($env{'form.passwords_stdtext'} == 0) {  
         $newvalues{'resetremove'} = 1;  
         unless ($current{'resetremove'}) {  
             $changes{'reset'} = 1;  
         }  
     } elsif ($current{'resetremove'}) {  
         $changes{'reset'} = 1;  
     }  
     if ($env{'form.passwords_customfile.filename'} ne '') {  
         my $servadm = $r->dir_config('lonAdmEMail');  
         my $servadm = $r->dir_config('lonAdmEMail');  
         my ($configuserok,$author_ok,$switchserver) =  
             &config_check($dom,$confname,$servadm);  
         my $error;  
         if ($configuserok eq 'ok') {  
             if ($switchserver) {  
                 $error = &mt("Upload of file containing domain-specific text is not permitted to this server: [_1]",$switchserver);  
             } else {  
                 if ($author_ok eq 'ok') {  
                     my ($result,$customurl) =  
                         &publishlogo($r,'upload','passwords_customfile',$dom,  
                                      $confname,'customtext/resetpw','','',$customfn);  
                     if ($result eq 'ok') {  
                         $newvalues{'resetcustom'} = $customurl;  
                         $changes{'reset'} = 1;  
                     } else {  
                         $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$customfn,$result);  
                     }  
                 } else {  
                     $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3].  Error was: [_4].",$customfn,$confname,$dom,$author_ok);  
                 }  
             }  
         } else {  
             $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3].  Error was: [_4].",$customfn,$confname,$dom,$configuserok);  
         }  
         if ($error) {  
             &Apache::lonnet::logthis($error);  
             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';  
         }  
     } elsif ($current{'resetcustom'}) {  
         if ($env{'form.passwords_custom_del'}) {  
             $changes{'reset'} = 1;  
         } else {  
             $newvalues{'resetcustom'} = $current{'resetcustom'};  
         }  
     }  
     $env{'form.intauth_cost'} =~ s/^\s+|\s+$//g;  
     if (($env{'form.intauth_cost'} ne '') && ($env{'form.intauth_cost'} =~ /^\d+$/)) {  
         $save_defaults{'intauth_cost'} = $env{'form.intauth_cost'};  
         if ($save_defaults{'intauth_cost'} ne $curr_defaults{'intauth_cost'}) {  
             $changes{'intauth'} = 1;  
         }  
     } else {  
         $save_defaults{'intauth_cost'} = $curr_defaults{'intauth_cost'};  
     }  
     if ($env{'form.intauth_check'} =~ /^(0|1|2)$/) {  
         $save_defaults{'intauth_check'} = $env{'form.intauth_check'};  
         if ($save_defaults{'intauth_check'} ne $curr_defaults{'intauth_check'}) {  
             $changes{'intauth'} = 1;  
         }  
     } else {  
         $save_defaults{'intauth_check'} = $curr_defaults{'intauth_check'};  
     }  
     if ($env{'form.intauth_switch'} =~ /^(0|1|2)$/) {  
         $save_defaults{'intauth_switch'} = $env{'form.intauth_switch'};  
         if ($save_defaults{'intauth_switch'} ne $curr_defaults{'intauth_switch'}) {  
             $changes{'intauth'} = 1;  
         }  
     } else {  
         $save_defaults{'intauth_check'} = $curr_defaults{'intauth_check'};  
     }  
     foreach my $item ('cost','check','switch') {  
         if ($save_defaults{'intauth_'.$item} ne $domdefaults{'intauth_'.$item}) {  
             $domdefaults{'intauth_'.$item} = $save_defaults{'intauth_'.$item};  
             $updatedefaults = 1;  
         }  
     }  
     &password_rule_changes('passwords',\%newvalues,\%current,\%changes);  
     my %crsownerchg = (  
                         by => [],  
                         for => [],  
                       );  
     foreach my $item ('by','for') {  
         my @posstypes = &Apache::loncommon::get_env_multiple('form.passwords_crsowner_'.$item);  
         foreach my $type (sort(@posstypes)) {  
             if (grep(/^\Q$type\E$/,@oktypes)) {  
                 push(@{$crsownerchg{$item}},$type);  
             }  
         }  
     }  
     $newvalues{'crsownerchg'} = \%crsownerchg;  
     if (ref($current{'crsownerchg'}) eq 'HASH') {  
         foreach my $item ('by','for') {  
             if (ref($current{'crsownerchg'}{$item}) eq 'ARRAY') {  
                 my @diffs = &Apache::loncommon::compare_arrays($current{'crsownerchg'}{$item},$crsownerchg{$item});  
                 if (@diffs > 0) {  
                     $changes{'crsownerchg'} = 1;  
                     last;  
                 }  
             }  
         }  
     } elsif (!(ref($domconfig{passwords}) eq 'HASH')) {  
         foreach my $item ('by','for') {  
             if (@{$crsownerchg{$item}} > 0) {  
                 $changes{'crsownerchg'} = 1;  
                 last;  
             }  
         }  
     }  
   
     my %confighash = (  
                         defaults  => \%save_defaults,  
                         passwords => \%newvalues,  
                      );  
     &process_captcha('passwords',\%changes,$confighash{'passwords'},$domconfig{'passwords'});  
   
     my $putresult = &Apache::lonnet::put_dom('configuration',\%confighash,$dom);  
     if ($putresult eq 'ok') {  
         if (keys(%changes) > 0) {  
             $resulttext = &mt('Changes made: ').'<ul>';  
             foreach my $key ('reset','intauth','rules','crsownerchg') {  
                 if ($changes{$key}) {  
                     unless ($key eq 'intauth') {  
                         $updateconf = 1;  
                     }  
                     $resulttext .= '<li>'.$titles{$key}.':<ul>';  
                     if ($key eq 'reset') {  
                         if ($confighash{'passwords'}{'captcha'} eq 'original') {  
                             $resulttext .= '<li>'.&mt('CAPTCHA validation set to use: original CAPTCHA').'</li>';  
                         } elsif ($confighash{'passwords'}{'captcha'} eq 'recaptcha') {  
                             $resulttext .= '<li>'.&mt('CAPTCHA validation set to use: reCAPTCHA').' '.  
                                            &mt('version: [_1]',$confighash{'passwords'}{'recaptchaversion'}).'<br />';  
                             if (ref($confighash{'passwords'}{'recaptchakeys'}) eq 'HASH') {  
                                 $resulttext .= &mt('Public key: [_1]',$confighash{'passwords'}{'recaptchakeys'}{'public'}).'</br>'.  
                                                &mt('Private key: [_1]',$confighash{'passwords'}{'recaptchakeys'}{'private'}).'</li>';  
                             }  
                         } else {  
                             $resulttext .= '<li>'.&mt('No CAPTCHA validation').'</li>';  
                         }  
                         if ($confighash{'passwords'}{'resetlink'}) {  
                             $resulttext .= '<li>'.&mt('Reset link expiration set to [quant,_1,hour]',$confighash{'passwords'}{'resetlink'}).'</li>';  
                         } else {  
                             $resulttext .= '<li>'.&mt('No reset link expiration set.').' '.  
                                                   &mt('Will default to 2 hours').'</li>';  
                         }  
                         if (ref($confighash{'passwords'}{'resetcase'}) eq 'ARRAY') {  
                             if (@{$confighash{'passwords'}{'resetcase'}} == 0) {  
                                 $resulttext .= '<li>'.&mt('User input for username and/or e-mail address not case sensitive for "Forgot Password" web form').'</li>';  
                             } else {  
                                 my $casesens;  
                                 foreach my $type (@{$confighash{'passwords'}{'resetcase'}}) {  
                                     if ($type eq 'default') {  
                                         $casesens .= $othertitle.', ';  
                                     } elsif ($usertypes->{$type} ne '') {  
                                         $casesens .= $usertypes->{$type}.', ';  
                                     }  
                                 }  
                                 $casesens =~ s/\Q, \E$//;  
                                 $resulttext .= '<li>'.&mt('"Forgot Password" web form input for username and/or e-mail address is case-sensitive for: [_1]',$casesens).'</li>';  
                             }  
                         } else {  
                             $resulttext .= '<li>'.&mt('Case-sensitivity not set for "Forgot Password" web form').' '.&mt('Will default to case-sensitive for username and/or e-mail address for all').'</li>';  
                         }  
                         if ($confighash{'passwords'}{'resetprelink'} eq 'either') {  
                             $resulttext .= '<li>'.&mt('Users can enter either a username or an e-mail address in "Forgot Password" web form').'</li>';  
                         } else {  
                             $resulttext .= '<li>'.&mt('Users can enter both a username and an e-mail address in "Forgot Password" web form').'</li>';  
                         }  
                         if (ref($confighash{'passwords'}{'resetpostlink'}) eq 'HASH') {  
                             my $output;  
                             if (ref($types) eq 'ARRAY') {  
                                 foreach my $type (@{$types}) {  
                                     if (ref($confighash{'passwords'}{'resetpostlink'}{$type}) eq 'ARRAY') {  
                                         if (@{$confighash{'passwords'}{'resetpostlink'}{$type}} == 0) {  
                                             $output .= $usertypes->{$type}.' -- '.&mt('none');  
                                         } else {  
                                             $output .= $usertypes->{$type}.' -- '.  
                                                        join(', ',map { $titles{$_}; } (@{$confighash{'passwords'}{'resetpostlink'}{$type}})).'; ';  
                                         }  
                                     }  
                                 }  
                             }  
                             if (ref($confighash{'passwords'}{'resetpostlink'}{'default'}) eq 'ARRAY') {  
                                 if (@{$confighash{'passwords'}{'resetpostlink'}{'default'}} == 0) {  
                                     $output .= $othertitle.' -- '.&mt('none');  
                                 } else {  
                                     $output .= $othertitle.' -- '.  
                                                join(', ',map { $titles{$_}; } (@{$confighash{'passwords'}{'resetpostlink'}{'default'}}));  
                                 }  
                             }  
                             if ($output) {  
                                 $resulttext .= '<li>'.&mt('Information required for new password form (by user type) set to: [_1]',$output).'</li>';  
                             } else {  
                                 $resulttext .= '<li>'.&mt('Information required for new password form not set.').' '.&mt('Will default to requiring both the username and an e-mail address').'</li>';  
                             }  
                         } else {  
                             $resulttext .= '<li>'.&mt('Information required for new password form not set.').' '.&mt('Will default to requiring both the username and an e-mail address').'</li>';  
                         }  
                         if (ref($confighash{'passwords'}{'resetemail'}) eq 'ARRAY') {  
                             if (@{$confighash{'passwords'}{'resetemail'}} > 0) {  
                                 $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$confighash{'passwords'}{'resetemail'}})).'</li>';  
                             } else {  
                                 $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';  
                             }  
                         } else {  
                             $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';  
                         }  
                         if ($confighash{'passwords'}{'resetremove'}) {  
                             $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" web form not shown').'</li>';  
                         } else {  
                             $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" web form is shown').'</li>';  
                         }  
                         if ($confighash{'passwords'}{'resetcustom'}) {  
                             my $customlink = &Apache::loncommon::modal_link($confighash{'passwords'}{'resetcustom'},  
                                                                             &mt('custom text'),600,500,undef,undef,  
                                                                             undef,undef,'background-color:#ffffff');  
                             $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" form includes: [_1]',$customlink).'</li>';  
                         } else {  
                             $resulttext .= '<li>'.&mt('No custom text included in preamble to "Forgot Password" form').'</li>';  
                         }  
                     } elsif ($key eq 'intauth') {  
                         foreach my $item ('cost','switch','check') {  
                             my $value = $save_defaults{$key.'_'.$item};  
                             if ($item eq 'switch') {  
                                 my %optiondesc = &Apache::lonlocal::texthash (  
                                                      0 => 'No',  
                                                      1 => 'Yes',  
                                                      2 => 'Yes, and copy existing passwd file to passwd.bak file',  
                                                  );  
                                 if ($value =~ /^(0|1|2)$/) {  
                                     $value = $optiondesc{$value};  
                                 } else {  
                                     $value = &mt('none -- defaults to No');  
                                 }  
                             } elsif ($item eq 'check') {  
                                 my %optiondesc = &Apache::lonlocal::texthash (  
                                                      0 => 'No',  
                                                      1 => 'Yes, allow login then update passwd file using default cost (if higher)',  
                                                      2 => 'Yes, disallow login if stored cost is less than domain default',  
                                                  );  
                                 if ($value =~ /^(0|1|2)$/) {  
                                     $value = $optiondesc{$value};  
                                 } else {  
                                     $value = &mt('none -- defaults to No');  
                                 }  
                             }  
                             $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$titles{$key.'_'.$item},$value).'</li>';  
                         }  
                     } elsif ($key eq 'rules') {  
                         foreach my $rule ('min','max','numsaved') {  
                             if ($confighash{'passwords'}{$rule} eq '') {  
                                 if ($rule eq 'min') {  
                                     $resulttext .= '<li>'.&mt('[_1] not set.',$titles{$rule});  
                                                    ' '.&mt('Default of [_1] will be used',  
                                                            $Apache::lonnet::passwdmin).'</li>';  
                                 } else {  
                                     $resulttext .= '<li>'.&mt('[_1] set to none',$titles{$rule}).'</li>';  
                                 }  
                             } else {  
                                 $resulttext .= '<li>'.&mt('[_1] set to [_2]',$titles{$rule},$confighash{'passwords'}{$rule}).'</li>';  
                             }  
                         }  
                         if (ref($confighash{'passwords'}{'chars'}) eq 'ARRAY') {  
                             if (@{$confighash{'passwords'}{'chars'}} > 0) {  
                                 my %rulenames = &Apache::lonlocal::texthash(  
                                                      uc => 'At least one upper case letter',  
                                                      lc => 'At least one lower case letter',  
                                                      num => 'At least one number',  
                                                      spec => 'At least one non-alphanumeric',  
                                                    );  
                                 my $needed = '<ul><li>'.  
                                              join('</li><li>',map {$rulenames{$_} } @{$confighash{'passwords'}{'chars'}}).  
                                              '</li></ul>';  
                                 $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$titles{'chars'},$needed).'</li>';  
                             } else {  
                                 $resulttext .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';  
                             }  
                         } else {  
                             $resulttext .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';  
                         }  
                     } elsif ($key eq 'crsownerchg') {  
                         if (ref($confighash{'passwords'}{'crsownerchg'}) eq 'HASH') {  
                             if ((@{$confighash{'passwords'}{'crsownerchg'}{'by'}} == 0) ||  
                                 (@{$confighash{'passwords'}{'crsownerchg'}{'for'}} == 0)) {  
                                 $resulttext .= '<li>'.&mt('Course owner may not change student passwords.').'</li>';  
                             } else {  
                                 my %crsownerstr;  
                                 foreach my $item ('by','for') {  
                                     if (ref($confighash{'passwords'}{'crsownerchg'}{$item}) eq 'ARRAY') {  
                                         foreach my $type (@{$confighash{'passwords'}{'crsownerchg'}{$item}}) {  
                                             if ($type eq 'default') {  
                                                 $crsownerstr{$item} .= $othertitle.', ';  
                                             } elsif ($usertypes->{$type} ne '') {  
                                                 $crsownerstr{$item} .= $usertypes->{$type}.', ';  
                                             }  
                                         }  
                                         $crsownerstr{$item} =~ s/\Q, \E$//;  
                                     }  
                                 }  
                                 $resulttext .= '<li>'.&mt('Course owner (with status: [_1]) may change passwords for students (with status: [_2]).',  
                                            $crsownerstr{'by'},$crsownerstr{'for'}).'</li>';  
                             }  
                         } else {  
                             $resulttext .= '<li>'.&mt('Course owner may not change student passwords.').'</li>';  
                         }  
                     }  
                     $resulttext .= '</ul></li>';  
                 }  
             }  
             $resulttext .= '</ul>';  
         } else {  
             $resulttext = &mt('No changes made to password settings');  
         }  
         my $cachetime = 24*60*60;  
         if ($updatedefaults) {  
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);  
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'domdefaults'} = 1;  
             }  
         }  
         if ($updateconf) {  
             &Apache::lonnet::do_cache_new('passwdconf',$dom,$confighash{'passwords'},$cachetime);  
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'passwdconf'} = 1;  
             }  
         }  
     } else {  
         $resulttext = '<span class="LC_error">'.  
             &mt('An error occurred: [_1]',$putresult).'</span>';  
     }  
     if ($errors) {  
         $resulttext .= '<p>'.&mt('The following errors occurred: ').'<ul>'.  
                        $errors.'</ul></p>';  
     }  
     return $resulttext;  
 }  
   
 sub password_rule_changes {  
     my ($prefix,$newvalues,$current,$changes) = @_;  
     return unless ((ref($newvalues) eq 'HASH') &&  
                    (ref($current) eq 'HASH') &&  
                    (ref($changes) eq 'HASH'));  
     my (@rules,%staticdefaults);  
     if ($prefix eq 'passwords') {  
         @rules = ('min','max','numsaved');  
     } elsif ($prefix eq 'secrets') {  
         @rules = ('min','max');  
     }  
     $staticdefaults{'min'} = $Apache::lonnet::passwdmin;  
     foreach my $rule (@rules) {  
         $env{'form.'.$prefix.'_'.$rule} =~ s/^\s+|\s+$//g;  
         my $ruleok;  
         if ($rule eq 'min') {  
             if ($env{'form.'.$prefix.'_'.$rule} =~ /^\d+$/) {  
                 if ($env{'form.'.$prefix.'_'.$rule} >= $staticdefaults{$rule}) {  
                     $ruleok = 1;  
                 }  
             }  
         } elsif (($env{'form.'.$prefix.'_'.$rule} =~ /^\d+$/) &&  
                  ($env{'form.'.$prefix.'_'.$rule} ne '0')) {  
             $ruleok = 1;  
         }  
         if ($ruleok) {  
             $newvalues->{$rule} = $env{'form.'.$prefix.'_'.$rule};  
             if (exists($current->{$rule})) {  
                 if ($newvalues->{$rule} ne $current->{$rule}) {  
                     $changes->{'rules'} = 1;  
                 }  
             } elsif ($rule eq 'min') {  
                 if ($staticdefaults{$rule} ne $newvalues->{$rule}) {  
                     $changes->{'rules'} = 1;  
                 }  
             } else {  
                 $changes->{'rules'} = 1;  
             }  
         } elsif (exists($current->{$rule})) {  
             $changes->{'rules'} = 1;  
         }  
     }  
     my @posschars = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_chars');  
     my @chars;  
     foreach my $item (sort(@posschars)) {  
         if ($item =~ /^(uc|lc|num|spec)$/) {  
             push(@chars,$item);  
         }  
     }  
     $newvalues->{'chars'} = \@chars;  
     unless ($changes->{'rules'}) {  
         if (ref($current->{'chars'}) eq 'ARRAY') {  
             my @diffs = &Apache::loncommon::compare_arrays($current->{'chars'},\@chars);  
             if (@diffs > 0) {  
                 $changes->{'rules'} = 1;  
             }  
         } else {  
             if (@chars > 0) {  
                 $changes->{'rules'} = 1;  
             }  
         }  
     }  
     return;  
 }  
   
 sub modify_usercreation {  sub modify_usercreation {
     my ($dom,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate,%save_usercreate);      my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate,%save_usercreate);
Line 15107  sub modify_usercreation { Line 10062  sub modify_usercreation {
             if ($key eq 'cancreate') {              if ($key eq 'cancreate') {
                 if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {                  if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {
                     foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {                      foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
                         if (($item eq 'requestcrs') || ($item eq 'course') || ($item eq 'author')) {                          if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||
                             $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};                              ($item eq 'captcha') || ($item eq 'recaptchakeys') ||
                         } else {                              ($item eq 'recaptchaversion')) {
                             $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};                              $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
                           } else {
                               $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
                         }                          }
                     }                      }
                 }                  }
Line 15313  sub modify_usercreation { Line 10270  sub modify_usercreation {
 }  }
   
 sub modify_selfcreation {  sub modify_selfcreation {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,$warningmsg,%curr_usercreation,%curr_usermodify,%curr_inststatus,%changes,%cancreate);      my ($resulttext,$warningmsg,%curr_usercreation,%curr_usermodify,%changes,%cancreate);
     my (%save_usercreate,%save_usermodify,%save_inststatus,@types,%usertypes);      my (%save_usercreate,%save_usermodify);
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);      my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
     my ($othertitle,$usertypesref,$typesref) = &Apache::loncommon::sorted_inst_types($dom);      if (ref($types) eq 'ARRAY') {
     if (ref($typesref) eq 'ARRAY') {          $usertypes->{'default'} = $othertitle;
         @types = @{$typesref};          push(@{$types},'default');
     }  
     if (ref($usertypesref) eq 'HASH') {  
         %usertypes = %{$usertypesref};  
     }      }
     $usertypes{'default'} = $othertitle;  
 #  #
 # Retrieve current domain configuration for self-creation of usernames from $domconfig{'usercreation'}.  # Retrieve current domain configuration for self-creation of usernames from $domconfig{'usercreation'}.
 #  #
Line 15334  sub modify_selfcreation { Line 10287  sub modify_selfcreation {
                 if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {                  if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {
                     foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {                      foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
                         if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||                          if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||
                             ($item eq 'captcha') || ($item eq 'recaptchakeys') ||                              ($item eq 'captcha') || ($item eq 'recaptchakeys') || 
                             ($item eq 'recaptchaversion') || ($item eq 'notify') ||                              ($item eq 'recaptchaversion') ||
                             ($item eq 'emailusername') || ($item eq 'shibenv') ||                              ($item eq 'emailusername') || ($item eq 'notify') ||
                             ($item eq 'selfcreateprocessing') || ($item eq 'emailverified') ||                              ($item eq 'selfcreateprocessing') || ($item eq 'shibenv')) {
                             ($item eq 'emailoptions') || ($item eq 'emaildomain')) {  
                             $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};                              $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
                         } else {                          } else {
                             $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};                              $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
Line 15364  sub modify_selfcreation { Line 10316  sub modify_selfcreation {
             }              }
         }          }
     }      }
 #  
 # Retrieve current domain configuration for institutional status types from $domconfig{'inststatus'}.  
 #  
     if (ref($domconfig{'inststatus'}) eq 'HASH') {  
         foreach my $key (keys(%{$domconfig{'inststatus'}})) {  
             if ($key eq 'inststatusguest') {  
                 $curr_inststatus{$key} = $domconfig{'inststatus'}{$key};  
             } else {  
                 $save_inststatus{$key} = $domconfig{'inststatus'}{$key};  
             }  
         }  
     }  
   
     my @contexts = ('selfcreate');      my @contexts = ('selfcreate');
     @{$cancreate{'selfcreate'}} = ();      @{$cancreate{'selfcreate'}} = ();
     %{$cancreate{'emailusername'}} = ();      %{$cancreate{'emailusername'}} = ();
     if (@types) {      @{$cancreate{'statustocreate'}} = ();
         @{$cancreate{'statustocreate'}} = ();  
     }  
     %{$cancreate{'selfcreateprocessing'}} = ();      %{$cancreate{'selfcreateprocessing'}} = ();
     %{$cancreate{'shibenv'}} = ();      %{$cancreate{'shibenv'}} = ();
     %{$cancreate{'emailverified'}} = ();  
     %{$cancreate{'emailoptions'}} = ();  
     %{$cancreate{'emaildomain'}} = ();  
     my %selfcreatetypes = (      my %selfcreatetypes = (
                              sso   => 'users authenticated by institutional single sign on',                               sso   => 'users authenticated by institutional single sign on',
                              login => 'users authenticated by institutional log-in',                               login => 'users authenticated by institutional log-in',
                              email => 'users verified by e-mail',                               email => 'users who provide a valid e-mail address for use as username',
                           );                            );
 #  #
 # Populate $cancreate{'selfcreate'} array reference with types of user, for which self-creation of user accounts  # Populate $cancreate{'selfcreate'} array reference with types of user, for which self-creation of user accounts
 # is permitted.  # is permitted.
 #  #
   
     my ($emailrules,$emailruleorder) = &Apache::lonnet::inst_userrules($dom,'email');      my @statuses;
       if (ref($domconfig{'inststatus'}) eq 'HASH') {
           if (ref($domconfig{'inststatus'}{'inststatusguest'}) eq 'ARRAY') {
               @statuses = @{$domconfig{'inststatus'}{'inststatusguest'}};
           }
       }
       push(@statuses,'default');
   
     my (@statuses,%email_rule);  
     foreach my $item ('login','sso','email') {      foreach my $item ('login','sso','email') {
         if ($item eq 'email') {          if ($item eq 'email') {
             if ($env{'form.cancreate_email'}) {              if ($env{'form.cancreate_email'}) {
                 if (@types) {                  push(@{$cancreate{'selfcreate'}},'email');
                     my @poss_statuses = &Apache::loncommon::get_env_multiple('form.selfassign');                  push(@contexts,'selfcreateprocessing');
                     foreach my $status (@poss_statuses) {                  foreach my $type (@statuses) {
                         if (grep(/^\Q$status\E$/,(@types,'default'))) {                      if ($type eq 'default') {
                             push(@statuses,$status);                          $cancreate{'selfcreateprocessing'}{$type} = $env{'form.cancreate_emailprocess'};
                         }                      } else { 
                     }                          $cancreate{'selfcreateprocessing'}{$type} = $env{'form.cancreate_emailprocess_'.$type};
                     $save_inststatus{'inststatusguest'} = \@statuses;  
                 } else {  
                     push(@statuses,'default');  
                 }  
                 if (@statuses) {  
                     my %curr_rule;  
                     if (ref($curr_usercreation{'email_rule'}) eq 'ARRAY') {  
                         foreach my $type (@statuses) {  
                             $curr_rule{$type} = $curr_usercreation{'email_rule'};  
                         }  
                     } elsif (ref($curr_usercreation{'email_rule'}) eq 'HASH') {  
                         foreach my $type (@statuses) {  
                             $curr_rule{$type} = $curr_usercreation{'email_rule'}{$type};  
                         }  
                     }  
                     push(@{$cancreate{'selfcreate'}},'email');  
                     push(@contexts,('selfcreateprocessing','emailverified','emailoptions'));  
                     my %curremaildom;  
                     if (ref($curr_usercreation{'cancreate'}{'emaildomain'}) eq 'HASH') {  
                         %curremaildom = %{$curr_usercreation{'cancreate'}{'emaildomain'}};  
                     }  
                     foreach my $type (@statuses) {  
                         if ($env{'form.cancreate_emailprocess_'.$type} =~ /^(?:approval|automatic)$/) {  
                             $cancreate{'selfcreateprocessing'}{$type} = $env{'form.cancreate_emailprocess_'.$type};  
                         }  
                         if ($env{'form.cancreate_usernameoptions_'.$type} =~ /^(?:all|first|free)$/) {  
                             $cancreate{'emailverified'}{$type} = $env{'form.cancreate_usernameoptions_'.$type};  
                         }  
                         if ($env{'form.cancreate_emailoptions_'.$type} =~ /^(any|inst|noninst|custom)$/) {  
 #  
 # Retrieve rules (if any) governing types of e-mail address which may be used to verify a username.  
 #  
                             my $chosen = $1;  
                             if (($chosen eq 'inst') || ($chosen eq 'noninst')) {  
                                 my $emaildom;  
                                 if ($env{'form.cancreate_emaildomain_'.$chosen.'_'.$type} =~ /^\@[^\@]+$/) {  
                                     $emaildom = $env{'form.cancreate_emaildomain_'.$chosen.'_'.$type};  
                                     $cancreate{'emaildomain'}{$type}{$chosen} = $emaildom;  
                                     if (ref($curremaildom{$type}) eq 'HASH') {  
                                         if (exists($curremaildom{$type}{$chosen})) {  
                                             if ($curremaildom{$type}{$chosen} ne $emaildom) {  
                                                 push(@{$changes{'cancreate'}},'emaildomain');  
                                             }  
                                         } elsif ($emaildom ne '') {  
                                             push(@{$changes{'cancreate'}},'emaildomain');  
                                         }  
                                     } elsif ($emaildom ne '') {  
                                         push(@{$changes{'cancreate'}},'emaildomain');  
                                     }  
                                 }  
                                 $cancreate{'emailoptions'}{$type} = $env{'form.cancreate_emailoptions_'.$type};  
                             } elsif ($chosen eq 'custom') {  
                                 my @possemail_rules = &Apache::loncommon::get_env_multiple('form.email_rule_'.$type);  
                                 $email_rule{$type} = [];  
                                 if (ref($emailrules) eq 'HASH') {  
                                     foreach my $rule (@possemail_rules) {  
                                         if (exists($emailrules->{$rule})) {  
                                             push(@{$email_rule{$type}},$rule);  
                                         }  
                                     }  
                                 }  
                                 if (@{$email_rule{$type}}) {  
                                     $cancreate{'emailoptions'}{$type} = 'custom';  
                                     if (ref($curr_rule{$type}) eq 'ARRAY') {  
                                         if (@{$curr_rule{$type}} > 0) {  
                                             foreach my $rule (@{$curr_rule{$type}}) {  
                                                 if (!grep(/^\Q$rule\E$/,@{$email_rule{$type}})) {  
                                                     push(@{$changes{'email_rule'}},$type);  
                                                 }  
                                             }  
                                         }  
                                         foreach my $type (@{$email_rule{$type}}) {  
                                             if (!grep(/^\Q$type\E$/,@{$curr_rule{$type}})) {  
                                                 push(@{$changes{'email_rule'}},$type);  
                                             }  
                                         }  
                                     } else {  
                                         push(@{$changes{'email_rule'}},$type);  
                                     }  
                                 }  
                             } else {  
                                 $cancreate{'emailoptions'}{$type} = $env{'form.cancreate_emailoptions_'.$type};  
                             }  
                         }  
                     }  
                     if (@types) {  
                         if (ref($curr_inststatus{'inststatusguest'}) eq 'ARRAY') {  
                             my @changed = &Apache::loncommon::compare_arrays(\@statuses,$curr_inststatus{'inststatusguest'});  
                             if (@changed) {  
                                 push(@{$changes{'inststatus'}},'inststatusguest');  
                             }  
                         } else {  
                             push(@{$changes{'inststatus'}},'inststatusguest');  
                         }  
                     }  
                 } else {  
                     delete($env{'form.cancreate_email'});  
                     if (ref($curr_inststatus{'inststatusguest'}) eq 'ARRAY') {  
                         if (@{$curr_inststatus{'inststatusguest'}} > 0) {  
                             push(@{$changes{'inststatus'}},'inststatusguest');  
                         }  
                     }  
                 }  
             } else {  
                 $save_inststatus{'inststatusguest'} = [];  
                 if (ref($curr_inststatus{'inststatusguest'}) eq 'ARRAY') {  
                     if (@{$curr_inststatus{'inststatusguest'}} > 0) {  
                         push(@{$changes{'inststatus'}},'inststatusguest');  
                     }                      }
                 }                  }
             }              }
Line 15528  sub modify_selfcreation { Line 10360  sub modify_selfcreation {
             }              }
         }          }
     }      }
     my (%userinfo,%savecaptcha);      my (@email_rule,%userinfo,%savecaptcha);
     my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();      my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();
 #  #
 # Populate $cancreate{'emailusername'}{$type} hash ref with information fields (if new user will provide data  # Populate $cancreate{'emailusername'}{$type} hash ref with information fields (if new user will provide data
Line 15537  sub modify_selfcreation { Line 10369  sub modify_selfcreation {
   
     if ($env{'form.cancreate_email'}) {      if ($env{'form.cancreate_email'}) {
         push(@contexts,'emailusername');          push(@contexts,'emailusername');
         if (@statuses) {          if (ref($types) eq 'ARRAY') {
             foreach my $type (@statuses) {              foreach my $type (@{$types}) {
                 if (ref($infofields) eq 'ARRAY') {                  if (ref($infofields) eq 'ARRAY') {
                     foreach my $field (@{$infofields}) {                      foreach my $field (@{$infofields}) {
                         if ($env{'form.canmodify_emailusername_'.$type.'_'.$field} =~ /^(required|optional)$/) {                          if ($env{'form.canmodify_emailusername_'.$type.'_'.$field} =~ /^(required|optional)$/) {
Line 15550  sub modify_selfcreation { Line 10382  sub modify_selfcreation {
         }          }
 #  #
 # Populate $cancreate{'notify'} hash ref with names of Domain Coordinators who are to be notified of  # Populate $cancreate{'notify'} hash ref with names of Domain Coordinators who are to be notified of
 # queued requests for self-creation of account verified by e-mail.  # queued requests for self-creation of account using e-mail address as username
 #  #
   
         my @approvalnotify = &Apache::loncommon::get_env_multiple('form.selfcreationnotifyapproval');          my @approvalnotify = &Apache::loncommon::get_env_multiple('form.selfcreationnotifyapproval');
Line 15570  sub modify_selfcreation { Line 10402  sub modify_selfcreation {
             push(@{$changes{'cancreate'}},'notify');              push(@{$changes{'cancreate'}},'notify');
         }          }
   
   #
   # Retrieve rules (if any) governing types of e-mail address which may be used as a username
   #
           @email_rule = &Apache::loncommon::get_env_multiple('form.email_rule');
         &process_captcha('cancreate',\%changes,\%savecaptcha,$curr_usercreation{'cancreate'});          &process_captcha('cancreate',\%changes,\%savecaptcha,$curr_usercreation{'cancreate'});
           if (ref($curr_usercreation{'email_rule'}) eq 'ARRAY') {
               if (@{$curr_usercreation{'email_rule'}} > 0) {
                   foreach my $type (@{$curr_usercreation{'email_rule'}}) {
                       if (!grep(/^\Q$type\E$/,@email_rule)) {
                           push(@{$changes{'email_rule'}},$type);
                       }
                   }
               }
               if (@email_rule > 0) {
                   foreach my $type (@email_rule) {
                       if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'email_rule'}})) {
                           push(@{$changes{'email_rule'}},$type);
                       }
                   }
               }
           } elsif (@email_rule > 0) {
               push(@{$changes{'email_rule'}},@email_rule);
           }
     }      }
 #    #  
 # Check if domain default is set appropriately, if self-creation of accounts is to be available for  # Check if domain default is set appropriately, if self-creation of accounts is to be available for
 # institutional log-in.  # institutional log-in.
 #  #
     if (grep(/^login$/,@{$cancreate{'selfcreate'}})) {      if (grep(/^login$/,@{$cancreate{'selfcreate'}})) {
           my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
         if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) ||           if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) || 
                ($domdefaults{'auth_def'} eq 'localauth'))) {                 ($domdefaults{'auth_def'} eq 'localauth'))) {
             $warningmsg = &mt('Although account creation has been set to be available for institutional logins, currently default authentication in this domain has not been set to support this.').' '.              $warningmsg = &mt('Although account creation has been set to be available for institutional logins, currently default authentication in this domain has not been set to support this.').' '.
Line 15595  sub modify_selfcreation { Line 10450  sub modify_selfcreation {
 # which the user may supply, if institutional data is unavailable.  # which the user may supply, if institutional data is unavailable.
 #  #
     if (($env{'form.cancreate_login'}) || ($env{'form.cancreate_sso'})) {      if (($env{'form.cancreate_login'}) || ($env{'form.cancreate_sso'})) {
         if (@types) {          if (ref($types) eq 'ARRAY') {
             @{$cancreate{'statustocreate'}} = &Apache::loncommon::get_env_multiple('form.statustocreate');              if (@{$types} > 1) {
             push(@contexts,'statustocreate');                  @{$cancreate{'statustocreate'}} = &Apache::loncommon::get_env_multiple('form.statustocreate');
             foreach my $type (@types) {                  push(@contexts,'statustocreate');
               } else {
                   undef($cancreate{'statustocreate'});
               } 
               foreach my $type (@{$types}) {
                 my @modifiable =  &Apache::loncommon::get_env_multiple('form.canmodify_'.$type);                  my @modifiable =  &Apache::loncommon::get_env_multiple('form.canmodify_'.$type);
                 foreach my $field (@fields) {                  foreach my $field (@fields) {
                     if (grep(/^\Q$field\E$/,@modifiable)) {                      if (grep(/^\Q$field\E$/,@modifiable)) {
Line 15609  sub modify_selfcreation { Line 10468  sub modify_selfcreation {
                 }                  }
             }              }
             if (ref($curr_usermodify{'selfcreate'}) eq 'HASH') {              if (ref($curr_usermodify{'selfcreate'}) eq 'HASH') {
                 foreach my $type (@types) {                  foreach my $type (@{$types}) {
                     if (ref($curr_usermodify{'selfcreate'}{$type}) eq 'HASH') {                      if (ref($curr_usermodify{'selfcreate'}{$type}) eq 'HASH') {
                         foreach my $field (@fields) {                          foreach my $field (@fields) {
                             if ($save_usermodify{'selfcreate'}{$type}{$field} ne                              if ($save_usermodify{'selfcreate'}{$type}{$field} ne
Line 15621  sub modify_selfcreation { Line 10480  sub modify_selfcreation {
                     }                      }
                 }                  }
             } else {              } else {
                 foreach my $type (@types) {                  foreach my $type (@{$types}) {
                     push(@{$changes{'selfcreate'}},$type);                      push(@{$changes{'selfcreate'}},$type);
                 }                  }
             }              }
Line 15670  sub modify_selfcreation { Line 10529  sub modify_selfcreation {
             }              }
         } elsif (ref($curr_usercreation{'cancreate'}{$item}) eq 'HASH') {          } elsif (ref($curr_usercreation{'cancreate'}{$item}) eq 'HASH') {
             if (ref($cancreate{$item}) eq 'HASH') {              if (ref($cancreate{$item}) eq 'HASH') {
                 foreach my $type (keys(%{$curr_usercreation{'cancreate'}{$item}})) {                  foreach my $curr (keys(%{$curr_usercreation{'cancreate'}{$item}})) {
                     if (ref($curr_usercreation{'cancreate'}{$item}{$type}) eq 'HASH') {                      if (ref($curr_usercreation{'cancreate'}{$item}{$curr}) eq 'HASH') {
                         foreach my $field (keys(%{$curr_usercreation{'cancreate'}{$item}{$type}})) {                          foreach my $field (keys(%{$curr_usercreation{'cancreate'}{$item}{$curr}})) {
                             unless ($curr_usercreation{'cancreate'}{$item}{$type}{$field} eq $cancreate{$item}{$type}{$field}) {                              unless ($curr_usercreation{'cancreate'}{$item}{$curr}{$field} eq $cancreate{$item}{$curr}{$field}) {
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {                                  if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                     push(@{$changes{'cancreate'}},$item);                                      push(@{$changes{'cancreate'}},$item);
                                 }                                  }
                             }                              }
                         }                          }
                     } elsif (($item eq 'selfcreateprocessing') || ($item eq 'emailverified') || ($item eq 'emailoptions')) {                      } elsif ($item eq 'selfcreateprocessing') {
                         if ($cancreate{$item}{$type} ne $curr_usercreation{'cancreate'}{$item}{$type}) {                          if ($cancreate{$item}{$curr} ne $curr_usercreation{'cancreate'}{$item}{$curr}) {
                               if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                   push(@{$changes{'cancreate'}},$item);
                               }
                           }
                       } else {
                           if (!$cancreate{$item}{$curr}) {
                             if (!grep(/^$item$/,@{$changes{'cancreate'}})) {                              if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                 push(@{$changes{'cancreate'}},$item);                                  push(@{$changes{'cancreate'}},$item);
                             }                              }
                         }                          }
                     }                      }
                 }                  }
                 foreach my $type (keys(%{$cancreate{$item}})) {                  foreach my $field (keys(%{$cancreate{$item}})) {
                     if (ref($cancreate{$item}{$type}) eq 'HASH') {                      if (ref($cancreate{$item}{$field}) eq 'HASH') {
                         foreach my $field (keys(%{$cancreate{$item}{$type}})) {                          foreach my $inner (keys(%{$cancreate{$item}{$field}})) {
                             if (ref($curr_usercreation{'cancreate'}{$item}{$type}) eq 'HASH') {                              if (ref($curr_usercreation{'cancreate'}{$item}{$field}) eq 'HASH') {
                                 unless ($curr_usercreation{'cancreate'}{$item}{$type}{$field} eq $cancreate{$item}{$type}{$field}) {                                  unless ($curr_usercreation{'cancreate'}{$item}{$field}{$inner} eq $cancreate{$item}{$field}{$inner}) {
                                     if (!grep(/^$item$/,@{$changes{'cancreate'}})) {                                      if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                         push(@{$changes{'cancreate'}},$item);                                          push(@{$changes{'cancreate'}},$item);
                                     }                                      }
Line 15702  sub modify_selfcreation { Line 10567  sub modify_selfcreation {
                                 }                                  }
                             }                              }
                         }                          }
                     } elsif (($item eq 'selfcreateprocessing') || ($item eq 'emailverified') || ($item eq 'emailoptions')) {                      } elsif ($item eq 'selfcreateprocessing') {
                         if ($cancreate{$item}{$type} ne $curr_usercreation{'cancreate'}{$item}{$type}) {                          if ($cancreate{$item}{$field} ne $curr_usercreation{'cancreate'}{$item}{$field}) {
                               if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                   push(@{$changes{'cancreate'}},$item);
                               }
                           }
                       } else {
                           if (!$curr_usercreation{'cancreate'}{$item}{$field}) {
                             if (!grep(/^$item$/,@{$changes{'cancreate'}})) {                              if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                 push(@{$changes{'cancreate'}},$item);                                  push(@{$changes{'cancreate'}},$item);
                             }                              }
Line 15718  sub modify_selfcreation { Line 10589  sub modify_selfcreation {
                         push(@{$changes{'cancreate'}},$item);                          push(@{$changes{'cancreate'}},$item);
                     }                      }
                 }                  }
             }              } elsif (ref($cancreate{$item}) eq 'HASH') {
         } elsif (($item eq 'selfcreateprocessing') || ($item eq 'emailverified') || ($item eq 'emailoptions')) {                  if (!$cancreate{$item}{$curr_usercreation{'cancreate'}{$item}}) {
             if (ref($cancreate{$item}) eq 'HASH') {                      if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {                          push(@{$changes{'cancreate'}},$item);
                     push(@{$changes{'cancreate'}},$item);                      }
                 }                  }
             }              }
         } elsif ($item eq 'emailusername') {          } elsif ($item eq 'emailusername') {
Line 15755  sub modify_selfcreation { Line 10626  sub modify_selfcreation {
     if (ref($cancreate{'selfcreateprocessing'}) eq 'HASH') {      if (ref($cancreate{'selfcreateprocessing'}) eq 'HASH') {
         $save_usercreate{'cancreate'}{'selfcreateprocessing'} = $cancreate{'selfcreateprocessing'};          $save_usercreate{'cancreate'}{'selfcreateprocessing'} = $cancreate{'selfcreateprocessing'};
     }      }
     if (ref($cancreate{'emailverified'}) eq 'HASH') {  
         $save_usercreate{'cancreate'}{'emailverified'} = $cancreate{'emailverified'};  
     }  
     if (ref($cancreate{'emailoptions'}) eq 'HASH') {  
         $save_usercreate{'cancreate'}{'emailoptions'} = $cancreate{'emailoptions'};  
     }  
     if (ref($cancreate{'emaildomain'}) eq 'HASH') {  
         $save_usercreate{'cancreate'}{'emaildomain'} = $cancreate{'emaildomain'};  
     }  
     if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {      if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {
         $save_usercreate{'cancreate'}{'statustocreate'} = $cancreate{'statustocreate'};          $save_usercreate{'cancreate'}{'statustocreate'} = $cancreate{'statustocreate'};
     }      }
Line 15771  sub modify_selfcreation { Line 10633  sub modify_selfcreation {
         $save_usercreate{'cancreate'}{'shibenv'} = $cancreate{'shibenv'};          $save_usercreate{'cancreate'}{'shibenv'} = $cancreate{'shibenv'};
     }      }
     $save_usercreate{'cancreate'}{'emailusername'} = $cancreate{'emailusername'};      $save_usercreate{'cancreate'}{'emailusername'} = $cancreate{'emailusername'};
     $save_usercreate{'email_rule'} = \%email_rule;      $save_usercreate{'emailrule'} = \@email_rule;
   
     my %userconfig_hash = (      my %userconfig_hash = (
             usercreation     => \%save_usercreate,              usercreation     => \%save_usercreate,
             usermodification => \%save_usermodify,              usermodification => \%save_usermodify,
             inststatus       => \%save_inststatus,  
     );      );
   
     my $putresult = &Apache::lonnet::put_dom('configuration',\%userconfig_hash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%userconfig_hash,
                                              $dom);                                               $dom);
 #  #
 # Accumulate details of changes to domain configuration for self-creation of usernames in $resulttext  # Accumulate details of changes to domain cofiguration for self-creation of usernames in $resulttext
 #  #
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
Line 15790  sub modify_selfcreation { Line 10650  sub modify_selfcreation {
             if (ref($changes{'cancreate'}) eq 'ARRAY') {              if (ref($changes{'cancreate'}) eq 'ARRAY') {
                 my %lt = &selfcreation_types();                  my %lt = &selfcreation_types();
                 foreach my $type (@{$changes{'cancreate'}}) {                  foreach my $type (@{$changes{'cancreate'}}) {
                     my $chgtext = '';                      my $chgtext;
                     if ($type eq 'selfcreate') {                      if ($type eq 'selfcreate') {
                         if (@{$cancreate{$type}} == 0) {                          if (@{$cancreate{$type}} == 0) {
                             $chgtext .= &mt('Self creation of a new user account is not permitted.');                              $chgtext .= &mt('Self creation of a new user account is not permitted.');
Line 15805  sub modify_selfcreation { Line 10665  sub modify_selfcreation {
                                 if (grep(/^(login|sso)$/,@{$cancreate{$type}})) {                                  if (grep(/^(login|sso)$/,@{$cancreate{$type}})) {
                                     if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {                                      if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {
                                         if (@{$cancreate{'statustocreate'}} == 0) {                                          if (@{$cancreate{'statustocreate'}} == 0) {
                                             $chgtext .= '<span class="LC_warning">'.                                              $chgtext .= '<br />'.
                                                         &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts via log-in or single sign-on.").                                                          '<span class="LC_warning">'.
                                                         '</span><br />';                                                          &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").
                                                           '</span>';
                                         }                                          }
                                     }                                      }
                                 }                                  }
                                 if (grep(/^email$/,@{$cancreate{$type}})) {  
                                     if (!@statuses) {  
                                         $chgtext .= '<span class="LC_warning">'.  
                                                     &mt("However, e-mail verification is currently set to 'unavailable' for all user types (including 'other'), so self-creation of accounts is not possible for non-institutional log-in.").  
                                                     '</span><br />';  
   
                                     }  
                                 }  
                             }                              }
                         }                          }
                     } elsif ($type eq 'shibenv') {                      } elsif ($type eq 'shibenv') {
                         if (keys(%{$cancreate{$type}}) == 0) {                          if (keys(%{$cancreate{$type}}) == 0) {
                             $chgtext .= &mt('Shibboleth-autheticated user does not use environment variables to set user information').'<br />';                               $chgtext .= &mt('Shibboleth-autheticated user does not use environment variables to set user information'); 
                         } else {                          } else {
                             $chgtext .= &mt('Shibboleth-autheticated user information set from environment variables, as follows:').                              $chgtext .= &mt('Shibboleth-autheticated user information set from environment variables, as follows:').
                                         '<ul>';                                          '<ul>';
Line 15836  sub modify_selfcreation { Line 10689  sub modify_selfcreation {
                                 }                                  }
                             }                              }
                             $chgtext .= '</ul>';                              $chgtext .= '</ul>';
                         }                          }  
                     } elsif ($type eq 'statustocreate') {                      } elsif ($type eq 'statustocreate') {
                         if ((ref($cancreate{'selfcreate'}) eq 'ARRAY') &&                          if ((ref($cancreate{'selfcreate'}) eq 'ARRAY') &&
                             (ref($cancreate{'statustocreate'}) eq 'ARRAY')) {                              (ref($cancreate{'statustocreate'}) eq 'ARRAY')) {
Line 15849  sub modify_selfcreation { Line 10702  sub modify_selfcreation {
                                                     &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").                                                      &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").
                                                     '</span>';                                                      '</span>';
                                     }                                      }
                                 } elsif (keys(%usertypes) > 0) {                                  } elsif (ref($usertypes) eq 'HASH') {
                                     if (grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {                                      if (grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {
                                         $chgtext .= &mt('Creation of a new account for an institutional user is restricted to the following institutional affiliation(s):');                                          $chgtext .= &mt('Creation of a new account for an institutional user is restricted to the following institutional affiliation(s):');
                                     } else {                                      } else {
Line 15860  sub modify_selfcreation { Line 10713  sub modify_selfcreation {
                                         if ($case eq 'default') {                                          if ($case eq 'default') {
                                             $chgtext .= '<li>'.$othertitle.'</li>';                                              $chgtext .= '<li>'.$othertitle.'</li>';
                                         } else {                                          } else {
                                             $chgtext .= '<li>'.$usertypes{$case}.'</li>';                                              $chgtext .= '<li>'.$usertypes->{$case}.'</li>';
                                         }                                          }
                                     }                                      }
                                     $chgtext .= '</ul>';                                      $chgtext .= '</ul>';
                                     if (!grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {                                      if (!grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {
                                         $chgtext .= '<span class="LC_warning">'.                                          $chgtext .= '<br /><span class="LC_warning">'.
                                                     &mt('However, users authenticated by institutional login/single sign on are not currently permitted to create accounts.').                                                      &mt('However, users authenticated by institutional login/single sign on are not currently permitted to create accounts.').
                                                     '</span>';                                                      '</span>';
                                     }                                      }
Line 15877  sub modify_selfcreation { Line 10730  sub modify_selfcreation {
                                     $chgtext .= &mt('Although institutional affiliations permitted to create accounts were changed, self creation of accounts is not currently permitted for any authentication types.');                                      $chgtext .= &mt('Although institutional affiliations permitted to create accounts were changed, self creation of accounts is not currently permitted for any authentication types.');
                                 }                                  }
                             }                              }
                             $chgtext .= '<br />';  
                         }                          }
                     } elsif ($type eq 'selfcreateprocessing') {                      } elsif ($type eq 'selfcreateprocessing') {
                         my %choices = &Apache::lonlocal::texthash (                          my %choices = &Apache::lonlocal::texthash (
                                                                     automatic => 'Automatic approval',                                                                      automatic => 'Automatic approval',
                                                                     approval  => 'Queued for approval',                                                                      approval  => 'Queued for approval',
                                                                   );                                                                    );
                         if (@types) {                          if (@statuses > 1) {
                             if (@statuses) {                              $chgtext .= &mt('Processing of requests to create account with e-mail address as username set as follows:'). 
                                 $chgtext .= &mt('Processing of requests to create account with e-mail verification set as follows:').                                          '<ul>';
                                             '<ul>';                             foreach my $type (@statuses) {
                                 foreach my $status (@statuses) {                                 if ($type eq 'default') {
                                     if ($status eq 'default') {                                     $chgtext .= '<li>'.$othertitle.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$type}}.'</li>';
                                         $chgtext .= '<li>'.$othertitle.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$status}}.'</li>';                                 } else {
                                     } else {                                     $chgtext .= '<li>'.$usertypes->{$type}.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$type}}.'</li>';
                                         $chgtext .= '<li>'.$usertypes{$status}.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$status}}.'</li>';                                 }
                                     }                             }
                                 }                             $chgtext .= '</ul>';
                                 $chgtext .= '</ul>';  
                             }  
                         } else {  
                             $chgtext .= &mt('Processing of requests to create account with e-mail verification set to: "[_1]"',  
                                             $choices{$cancreate{'selfcreateprocessing'}{'default'}});  
                         }  
                     } elsif ($type eq 'emailverified') {  
                         my %options = &Apache::lonlocal::texthash (  
                                                                     all   => 'Same as e-mail',  
                                                                     first => 'Omit @domain',  
                                                                     free  => 'Free to choose',  
                                                                   );  
                         if (@types) {  
                             if (@statuses) {  
                                 $chgtext .= &mt('For self-created accounts verified by e-mail address, username is set as follows:').  
                                             '<ul>';  
                                 foreach my $status (@statuses) {  
                                     if ($status eq 'default') {  
                                         $chgtext .= '<li>'.$othertitle.' -- '.$options{$cancreate{'emailverified'}{$status}}.'</li>';  
                                     } else {  
                                         $chgtext .= '<li>'.$usertypes{$status}.' -- '.$options{$cancreate{'emailverified'}{$status}}.'</li>';  
                                     }  
                                 }  
                                 $chgtext .= '</ul>';  
                             }  
                         } else {  
                             $chgtext .= &mt("For self-created accounts verified by e-mail address, user's username is: '[_1]'",  
                                             $options{$cancreate{'emailverified'}{'default'}});  
                         }  
                     } elsif ($type eq 'emailoptions') {  
                         my %options = &Apache::lonlocal::texthash (  
                                                                     any     => 'Any e-mail',  
                                                                     inst    => 'Institutional only',  
                                                                     noninst => 'Non-institutional only',  
                                                                     custom  => 'Custom restrictions',  
                                                                   );  
                         if (@types) {  
                             if (@statuses) {  
                                 $chgtext .= &mt('For self-created accounts verified by e-mail address, requirements for e-mail address are as follows:').  
                                             '<ul>';  
                                 foreach my $status (@statuses) {  
                                     if ($type eq 'default') {  
                                         $chgtext .= '<li>'.$othertitle.' -- '.$options{$cancreate{'emailoptions'}{$status}}.'</li>';  
                                     } else {  
                                         $chgtext .= '<li>'.$usertypes{$status}.' -- '.$options{$cancreate{'emailoptions'}{$status}}.'</li>';  
                                     }  
                                 }  
                                 $chgtext .= '</ul>';  
                             }  
                         } else {                          } else {
                             if ($cancreate{'emailoptions'}{'default'} eq 'any') {                             $chgtext .= &mt('Processing of requests to create account with e-mail address as username set to: "[_1]"',
                                 $chgtext .= &mt('For self-created accounts verified by e-mail address, any e-mail may be used');                                           $choices{$cancreate{'selfcreateprocessing'}{'default'}});
                             } else {  
                                 $chgtext .= &mt('For self-created accounts verified by e-mail address, e-mail restricted to: "[_1]"',  
                                                 $options{$cancreate{'emailoptions'}{'default'}});  
                             }  
                         }  
                     } elsif ($type eq 'emaildomain') {  
                         my $output;  
                         if (@statuses) {  
                             foreach my $type (@statuses) {  
                                 if (ref($cancreate{'emaildomain'}{$type}) eq 'HASH') {  
                                     if ($cancreate{'emailoptions'}{$type} eq 'inst') {  
                                         if ($type eq 'default') {  
                                             if ((ref($cancreate{'emaildomain'}{$type}) ne 'HASH') ||  
                                                 ($cancreate{'emaildomain'}{$type}{'inst'} eq '')) {  
                                                 $output = '<li>'.$othertitle.' -- '.&mt('No restriction on e-mail domain').'</li>';  
                                             } else {  
                                                 $output = '<li>'.$othertitle.' -- '.&mt("User's e-mail address needs to end: [_1]",  
                                                                                         $cancreate{'emaildomain'}{$type}{'inst'}).'</li>';  
                                             }  
                                         } else {  
                                             if ((ref($cancreate{'emaildomain'}{$type}) ne 'HASH') ||  
                                                 ($cancreate{'emaildomain'}{$type}{'inst'} eq '')) {  
                                                 $output = '<li>'.$usertypes{$type}.' -- '.&mt('No restriction on e-mail domain').'</li>';  
                                             } else {  
                                                 $output = '<li>'.$usertypes{$type}.' -- '.&mt("User's e-mail address needs to end: [_1]",  
                                                                                               $cancreate{'emaildomain'}{$type}{'inst'}).'</li>';  
                                             }  
                                         }  
                                     } elsif ($cancreate{'emailoptions'}{$type} eq 'noninst') {  
                                         if ($type eq 'default') {  
                                             if ((ref($cancreate{'emaildomain'}{$type}) ne 'HASH') ||  
                                                 ($cancreate{'emaildomain'}{$type}{'noninst'} eq '')) {  
                                                 $output = '<li>'.$othertitle.' -- '.&mt('No restriction on e-mail domain').'</li>';  
                                             } else {  
                                                 $output = '<li>'.$othertitle.' -- '.&mt("User's e-mail address must not end: [_1]",  
                                                                                         $cancreate{'emaildomain'}{$type}{'noninst'}).'</li>';  
                                             }  
                                         } else {  
                                             if ((ref($cancreate{'emaildomain'}{$type}) ne 'HASH') ||  
                                                 ($cancreate{'emaildomain'}{$type}{'noninst'} eq '')) {  
                                                 $output = '<li>'.$usertypes{$type}.' -- '.&mt('No restriction on e-mail domain').'</li>';  
                                             } else {  
                                                 $output = '<li>'.$usertypes{$type}.' -- '.&mt("User's e-mail address must not end: [_1]",  
                                                                                                 $cancreate{'emaildomain'}{$type}{'noninst'}).'</li>';  
                                             }  
                                         }  
                                     }  
                                 }  
                             }  
                         }  
                         if ($output ne '') {  
                             $chgtext .= &mt('For self-created accounts verified by e-mail address:').  
                                         '<ul>'.$output.'</ul>';  
                         }                          }
                     } elsif ($type eq 'captcha') {                      } elsif ($type eq 'captcha') {
                         if ($savecaptcha{$type} eq 'notused') {                          if ($savecaptcha{$type} eq 'notused') {
Line 16036  sub modify_selfcreation { Line 10786  sub modify_selfcreation {
                         }                          }
                     } elsif ($type eq 'emailusername') {                      } elsif ($type eq 'emailusername') {
                         if (ref($cancreate{'emailusername'}) eq 'HASH') {                          if (ref($cancreate{'emailusername'}) eq 'HASH') {
                             if (@statuses) {                              if (ref($types) eq 'ARRAY') {
                                 foreach my $type (@statuses) {                                  foreach my $type (@{$types}) {
                                     if (ref($cancreate{'emailusername'}{$type}) eq 'HASH') {                                      if (ref($cancreate{'emailusername'}{$type}) eq 'HASH') {
                                         if (keys(%{$cancreate{'emailusername'}{$type}}) > 0) {                                          if (keys(%{$cancreate{'emailusername'}{$type}}) > 0) {
                                             $chgtext .= &mt('When self-creating account with e-mail verification, the following information will be provided by [_1]:',"'$usertypes{$type}'").                                              $chgtext .= &mt('When self-creating account with e-mail as username, the following information will be provided by [_1]:',"'$usertypes->{$type}'").
                                                     '<ul>';                                                      '<ul>';
                                             foreach my $field (@{$infofields}) {                                              foreach my $field (@{$infofields}) {
                                                 if ($cancreate{'emailusername'}{$type}{$field}) {                                                  if ($cancreate{'emailusername'}{$type}{$field}) {
Line 16049  sub modify_selfcreation { Line 10799  sub modify_selfcreation {
                                             }                                              }
                                             $chgtext .= '</ul>';                                              $chgtext .= '</ul>';
                                         } else {                                          } else {
                                             $chgtext .= &mt('When self creating account with e-mail verification, no information besides e-mail address will be provided by [_1].',"'$usertypes{$type}'").'<br />';                                              $chgtext .= &mt('When self creating account with e-mail as username, no information besides e-mail address will be provided by [_1].',"'$usertypes->{$type}'").'<br />';
                                         }                                          }
                                     } else {                                      } else {
                                         $chgtext .= &mt('When self creating account with e-mail verification, no information besides e-mail address will be provided by [_1].',"'$usertypes{$type}'").'<br />';                                          $chgtext .= &mt('When self creating account with e-mail as username, no information besides e-mail address will be provided by [_1].',"'$usertypes->{$type}'").'<br />';
                                     }                                      }
                                 }                                  }
                             }                              }
                         }                          }
                     } elsif ($type eq 'notify') {                      } elsif ($type eq 'notify') {
                         my $numapprove = 0;                          $chgtext = &mt('No Domain Coordinators will receive notification of username requests requiring approval.');
                         if (ref($changes{'cancreate'}) eq 'ARRAY') {                          if (ref($changes{'cancreate'}) eq 'ARRAY') {
                             if ((grep(/^notify$/,@{$changes{'cancreate'}})) && (ref($cancreate{'notify'}) eq 'HASH')) {                              if ((grep(/^notify$/,@{$changes{'cancreate'}})) && (ref($cancreate{'notify'}) eq 'HASH')) {
                                 if ($cancreate{'notify'}{'approval'}) {                                  if ($cancreate{'notify'}{'approval'}) {
                                     $chgtext .= &mt('Notification of username requests requiring approval will be sent to: ').$cancreate{'notify'}{'approval'};                                      $chgtext = &mt('Notification of username requests requiring approval will be sent to: ').$cancreate{'notify'}{'approval'};
                                     $numapprove ++;  
                                 }                                  }
                             }                              }
                         }                          }
                         unless ($numapprove) {  
                             $chgtext .= &mt('No Domain Coordinators will receive notification of username requests requiring approval.');  
                         }  
                     }                      }
                     if ($chgtext) {                      if ($chgtext) {
                         $resulttext .= '<li>'.$chgtext.'</li>';                          $resulttext .= '<li>'.$chgtext.'</li>';
                     }                      }
                 }                  }
             }              }
             if ((ref($changes{'email_rule'}) eq 'ARRAY') && (@{$changes{'email_rule'}} > 0)) {              if (ref($changes{'email_rule'}) eq 'ARRAY') {
                 my ($emailrules,$emailruleorder) =                  my ($emailrules,$emailruleorder) =
                     &Apache::lonnet::inst_userrules($dom,'email');                      &Apache::lonnet::inst_userrules($dom,'email');
                 foreach my $type (@{$changes{'email_rule'}}) {                  my $chgtext = '<ul>';
                     if (ref($email_rule{$type}) eq 'ARRAY') {                  foreach my $type (@email_rule) {
                         my $chgtext = '<ul>';                      if (ref($emailrules->{$type}) eq 'HASH') {
                         foreach my $rule (@{$email_rule{$type}}) {                          $chgtext .= '<li>'.$emailrules->{$type}{'name'}.'</li>';
                             if (ref($emailrules->{$rule}) eq 'HASH') {  
                                 $chgtext .= '<li>'.$emailrules->{$rule}{'name'}.'</li>';  
                             }  
                         }  
                         $chgtext .= '</ul>';  
                         my $typename;  
                         if (@types) {  
                             if ($type eq 'default') {  
                                 $typename = $othertitle;  
                             } else {  
                                 $typename = $usertypes{$type};  
                             }  
                             $chgtext .= &mt('(Affiliation: [_1])',$typename);  
                         }  
                         if (@{$email_rule{$type}} > 0) {  
                             $resulttext .= '<li>'.  
                                            &mt('Accounts may not be created by users verified by e-mail, for e-mail addresses of the following types: ',  
                                                $usertypes{$type}).  
                                            $chgtext.  
                                            '</li>';  
                         } else {  
                             $resulttext .= '<li>'.  
                                            &mt('There are now no restrictions on e-mail addresses which may be used for verification when a user requests an account.').  
                                            '</li>'.  
                                            &mt('(Affiliation: [_1])',$typename);  
                         }  
                     }                      }
                 }                  }
             }                  $chgtext .= '</ul>';
             if (ref($changes{'inststatus'}) eq 'ARRAY') {                  if (@email_rule > 0) {
                 if (ref($save_inststatus{'inststatusguest'}) eq 'ARRAY') {                      $resulttext .= '<li>'.
                     if (@{$save_inststatus{'inststatusguest'}} > 0) {                                     &mt('Accounts may not be created by users self-enrolling with e-mail addresses of the following types: ').
                         my $chgtext = '<ul>';                                         $chgtext.
                         foreach my $type (@{$save_inststatus{'inststatusguest'}}) {                                     '</li>';
                             $chgtext .= '<li>'.$usertypes{$type}.'</li>';                  } else {
                         }                      $resulttext .= '<li>'.
                         $chgtext .= '</ul>';                                     &mt('There are now no restrictions on e-mail addresses which may be used as a username when self-enrolling.').
                         $resulttext .= '<li>'.                                     '</li>';
                                        &mt('A user will self-report one of the following affiliations when requesting an account verified by e-mail: ').  
                                           $chgtext.  
                                        '</li>';  
                     } else {  
                         $resulttext .= '<li>'.  
                                        &mt('No affiliations available for self-reporting when requesting an account verified by e-mail.').  
                                        '</li>';  
                     }  
                 }                  }
             }              }
             if (ref($changes{'selfcreate'}) eq 'ARRAY') {              if (ref($changes{'selfcreate'}) eq 'ARRAY') {
Line 16136  sub modify_selfcreation { Line 10848  sub modify_selfcreation {
                 my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();                  my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
                 foreach my $type (@{$changes{'selfcreate'}}) {                  foreach my $type (@{$changes{'selfcreate'}}) {
                     my $typename = $type;                      my $typename = $type;
                     if (keys(%usertypes) > 0) {                      if (ref($usertypes) eq 'HASH') {
                         if ($usertypes{$type} ne '') {                          if ($usertypes->{$type} ne '') {
                             $typename = $usertypes{$type};                              $typename = $usertypes->{$type};
                         }                          }
                     }                      }
                     my @modifiable;                      my @modifiable;
Line 16161  sub modify_selfcreation { Line 10873  sub modify_selfcreation {
                 $resulttext .= '</ul></li>';                  $resulttext .= '</ul></li>';
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
             my $cachetime = 24*60*60;  
             $domdefaults{'inststatusguest'} = $save_inststatus{'inststatusguest'};  
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);  
             if (ref($lastactref) eq 'HASH') {  
                 $lastactref->{'domdefaults'} = 1;  
             }  
         } else {          } else {
             $resulttext = &mt('No changes made to self-creation settings');              $resulttext = &mt('No changes made to self-creation settings');
         }          }
Line 16181  sub modify_selfcreation { Line 10887  sub modify_selfcreation {
 }  }
   
 sub process_captcha {  sub process_captcha {
     my ($container,$changes,$newsettings,$currsettings) = @_;      my ($container,$changes,$newsettings,$current) = @_;
     return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH'));      return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH') || (ref($current) eq 'HASH'));
     $newsettings->{'captcha'} = $env{'form.'.$container.'_captcha'};      $newsettings->{'captcha'} = $env{'form.'.$container.'_captcha'};
     unless ($newsettings->{'captcha'} eq 'recaptcha' || $newsettings->{'captcha'} eq 'notused') {      unless ($newsettings->{'captcha'} eq 'recaptcha' || $newsettings->{'captcha'} eq 'notused') {
         $newsettings->{'captcha'} = 'original';          $newsettings->{'captcha'} = 'original';
     }      }
     my %current;      if ($current->{'captcha'} ne $newsettings->{'captcha'}) {
     if (ref($currsettings) eq 'HASH') {  
         %current = %{$currsettings};  
     }  
     if ($current{'captcha'} ne $newsettings->{'captcha'}) {  
         if ($container eq 'cancreate') {          if ($container eq 'cancreate') {
             if (ref($changes->{'cancreate'}) eq 'ARRAY') {              if (ref($changes->{'cancreate'}) eq 'ARRAY') {
                 push(@{$changes->{'cancreate'}},'captcha');                  push(@{$changes->{'cancreate'}},'captcha');
             } elsif (!defined($changes->{'cancreate'})) {              } elsif (!defined($changes->{'cancreate'})) {
                 $changes->{'cancreate'} = ['captcha'];                  $changes->{'cancreate'} = ['captcha'];
             }              }
         } elsif ($container eq 'passwords') {  
             $changes->{'reset'} = 1;  
         } else {          } else {
             $changes->{'captcha'} = 1;              $changes->{'captcha'} = 1;
         }          }
Line 16221  sub process_captcha { Line 10921  sub process_captcha {
         }          }
         $newsettings->{'recaptchaversion'} = $newversion;          $newsettings->{'recaptchaversion'} = $newversion;
     }      }
     if (ref($current{'recaptchakeys'}) eq 'HASH') {      if (ref($current->{'recaptchakeys'}) eq 'HASH') {
         $currpub = $current{'recaptchakeys'}{'public'};          $currpub = $current->{'recaptchakeys'}{'public'};
         $currpriv = $current{'recaptchakeys'}{'private'};          $currpriv = $current->{'recaptchakeys'}{'private'};
         unless ($newsettings->{'captcha'} eq 'recaptcha') {          unless ($newsettings->{'captcha'} eq 'recaptcha') {
             $newsettings->{'recaptchakeys'} = {              $newsettings->{'recaptchakeys'} = {
                                                  public  => '',                                                   public  => '',
Line 16231  sub process_captcha { Line 10931  sub process_captcha {
                                               }                                                }
         }          }
     }      }
     if ($current{'captcha'} eq 'recaptcha') {      if ($current->{'captcha'} eq 'recaptcha') {
         $currversion = $current{'recaptchaversion'};          $currversion = $current->{'recaptchaversion'};
         if ($currversion ne '2') {          if ($currversion ne '2') {
             $currversion = 1;              $currversion = 1;
         }          }
Line 16244  sub process_captcha { Line 10944  sub process_captcha {
             } elsif (!defined($changes->{'cancreate'})) {              } elsif (!defined($changes->{'cancreate'})) {
                 $changes->{'cancreate'} = ['recaptchaversion'];                  $changes->{'cancreate'} = ['recaptchaversion'];
             }              }
         } elsif ($container eq 'passwords') {  
             $changes->{'reset'} = 1;  
         } else {          } else {
             $changes->{'recaptchaversion'} = 1;              $changes->{'recaptchaversion'} = 1;
         }          }
Line 16257  sub process_captcha { Line 10955  sub process_captcha {
             } elsif (!defined($changes->{'cancreate'})) {              } elsif (!defined($changes->{'cancreate'})) {
                 $changes->{'cancreate'} = ['recaptchakeys'];                  $changes->{'cancreate'} = ['recaptchakeys'];
             }              }
         } elsif ($container eq 'passwords') {  
             $changes->{'reset'} = 1;  
         } else {          } else {
             $changes->{'recaptchakeys'} = 1;              $changes->{'recaptchakeys'} = 1;
         }          }
Line 16373  sub modify_defaults { Line 11069  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',      my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def','portal_def');
                  'portal_def');  
     my @authtypes = ('internal','krb4','krb5','localauth');      my @authtypes = ('internal','krb4','krb5','localauth');
     foreach my $item (@items) {      foreach my $item (@items) {
         $newvalues{$item} = $env{'form.'.$item};          $newvalues{$item} = $env{'form.'.$item};
Line 16412  sub modify_defaults { Line 11107  sub modify_defaults {
             }              }
         } elsif ($item eq 'portal_def') {          } elsif ($item eq 'portal_def') {
             if ($newvalues{$item} ne '') {              if ($newvalues{$item} ne '') {
                 if ($newvalues{$item} =~ /^https?\:\/\/(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])\/?$/) {                  unless ($newvalues{$item} =~ /^https?\:\/\/(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])\/?$/) {
                     foreach my $field ('email','web') {  
                         if ($env{'form.'.$item.'_'.$field}) {  
                             $newvalues{$item.'_'.$field} = $env{'form.'.$item.'_'.$field};  
                         }  
                     }  
                 } else {  
                     push(@errors,$item);                      push(@errors,$item);
                 }                  }
             }              }
         }          }
         if (grep(/^\Q$item\E$/,@errors)) {          if (grep(/^\Q$item\E$/,@errors)) {
             $newvalues{$item} = $domdefaults{$item};              $newvalues{$item} = $domdefaults{$item};
             if ($item eq 'portal_def') {  
                 if ($domdefaults{$item}) {  
                     foreach my $field ('email','web') {  
                         if (exists($domdefaults{$item.'_'.$field})) {  
                             $newvalues{$item.'_'.$field} = $domdefaults{$item.'_'.$field};  
                         }  
                     }  
                 }  
             }  
         } elsif ($domdefaults{$item} ne $newvalues{$item}) {          } elsif ($domdefaults{$item} ne $newvalues{$item}) {
             $changes{$item} = 1;              $changes{$item} = 1;
         }          }
         if ($item eq 'portal_def') {  
             unless (grep(/^\Q$item\E$/,@errors)) {  
                 if ($newvalues{$item} eq '') {  
                     foreach my $field ('email','web') {  
                         if (exists($domdefaults{$item.'_'.$field})) {  
                             delete($domdefaults{$item.'_'.$field});  
                         }  
                     }  
                 } else {  
                     unless ($changes{$item}) {  
                         foreach my $field ('email','web') {  
                             if ($domdefaults{$item.'_'.$field} ne $newvalues{$item.'_'.$field}) {  
                                 $changes{$item} = 1;  
                                 last;  
                             }  
                         }  
                     }  
                     foreach my $field ('email','web') {  
                         if ($newvalues{$item.'_'.$field}) {  
                             $domdefaults{$item.'_'.$field} = $newvalues{$item.'_'.$field};  
                         } elsif (exists($domdefaults{$item.'_'.$field})) {  
                             delete($domdefaults{$item.'_'.$field});  
                         }  
                     }  
                 }  
             }  
         }  
         $domdefaults{$item} = $newvalues{$item};          $domdefaults{$item} = $newvalues{$item};
     }      }
     my %staticdefaults = (  
                            'intauth_cost'   => 10,  
                            'intauth_check'  => 0,  
                            'intauth_switch' => 0,  
                          );  
     foreach my $item ('intauth_cost','intauth_check','intauth_switch') {  
         if (exists($domdefaults{$item})) {  
             $newvalues{$item} = $domdefaults{$item};  
         } else {  
             $newvalues{$item} = $staticdefaults{$item};  
         }  
     }  
     my ($unamemaprules,$ruleorder);  
     my @possunamemaprules = &Apache::loncommon::get_env_multiple('form.unamemap_rule');  
     if (@possunamemaprules) {  
         ($unamemaprules,$ruleorder) =  
             &Apache::lonnet::inst_userrules($dom,'unamemap');  
         if ((ref($unamemaprules) eq 'HASH') && (ref($ruleorder) eq 'ARRAY')) {  
             if (@{$ruleorder} > 0) {  
                 my %possrules;  
                 map { $possrules{$_} = 1; } @possunamemaprules;  
                 foreach my $rule (@{$ruleorder}) {  
                     if ($possrules{$rule}) {  
                         push(@{$newvalues{'unamemap_rule'}},$rule);  
                     }  
                 }  
             }  
         }  
     }  
     if (ref($domdefaults{'unamemap_rule'}) eq 'ARRAY') {  
         if (ref($newvalues{'unamemap_rule'}) eq 'ARRAY') {  
             my @rulediffs = &Apache::loncommon::compare_arrays($domdefaults{'unamemap_rule'},  
                                                                $newvalues{'unamemap_rule'});  
             if (@rulediffs) {  
                 $changes{'unamemap_rule'} = 1;  
                 $domdefaults{'unamemap_rule'} = $newvalues{'unamemap_rule'};  
             }  
         } elsif (@{$domdefaults{'unamemap_rule'}} > 0) {  
             $changes{'unamemap_rule'} = 1;  
             delete($domdefaults{'unamemap_rule'});  
         }  
     } elsif (ref($newvalues{'unamemap_rule'}) eq 'ARRAY') {  
         if (@{$newvalues{'unamemap_rule'}} > 0) {  
             $changes{'unamemap_rule'} = 1;  
             $domdefaults{'unamemap_rule'} = $newvalues{'unamemap_rule'};  
         }  
     }  
     my %defaults_hash = (      my %defaults_hash = (
                          defaults => \%newvalues,                           defaults => \%newvalues,
                         );                          );
Line 16531  sub modify_defaults { Line 11137  sub modify_defaults {
     }      }
     my @todelete = &Apache::loncommon::get_env_multiple('form.inststatus_delete');      my @todelete = &Apache::loncommon::get_env_multiple('form.inststatus_delete');
     my @allpos;      my @allpos;
       my %guests;
     my %alltypes;      my %alltypes;
     my @inststatusguest;      my ($currtitles,$currguests,$currorder);
     if (ref($currinststatus) eq 'HASH') {  
         if (ref($currinststatus->{'inststatusguest'}) eq 'ARRAY') {  
             foreach my $type (@{$currinststatus->{'inststatusguest'}}) {  
                 unless (grep(/^\Q$type\E$/,@todelete)) {  
                     push(@inststatusguest,$type);  
                 }  
             }  
         }  
     }  
     my ($currtitles,$currorder);  
     if (ref($currinststatus) eq 'HASH') {      if (ref($currinststatus) eq 'HASH') {
         if (ref($currinststatus->{'inststatusorder'}) eq 'ARRAY') {          if (ref($currinststatus->{'inststatusorder'}) eq 'ARRAY') {
             foreach my $type (@{$currinststatus->{'inststatusorder'}}) {              foreach my $type (@{$currinststatus->{'inststatusorder'}}) {
Line 16557  sub modify_defaults { Line 11154  sub modify_defaults {
                     $allpos[$position] = $type;                      $allpos[$position] = $type;
                     $alltypes{$type} = $env{'form.inststatus_title_'.$type};                      $alltypes{$type} = $env{'form.inststatus_title_'.$type};
                     $alltypes{$type} =~ s/`//g;                      $alltypes{$type} =~ s/`//g;
                       if ($env{'form.inststatus_guest_'.$type}) {
                           $guests{$type} = 1;
                       }
                 }                  }
             }              }
               if (ref($currinststatus->{'inststatusguest'}) eq 'ARRAY') {
                   $currguests = join(',',@{$currinststatus->{'inststatusguest'}});
               }
             $currorder = join(',',@{$currinststatus->{'inststatusorder'}});              $currorder = join(',',@{$currinststatus->{'inststatusorder'}});
             $currtitles =~ s/,$//;              $currtitles =~ s/,$//;
         }          }
Line 16567  sub modify_defaults { Line 11170  sub modify_defaults {
         my $newtype = $env{'form.addinststatus'};          my $newtype = $env{'form.addinststatus'};
         $newtype =~ s/\W//g;          $newtype =~ s/\W//g;
         unless (exists($alltypes{$newtype})) {          unless (exists($alltypes{$newtype})) {
               if ($env{'form.addinststatus_guest'}) {
                   $guests{$newtype} = 1;
               }
             $alltypes{$newtype} = $env{'form.addinststatus_title'};              $alltypes{$newtype} = $env{'form.addinststatus_title'};
             $alltypes{$newtype} =~ s/`//g;               $alltypes{$newtype} =~ s/`//g; 
             my $position = $env{'form.addinststatus_pos'};              my $position = $env{'form.addinststatus_pos'};
Line 16576  sub modify_defaults { Line 11182  sub modify_defaults {
             }              }
         }          }
     }      }
     my @orderedstatus;      my (@orderedstatus,@orderedguests);
     foreach my $type (@allpos) {      foreach my $type (@allpos) {
         unless (($type eq '') || (grep(/^\Q$type\E$/,@orderedstatus))) {          unless (($type eq '') || (grep(/^\Q$type\E$/,@orderedstatus))) {
             push(@orderedstatus,$type);              push(@orderedstatus,$type);
               if ($guests{$type}) {
                   push(@orderedguests,$type);
               }
         }          }
     }      }
     foreach my $type (keys(%alltypes)) {      foreach my $type (keys(%alltypes)) {
Line 16590  sub modify_defaults { Line 11199  sub modify_defaults {
     $defaults_hash{'inststatus'} = {      $defaults_hash{'inststatus'} = {
                                      inststatustypes => \%alltypes,                                       inststatustypes => \%alltypes,
                                      inststatusorder => \@orderedstatus,                                       inststatusorder => \@orderedstatus,
                                      inststatusguest => \@inststatusguest,                                       inststatusguest => \@orderedguests,
                                    };                                     };
     if (ref($defaults_hash{'inststatus'}) eq 'HASH') {      if (ref($defaults_hash{'inststatus'}) eq 'HASH') {
         foreach my $item ('inststatustypes','inststatusorder','inststatusguest') {          foreach my $item ('inststatustypes','inststatusorder','inststatusguest') {
Line 16600  sub modify_defaults { Line 11209  sub modify_defaults {
     if ($currorder ne join(',',@orderedstatus)) {      if ($currorder ne join(',',@orderedstatus)) {
         $changes{'inststatus'}{'inststatusorder'} = 1;          $changes{'inststatus'}{'inststatusorder'} = 1;
     }      }
       if ($currguests ne join(',',@orderedguests)) {
           $changes{'inststatus'}{'inststatusguest'} = 1;
       }
     my $newtitles;      my $newtitles;
     foreach my $item (@orderedstatus) {      foreach my $item (@orderedstatus) {
         $newtitles .= $alltypes{$item}.',';          $newtitles .= $alltypes{$item}.',';
Line 16618  sub modify_defaults { Line 11230  sub modify_defaults {
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
                 if ($item eq 'inststatus') {                  if ($item eq 'inststatus') {
                     if (ref($changes{'inststatus'}) eq 'HASH') {                      if (ref($changes{'inststatus'}) eq 'HASH') {
                         if (@orderedstatus) {                          if (($changes{'inststatus'}{'inststatustypes'}) || $changes{'inststatus'}{'inststatusorder'}) {
                             $resulttext .= '<li>'.&mt('Institutional user status types set to:').' ';                              $resulttext .= '<li>'.&mt('Institutional user status types set to:').' ';
                             foreach my $type (@orderedstatus) {                               foreach my $type (@orderedstatus) { 
                                 $resulttext .= $alltypes{$type}.', ';                                  $resulttext .= $alltypes{$type}.', ';
                             }                              }
                             $resulttext =~ s/, $//;                              $resulttext =~ s/, $//;
                             $resulttext .= '</li>';                              $resulttext .= '</li>';
                         } else {  
                             $resulttext .= '<li>'.&mt('Institutional user status types deleted').'</li>';  
                         }                          }
                     }                          if ($changes{'inststatus'}{'inststatusguest'}) {
                 } elsif ($item eq 'unamemap_rule') {                              $resulttext .= '<li>'; 
                     if (ref($newvalues{'unamemap_rule'}) eq 'ARRAY') {                              if (@orderedguests) {
                         my @rulenames;                                  $resulttext .= &mt('Types assignable to "non-institutional" usernames set to:').' ';
                         if (ref($unamemaprules) eq 'HASH') {                                  foreach my $type (@orderedguests) {
                             foreach my $rule (@{$newvalues{'unamemap_rule'}}) {                                      $resulttext .= $alltypes{$type}.', ';
                                 if (ref($unamemaprules->{$rule}) eq 'HASH') {  
                                     push(@rulenames,$unamemaprules->{$rule}->{'name'});  
                                 }                                  }
                                   $resulttext =~ s/, $//;
                               } else {
                                   $resulttext .= &mt('Types assignable to "non-institutional" usernames set to none.');
                             }                              }
                               $resulttext .= '</li>';
                         }                          }
                         if (@rulenames) {  
                             $resulttext .= '<li>'.&mt('Mapping for missing usernames includes: [_1]',  
                                                      '<ul><li>'.join('</li><li>',@rulenames).'</li></ul>').  
                                            '</li>';  
                         } else {  
                             $resulttext .= '<li>'.&mt('No mapping for missing usernames via standard log-in').'</li>';   
                         }   
                     } else {  
                         $resulttext .= '<li>'.&mt('Mapping for missing usernames via standard log-in deleted').'</li>';  
                     }                      }
                 } else {                  } else {
                     my $value = $env{'form.'.$item};                      my $value = $env{'form.'.$item};
Line 16664  sub modify_defaults { Line 11267  sub modify_defaults {
                         $value = $authnames{$shortauth{$value}};                          $value = $authnames{$shortauth{$value}};
                     }                      }
                     $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";  
                     if ($item eq 'portal_def') {  
                         if ($env{'form.'.$item} ne '') {  
                             foreach my $field ('email','web') {  
                                 $value = $env{'form.'.$item.'_'.$field};  
                                 if ($value) {  
                                     $value = &mt('Yes');  
                                 } else {  
                                     $value = &mt('No');  
                                 }  
                                 $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$field},$value).'</li>';  
                             }  
                         }  
                     }  
                 }                  }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
Line 16723  sub modify_scantron { Line 11313  sub modify_scantron {
     my $custom = 'custom.tab';      my $custom = 'custom.tab';
     my $default = 'default.tab';      my $default = 'default.tab';
     my $servadm = $r->dir_config('lonAdmEMail');      my $servadm = $r->dir_config('lonAdmEMail');
     my ($configuserok,$author_ok,$switchserver) =      my ($configuserok,$author_ok,$switchserver) = 
         &config_check($dom,$confname,$servadm);          &config_check($dom,$confname,$servadm);
     if ($env{'form.scantronformat.filename'} ne '') {      if ($env{'form.scantronformat.filename'} ne '') {
         my $error;          my $error;
Line 16758  sub modify_scantron { Line 11348  sub modify_scantron {
             if ($env{'form.scantronformat_del'}) {              if ($env{'form.scantronformat_del'}) {
                 $confhash{'scantron'}{'scantronformat'} = '';                  $confhash{'scantron'}{'scantronformat'} = '';
                 $changes{'scantronformat'} = 1;                  $changes{'scantronformat'} = 1;
             } else {  
                 $confhash{'scantron'}{'scantronformat'} = $domconfig{'scantron'}{'scantronformat'};  
             }  
         }  
     }  
     my @options = ('hdr','pad','rem');  
     my @fields = &scantroncsv_fields();  
     my %titles = &scantronconfig_titles();  
     my @formats = &Apache::loncommon::get_env_multiple('form.scantronconfig');  
     my ($newdat,$currdat,%newcol,%currcol);  
     if (grep(/^dat$/,@formats)) {  
         $confhash{'scantron'}{config}{dat} = 1;  
         $newdat = 1;  
     } else {  
         $newdat = 0;  
     }  
     if (grep(/^csv$/,@formats)) {  
         my %bynum;  
         foreach my $field (@fields) {  
             if ($env{'form.scantronconfig_csv_'.$field} =~ /^(\d+)$/) {  
                 my $posscol = $1;  
                 if (($posscol < 20) && (!$bynum{$posscol})) {  
                     $confhash{'scantron'}{config}{csv}{fields}{$field} = $posscol;  
                     $bynum{$posscol} = $field;  
                     $newcol{$field} = $posscol;  
                 }  
             }  
         }  
         if (keys(%newcol)) {  
             foreach my $option (@options) {  
                 if ($env{'form.scantroncsv_'.$option}) {  
                     $confhash{'scantron'}{config}{csv}{options}{$option} = 1;  
                 }  
             }  
         }  
     }  
     $currdat = 1;  
     if (ref($domconfig{'scantron'}) eq 'HASH') {  
         if (ref($domconfig{'scantron'}{'config'}) eq 'HASH') {  
             unless (exists($domconfig{'scantron'}{'config'}{'dat'})) {  
                 $currdat = 0;  
             }  
             if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {  
                 if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {  
                     %currcol = %{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}};  
                 }  
             }  
         }  
     }  
     if ($currdat != $newdat) {  
         $changes{'config'} = 1;  
     } else {  
         foreach my $field (@fields) {  
             if ($currcol{$field} ne '') {  
                 if ($currcol{$field} ne $newcol{$field}) {  
                     $changes{'config'} = 1;  
                     last;  
                 }  
             } elsif ($newcol{$field} ne '') {  
                 $changes{'config'} = 1;  
                 last;  
             }              }
         }          }
     }      }
Line 16829  sub modify_scantron { Line 11358  sub modify_scantron {
             if (keys(%changes) > 0) {              if (keys(%changes) > 0) {
                 if (ref($confhash{'scantron'}) eq 'HASH') {                  if (ref($confhash{'scantron'}) eq 'HASH') {
                     $resulttext = &mt('Changes made:').'<ul>';                      $resulttext = &mt('Changes made:').'<ul>';
                     if ($changes{'scantronformat'}) {                      if ($confhash{'scantron'}{'scantronformat'} eq '') {
                         if ($confhash{'scantron'}{'scantronformat'} eq '') {                          $resulttext .= '<li>'.&mt('[_1] bubblesheet format file removed; [_2] file will be used for courses in this domain.',$custom,$default).'</li>';
                             $resulttext .= '<li>'.&mt('[_1] bubblesheet format file removed; [_2] file will be used for courses in this domain.',$custom,$default).'</li>';                      } else {
                         } else {                          $resulttext .= '<li>'.&mt('Custom bubblesheet format file ([_1]) uploaded for use with courses in this domain.',$custom).'</li>';
                             $resulttext .= '<li>'.&mt('Custom bubblesheet format file ([_1]) uploaded for use with courses in this domain.',$custom).'</li>';  
                         }  
                     }  
                     if ($changes{'config'}) {  
                         if (ref($confhash{'scantron'}{'config'}) eq 'HASH') {  
                             if ($confhash{'scantron'}{'config'}{'dat'}) {  
                                 $resulttext .= '<li>'.&mt('Bubblesheet data upload formats includes .dat format').'</li>';  
                             }  
                             if (ref($confhash{'scantron'}{'config'}{'csv'}) eq 'HASH') {  
                                 if (ref($confhash{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {  
                                     if (keys(%{$confhash{'scantron'}{'config'}{'csv'}{'fields'}})) {  
                                         $resulttext .= '<li>'.&mt('Bubblesheet data upload formats includes .csv format, with following fields/column numbers supported:').'<ul>';  
                                         foreach my $field (@fields) {  
                                             if ($confhash{'scantron'}{'config'}{'csv'}{'fields'}{$field} ne '') {  
                                                 my $showcol = $confhash{'scantron'}{'config'}{'csv'}{'fields'}{$field} + 1;  
                                                 $resulttext .= '<li>'.$titles{$field}.': '.$showcol.'</li>';  
                                             }  
                                         }  
                                         $resulttext .= '</ul></li>';  
                                         if (ref($confhash{'scantron'}{'config'}{'csv'}{'options'}) eq 'HASH') {  
                                             if (keys(%{$confhash{'scantron'}{'config'}{'csv'}{'options'}})) {  
                                                 $resulttext .= '<li>'.&mt('Bubblesheet data upload formats includes .csv format, with following options:').'<ul>';  
                                                 foreach my $option (@options) {  
                                                     if ($confhash{'scantron'}{'config'}{'csv'}{'options'}{$option} ne '') {  
                                                         $resulttext .= '<li>'.$titles{$option}.'</li>';  
                                                     }  
                                                 }  
                                                 $resulttext .= '</ul></li>';  
                                             }  
                                         }  
                                     }  
                                 }  
                             }  
                         } else {  
                             $resulttext .= '<li>'.&mt('No bubblesheet data upload formats set -- will default to assuming .dat format').'</li>';  
                         }  
                     }                      }
                     $resulttext .= '</ul>';                      $resulttext .= '</ul>';
                 } else {                  } else {
                     $resulttext = &mt('Changes made to bubblesheet format file.');                      $resulttext = &mt('Changes made to bubblesheet format file.');
                 }                  }
                   $resulttext .= '</ul>';
                 &Apache::loncommon::devalidate_domconfig_cache($dom);                  &Apache::loncommon::devalidate_domconfig_cache($dom);
                 if (ref($lastactref) eq 'HASH') {                  if (ref($lastactref) eq 'HASH') {
                     $lastactref->{'domainconfig'} = 1;                      $lastactref->{'domainconfig'} = 1;
                 }                  }
             } else {              } else {
                 $resulttext = &mt('No changes made to bubblesheet format settings');                  $resulttext = &mt('No changes made to bubblesheet format file');
             }              }
         } else {          } else {
             $resulttext = '<span class="LC_error">'.              $resulttext = '<span class="LC_error">'.
                 &mt('An error occurred: [_1]',$putresult).'</span>';                  &mt('An error occurred: [_1]',$putresult).'</span>';
         }          }
     } else {      } else {
         $resulttext = &mt('No changes made to bubblesheet format settings');          $resulttext = &mt('No changes made to bubblesheet format file'); 
     }      }
     if ($errors) {      if ($errors) {
         $resulttext .= &mt('The following errors occurred: ').'<ul>'.          $resulttext .= &mt('The following errors occurred: ').'<ul>'.
Line 16919  sub modify_coursecategories { Line 11413  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 16933  sub modify_coursecategories { Line 11436  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 16955  sub modify_coursecategories { Line 11462  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 17017  sub modify_coursecategories { Line 11527  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 17135  sub modify_coursecategories { Line 11659  sub modify_coursecategories {
                     }                      }
                     $resulttext .= '</ul></li>';                      $resulttext .= '</ul></li>';
                 }                  }
                 &Apache::lonnet::do_cache_new('cats',$dom,$cathash,3600);  
                 if (ref($lastactref) eq 'HASH') {  
                     $lastactref->{'cats'} = 1;  
                 }  
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
             if ($changes{'unauth'} || $changes{'auth'}) {              if ($changes{'unauth'} || $changes{'auth'}) {
Line 17290  sub modify_serverstatuses { Line 11810  sub modify_serverstatuses {
 }  }
   
 sub modify_helpsettings {  sub modify_helpsettings {
     my ($r,$dom,$confname,$lastactref,%domconfig) = @_;      my ($r,$dom,$confname,%domconfig) = @_;
     my ($resulttext,$errors,%changes,%helphash);      my ($resulttext,$errors,%changes,%helphash);
     my %defaultchecked = ('submitbugs' => 'on');      my %defaultchecked = ('submitbugs' => 'on');
     my @offon = ('off','on');      my @offon = ('off','on');
     my @toggles = ('submitbugs');      my @toggles = ('submitbugs');
     my %current = ('submitbugs' => '',      my %current = ('submitbugs' => '');  
                    'adhoc'      => {},  
                   );  
     if (ref($domconfig{'helpsettings'}) eq 'HASH') {      if (ref($domconfig{'helpsettings'}) eq 'HASH') {
         %current = %{$domconfig{'helpsettings'}};          %current = %{$domconfig{'helpsettings'}};
     }      }
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);  
     foreach my $item (@toggles) {      foreach my $item (@toggles) {
         if ($defaultchecked{$item} eq 'on') {           if ($defaultchecked{$item} eq 'on') { 
             if ($current{$item} eq '') {              if ($current{$item} eq '') {
Line 17324  sub modify_helpsettings { Line 11841  sub modify_helpsettings {
             $helphash{'helpsettings'}{$item} = $env{'form.'.$item};              $helphash{'helpsettings'}{$item} = $env{'form.'.$item};
         }          }
     }      }
     my $maxnum = $env{'form.helproles_maxnum'};  
       my @modify = &Apache::loncommon::get_env_multiple('form.modifycusthelp');
     my $confname = $dom.'-domainconfig';      my $confname = $dom.'-domainconfig';
     my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');      my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');
     my (@allpos,%newsettings,%changedprivs,$newrole);      if (@modify) {
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);          foreach my $num (@modify) {
     my @accesstypes = ('all','dh','da','none','status','inc','exc');              my $rolename = $env{'form.custhelprole'.$num};
     my %domhelpdesk = &Apache::lonnet::get_active_domroles($dom,['dh','da']);              if ($rolename ne '') {
     my %lt = &Apache::lonlocal::texthash(                  if (exists($existing{'rolesdef_'.$rolename})) {
                     s      => 'system',                      my $prefix = 'custhelp'.$num;
                     d      => 'domain',                      my %newprivs = &Apache::lonuserutils::custom_role_update($rolename,$prefix);
                     order  => 'Display order',                      my %currprivs;
                     access => 'Role usage',                      ($currprivs{'s'},$currprivs{'d'},$currprivs{'c'}) = 
                     all    => 'All with domain helpdesk or helpdesk assistant role',                          split(/\_/,$existing{'rolesdef_'.$rolename});
                     dh     => 'All with domain helpdesk role',                      foreach my $level ('c','d','s') {
                     da     => 'All with domain helpdesk assistant role',                          if ($newprivs{$level} ne $currprivs{$level}) {
                     none   => 'None',                              $changes{'customrole'}{$rolename} = 1;
                     status => 'Determined based on institutional status',                              my $result = &Apache::lonnet::definerole($rolename,$newprivs{'s'},$newprivs{'d'},
                     inc    => 'Include all, but exclude specific personnel',                                                                       $newprivs{'c'},$confname,$dom);
                     exc    => 'Exclude all, but include specific personnel',                              last;
     );  
     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) {      if ($env{'form.newcusthelp'} ne '') {
         my $idx = 0;          my $prefix = 'custhelp'.$env{'form.newcusthelp'};
         foreach my $rolename (@allpos) {          my $rolename = $env{'form.newcusthelpname'};
             if ($rolename ne '') {          $rolename=~s/[^A-Za-z0-9]//gs;
                 $helphash{'helpsettings'}{'adhoc'}{$rolename}{'order'} = $idx;          if ($rolename ne '') {
                 if (ref($current{'adhoc'}) eq 'HASH') {              unless(exists($existing{'rolesdef_'.$rolename})) {
                     if (ref($current{'adhoc'}{$rolename}) eq 'HASH') {                  my %newprivs = &Apache::lonuserutils::custom_role_update($rolename,$prefix);
                         if ($current{'adhoc'}{$rolename}{'order'} ne $idx) {                  my $result = &Apache::lonnet::definerole($rolename,$newprivs{'s'},$newprivs{'d'},
                             $changes{'customrole'}{$rolename}{'order'} = 1;                                                           $newprivs{'c'},$confname,$dom);
                             $newsettings{$rolename}{'order'} = $idx+1;                  if ($result eq 'ok') {
                         }                      $changes{'newcustomrole'} = $rolename;
                     }                  } else {
                       $errors .= '<li><span class="LC_error">'.
                                  &mt('An error occurred storing the new custom role: [_1]',
                                      $result).'</span></li>';
                 }                  }
                 $idx ++;  
             }              }
         }          }
     }      }
   
     my $putresult;      my $putresult;
     if (keys(%changes) > 0) {      if (keys(%changes) > 0) {
         $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom);          $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom);
         if ($putresult eq 'ok') {          if ($putresult eq 'ok') {
             if (ref($helphash{'helpsettings'}) eq 'HASH') {              $resulttext = &mt('Changes made:').'<ul>';
                 $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}].'".',
Line 17530  sub modify_helpsettings { Line 11899  sub modify_helpsettings {
                                               &mt('LON-CAPA bug tracker'),600,500)).'</li>';                                                &mt('LON-CAPA bug tracker'),600,500)).'</li>';
                 } elsif ($item eq 'customrole') {                  } elsif ($item eq 'customrole') {
                     if (ref($changes{'customrole'}) eq 'HASH') {                      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 institutional types',  
                                                                    exc    => 'Allowed personnel',  
                                                                    inc    => 'Disallowed personnel',  
                         );  
                         foreach my $role (sort(keys(%{$changes{'customrole'}}))) {                          foreach my $role (sort(keys(%{$changes{'customrole'}}))) {
                             if (ref($changes{'customrole'}{$role}) eq 'HASH') {                              $resulttext .= '<li>'.&mt('Existing custom role modified: [_1]',
                                 if ($role eq $newrole) {                                                       $role).'</li>';
                                     $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>';  
                             }  
                         }                          }
                     }                      }
                   } elsif ($item eq 'newcustomrole') {
                       $resulttext .= '<li>'.&mt('New custom role added: [_1]',
                                                 $changes{'newcustomrole'}).'</li>';
                 }                  }
             }              }
               $resulttext .= '</ul>';
           } else {
               $resulttext = &mt('No changes made to help settings');
               $errors .= '<li><span class="LC_error">'.
                          &mt('An error occurred storing the settings: [_1]',
                              $putresult).'</span></li>';
         }          }
         if (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');  
     }      }
     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 17618  sub modify_coursedefaults { Line 11928  sub modify_coursedefaults {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,$errors,%changes,%defaultshash);      my ($resulttext,$errors,%changes,%defaultshash);
     my %defaultchecked = (      my %defaultchecked = (
                              'canuse_pdfforms' => 'off',
                            'uselcmath'       => 'on',                             'uselcmath'       => 'on',
                            'usejsme'         => 'on',                             'usejsme'         => 'on'
                            'inline_chem'     => 'on',  
                            'ltiauth'         => 'off',  
                          );                           );
     my @toggles = ('uselcmath','usejsme','inline_chem','ltiauth');      my @toggles = ('canuse_pdfforms','uselcmath','usejsme');
     my @numbers = ('anonsurvey_threshold','uploadquota_official','uploadquota_unofficial',      my @numbers = ('anonsurvey_threshold','uploadquota_official','uploadquota_unofficial',
                    'uploadquota_community','uploadquota_textbook','mysqltables_official',                     'uploadquota_community','uploadquota_textbook','uploadquota_placement',
                    'mysqltables_unofficial','mysqltables_community','mysqltables_textbook');                     'mysqltables_official','mysqltables_unofficial','mysqltables_community',
     my @types = ('official','unofficial','community','textbook');                     'mysqltables_textbook','mysqltables_placement');
       my @types = ('official','unofficial','community','textbook','placement');
     my %staticdefaults = (      my %staticdefaults = (
                            anonsurvey_threshold => 10,                             anonsurvey_threshold => 10,
                            uploadquota          => 500,                             uploadquota          => 500,
                            postsubmit           => 60,                             postsubmit           => 60,
                            mysqltables          => 172800,                             mysqltables          => 172800,
                          );                           );
     my %texoptions = (  
                         MathJax  => 'MathJax',  
                         mimetex  => &mt('Convert to Images'),  
                         tth      => &mt('TeX to HTML'),  
                      );  
     $defaultshash{'coursedefaults'} = {};      $defaultshash{'coursedefaults'} = {};
   
     if (ref($domconfig{'coursedefaults'}) ne 'HASH') {      if (ref($domconfig{'coursedefaults'}) ne 'HASH') {
Line 17685  sub modify_coursedefaults { Line 11991  sub modify_coursedefaults {
                 $defaultshash{'coursedefaults'}{$setting}{$type} = $newdef;                  $defaultshash{'coursedefaults'}{$setting}{$type} = $newdef;
             }              }
             if ($currdef ne $newdef) {              if ($currdef ne $newdef) {
                   my $staticdef;
                 if ($item eq 'anonsurvey_threshold') {                  if ($item eq 'anonsurvey_threshold') {
                     unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) {                      unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) {
                         $changes{$item} = 1;                          $changes{$item} = 1;
                     }                      }
                 } elsif ($item =~ /^(uploadquota|mysqltables)_/) {                  } elsif ($item =~ /^(uploadquota|mysqltables)_/) {
                     my $setting = $1;                      my $setting = $1; 
                     unless (($currdef eq '') && ($newdef == $staticdefaults{$setting})) {                      unless (($currdef eq '') && ($newdef == $staticdefaults{$setting})) {
                         $changes{$setting} = 1;                          $changes{$setting} = 1;
                     }                      }
                 }                  }
             }              }
         }          }
         my $texengine;  
         if ($env{'form.texengine'} =~ /^(MathJax|mimetex|tth)$/) {  
             $texengine = $env{'form.texengine'};  
             my $currdef = $domconfig{'coursedefaults'}{'texengine'};  
             if ($currdef eq '') {  
                 unless ($texengine eq $Apache::lonnet::deftex) {  
                     $changes{'texengine'} = 1;  
                 }  
             } elsif ($currdef ne $texengine) {  
                 $changes{'texengine'} = 1;  
             }  
         }  
         if ($texengine ne '') {  
             $defaultshash{'coursedefaults'}{'texengine'} = $texengine;  
         }  
         my $currclone = $domconfig{'coursedefaults'}{'canclone'};          my $currclone = $domconfig{'coursedefaults'}{'canclone'};
         my @currclonecode;          my @currclonecode;
         if (ref($currclone) eq 'HASH') {          if (ref($currclone) eq 'HASH') {
Line 17720  sub modify_coursedefaults { Line 12012  sub modify_coursedefaults {
             }              }
         }          }
         my $newclone;          my $newclone;
         if ($env{'form.canclone'} =~ /^(none|domain|instcode)$/) {          if ($env{'form.canclone'} =~ /^(none|domain|instcode)$/) { 
             $newclone = $env{'form.canclone'};              $newclone = $env{'form.canclone'};
         }          }
         if ($newclone eq 'instcode') {          if ($newclone eq 'instcode') {
Line 17743  sub modify_coursedefaults { Line 12035  sub modify_coursedefaults {
                 $newclone eq '';                  $newclone eq '';
             }              }
         } elsif ($newclone ne '') {          } elsif ($newclone ne '') {
             $defaultshash{'coursedefaults'}{'canclone'} = $newclone;              $defaultshash{'coursedefaults'}{'canclone'} = $newclone; 
         }          } 
         if ($newclone ne $currclone) {          if ($newclone ne $currclone) {
             $changes{'canclone'} = 1;              $changes{'canclone'} = 1;
         }          }
Line 17762  sub modify_coursedefaults { Line 12054  sub modify_coursedefaults {
                 $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type};                  $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type};
             }              }
         } else {          } else {
             if ($env{'form.coursecredits'} eq '1') {              if ($env{'form.coursecredits'} eq '1') { 
                 foreach my $type (@types) {                  foreach my $type (@types) {
                     unless ($type eq 'community') {                      unless ($type eq 'community') {
                         if ($domconfig{'coursedefaults'}{'coursecredits'}{$type} ne $credits{$type}) {                          if ($domconfig{'coursedefaults'}{'coursecredits'}{$type} ne $credits{$type}) {        
                             $changes{'coursecredits'} = 1;                              $changes{'coursecredits'} = 1;
                         }                          }
                         $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type};                          $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type};
Line 17808  sub modify_coursedefaults { Line 12100  sub modify_coursedefaults {
                 }                  }
                 if (exists($currtimeout{$type})) {                  if (exists($currtimeout{$type})) {
                     if ($timeout ne $currtimeout{$type}) {                      if ($timeout ne $currtimeout{$type}) {
                         $changes{'postsubmit'} = 1;                          $changes{'postsubmit'} = 1; 
                     }                      }
                 } elsif ($timeout ne '') {                  } elsif ($timeout ne '') {
                     $changes{'postsubmit'} = 1;                      $changes{'postsubmit'} = 1;
Line 17830  sub modify_coursedefaults { Line 12122  sub modify_coursedefaults {
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);              my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
             if (($changes{'uploadquota'}) || ($changes{'postsubmit'}) ||              if (($changes{'canuse_pdfforms'}) || ($changes{'uploadquota'}) || ($changes{'postsubmit'}) ||
                 ($changes{'coursecredits'}) || ($changes{'uselcmath'}) || ($changes{'usejsme'}) ||                  ($changes{'coursecredits'}) || ($changes{'uselcmath'}) || ($changes{'usejsme'}) ||
                 ($changes{'canclone'}) || ($changes{'mysqltables'}) || ($changes{'texengine'}) ||                  ($changes{'canclone'}) || ($changes{'mysqltables'})) {
                 ($changes{'inline_chem'}) || ($changes{'ltiauth'})) {                  foreach my $item ('canuse_pdfforms','uselcmath','usejsme') { 
                 foreach my $item ('uselcmath','usejsme','inline_chem','texengine','ltiauth') {  
                     if ($changes{$item}) {                      if ($changes{$item}) {
                         $domdefaults{$item}=$defaultshash{'coursedefaults'}{$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') {
                         foreach my $type (keys(%{$defaultshash{'coursedefaults'}{'coursecredits'}})) {                          foreach my $type (keys(%{$defaultshash{'coursedefaults'}{'coursecredits'}})) {
Line 17885  sub modify_coursedefaults { Line 12176  sub modify_coursedefaults {
             }              }
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
                 if ($item eq 'uselcmath') {                  if ($item eq 'canuse_pdfforms') {
                       if ($env{'form.'.$item} eq '1') {
                           $resulttext .= '<li>'.&mt("Course/Community users can create/upload PDF forms set to 'on'").'</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('Course/Community users can create/upload PDF forms set to "off"').'</li>';
                       }
                   } elsif ($item eq 'uselcmath') {
                     if ($env{'form.'.$item} eq '1') {                      if ($env{'form.'.$item} eq '1') {
                         $resulttext .= '<li>'.&mt('Math preview uses LON-CAPA previewer (javascript), if supported by browser.').'</li>';                          $resulttext .= '<li>'.&mt('Math preview uses LON-CAPA previewer (javascript), if supported by browser.').'</li>';
                     } else {                      } else {
Line 17895  sub modify_coursedefaults { Line 12192  sub modify_coursedefaults {
                     if ($env{'form.'.$item} eq '1') {                      if ($env{'form.'.$item} eq '1') {
                         $resulttext .= '<li>'.&mt('Molecule editor uses JSME (HTML5), if supported by browser.').'</li>';                          $resulttext .= '<li>'.&mt('Molecule editor uses JSME (HTML5), if supported by browser.').'</li>';
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('Molecule editor uses JME (Java), if supported by client OS.').'</li>';                          $resulttext .= '<li>'.&mt('Molecule editor uses JME (Java), if supported by client OS.').'</li>'; 
                     }  
                 } elsif ($item eq 'inline_chem') {  
                     if ($env{'form.'.$item} eq '1') {  
                         $resulttext .= '<li>'.&mt('Chemical Reaction Response uses inline previewer').'</li>';  
                     } else {  
                         $resulttext .= '<li>'.&mt('Chemical Reaction Response uses pop-up previewer').'</li>';  
                     }  
                 } elsif ($item eq 'texengine') {  
                     if ($defaultshash{'coursedefaults'}{'texengine'} ne '') {  
                         $resulttext .= '<li>'.&mt('Default method to display mathematics set to: "[_1]"',  
                                                   $texoptions{$defaultshash{'coursedefaults'}{'texengine'}}).'</li>';  
                     }                      }
                 } elsif ($item eq 'anonsurvey_threshold') {                  } elsif ($item eq 'anonsurvey_threshold') {
                     $resulttext .= '<li>'.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'</li>';                      $resulttext .= '<li>'.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'</li>';
Line 17916  sub modify_coursedefaults { Line 12202  sub modify_coursedefaults {
                                        '<li>'.&mt('Official courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'official'}.'</b>').'</li>'.                                         '<li>'.&mt('Official courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'official'}.'</b>').'</li>'.
                                        '<li>'.&mt('Unofficial courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'unofficial'}.'</b>').'</li>'.                                         '<li>'.&mt('Unofficial courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'unofficial'}.'</b>').'</li>'.
                                        '<li>'.&mt('Textbook courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'textbook'}.'</b>').'</li>'.                                         '<li>'.&mt('Textbook courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'textbook'}.'</b>').'</li>'.
                                          '<li>'.&mt('Placement tests: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'placement'}.'</b>').'</li>'. 
                                        '<li>'.&mt('Communities: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'community'}.'</b>').'</li>'.                                         '<li>'.&mt('Communities: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'community'}.'</b>').'</li>'.
                                        '</ul>'.                                         '</ul>'.
                                        '</li>';                                         '</li>';
Line 17929  sub modify_coursedefaults { Line 12215  sub modify_coursedefaults {
                                        '<li>'.&mt('Official courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'official'}.'</b>').'</li>'.                                         '<li>'.&mt('Official courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'official'}.'</b>').'</li>'.
                                        '<li>'.&mt('Unofficial courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'unofficial'}.'</b>').'</li>'.                                         '<li>'.&mt('Unofficial courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'unofficial'}.'</b>').'</li>'.
                                        '<li>'.&mt('Textbook courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'textbook'}.'</b>').'</li>'.                                         '<li>'.&mt('Textbook courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'textbook'}.'</b>').'</li>'.
                                          '<li>'.&mt('Placement tests: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'placement'}.'</b>').'</li>'.
                                        '<li>'.&mt('Communities: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'community'}.'</b>').'</li>'.                                         '<li>'.&mt('Communities: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'community'}.'</b>').'</li>'.
                                        '</ul>'.                                         '</ul>'.
                                        '</li>';                                         '</li>';
Line 17940  sub modify_coursedefaults { Line 12227  sub modify_coursedefaults {
                         $resulttext .= '<li>'.&mt('Submit button(s) remain enabled on page after student makes submission.');                          $resulttext .= '<li>'.&mt('Submit button(s) remain enabled on page after student makes submission.');
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('Submit button(s) disabled on page after student makes submission').'; ';                          $resulttext .= '<li>'.&mt('Submit button(s) disabled on page after student makes submission').'; ';
                         if (ref($defaultshash{'coursedefaults'}{'postsubmit'}) eq 'HASH') {                          if (ref($defaultshash{'coursedefaults'}{'postsubmit'}) eq 'HASH') { 
                             $resulttext .= &mt('durations:').'<ul>';                              $resulttext .= &mt('durations:').'<ul>';
                             foreach my $type (@types) {                              foreach my $type (@types) {
                                 $resulttext .= '<li>';                                  $resulttext .= '<li>';
Line 17964  sub modify_coursedefaults { Line 12251  sub modify_coursedefaults {
                                     $resulttext .= &mt('Unofficial courses');                                      $resulttext .= &mt('Unofficial courses');
                                 } elsif ($type eq 'textbook') {                                  } elsif ($type eq 'textbook') {
                                     $resulttext .= &mt('Textbook courses');                                      $resulttext .= &mt('Textbook courses');
                                   } elsif ($type eq 'placement') {
                                       $resulttext .= &mt('Placement tests');
                                 }                                  }
                                 $resulttext .= ' -- '.$display.'</li>';                                  $resulttext .= ' -- '.$display.'</li>';
                             }                              }
                             $resulttext .= '</ul>';                              $resulttext .= '</ul>';
                         }                          }
                         $resulttext .= '</li>';                          $resulttext .= '</li>';    
                     }                      }
                 } elsif ($item eq 'coursecredits') {                  } elsif ($item eq 'coursecredits') {
                     if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {                      if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
Line 17997  sub modify_coursedefaults { Line 12286  sub modify_coursedefaults {
                     } elsif ($defaultshash{'coursedefaults'}{'canclone'} eq 'domain') {                      } elsif ($defaultshash{'coursedefaults'}{'canclone'} eq 'domain') {
                         $resulttext .= '<li>'.&mt('By default, a course requester can clone any course from his/her domain.').'</li>';                          $resulttext .= '<li>'.&mt('By default, a course requester can clone any course from his/her domain.').'</li>';
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('By default, only course owner and coordinators may clone a course.').'</li>';                          $resulttext .= '<li>'.&mt('By default, only course owner and coordinators may clone a course.').'</li>'; 
                     }  
                 } elsif ($item eq 'ltiauth') {  
                     if ($env{'form.'.$item} eq '1') {  
                         $resulttext .= '<li>'.&mt('LTI launch of deep-linked URL need not require re-authentication').'</li>';  
                     } else {  
                         $resulttext .= '<li>'.&mt('LTI launch of deep-linked URL will require re-authentication').'</li>';  
                     }                      }
                 }                  }
             }              }
Line 18021  sub modify_coursedefaults { Line 12304  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 18238  sub modify_selfenrollment { Line 12521  sub modify_selfenrollment {
                         $resulttext .= '</ul></li>';                           $resulttext .= '</ul></li>'; 
                     }                      }
                 }                  }
             }                  if ((exists($changes{'admin'})) || (exists($changes{'default'}))) {
             if ((exists($changes{'admin'})) || (exists($changes{'default'}))) {                      my $cachetime = 24*60*60;
                 my $cachetime = 24*60*60;                      &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
                 &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);                      if (ref($lastactref) eq 'HASH') {
                 if (ref($lastactref) eq 'HASH') {                          $lastactref->{'domdefaults'} = 1;
                     $lastactref->{'domdefaults'} = 1;                      }
                 }                  }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
Line 18257  sub modify_selfenrollment { Line 12540  sub modify_selfenrollment {
     return $resulttext;      return $resulttext;
 }  }
   
 sub modify_wafproxy {  
     my ($dom,$action,$lastactref,%domconfig) = @_;  
     my %servers = &Apache::lonnet::internet_dom_servers($dom);  
     my (%othercontrol,%canset,%values,%curralias,%currsaml,%currvalue,@warnings,  
         %wafproxy,%changes,%expirecache,%expiresaml);  
     foreach my $server (sort(keys(%servers))) {  
         my $serverhome = &Apache::lonnet::get_server_homeID($servers{$server});  
         if ($serverhome eq $server) {  
             my $serverdom = &Apache::lonnet::host_domain($server);  
             if ($serverdom eq $dom) {  
                 $canset{$server} = 1;  
             }  
         }  
     }  
     if (ref($domconfig{'wafproxy'}) eq 'HASH') {  
         %{$values{$dom}} = ();  
         if (ref($domconfig{'wafproxy'}{'alias'}) eq 'HASH') {  
             %curralias = %{$domconfig{'wafproxy'}{'alias'}};  
         }  
         if (ref($domconfig{'wafproxy'}{'saml'}) eq 'HASH') {  
             %currsaml = %{$domconfig{'wafproxy'}{'saml'}};  
         }  
         foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext','sslopt') {  
             $currvalue{$item} = $domconfig{'wafproxy'}{$item};  
         }  
     }  
     my $output;  
     if (keys(%canset)) {  
         %{$wafproxy{'alias'}} = ();  
         %{$wafproxy{'saml'}} = ();  
         foreach my $key (sort(keys(%canset))) {  
             if ($env{'form.wafproxy_'.$dom}) {  
                 $wafproxy{'alias'}{$key} = $env{'form.wafproxy_alias_'.$key};  
                 $wafproxy{'alias'}{$key} =~ s/^\s+|\s+$//g;  
                 if ($wafproxy{'alias'}{$key} ne $curralias{$key}) {  
                     $changes{'alias'} = 1;  
                 }  
                 if ($env{'form.wafproxy_alias_saml_'.$key}) {  
                     $wafproxy{'saml'}{$key} = 1;  
                 }  
                 if ($wafproxy{'saml'}{$key} ne $currsaml{$key}) {  
                     $changes{'saml'} = 1;  
                 }  
             } else {  
                 $wafproxy{'alias'}{$key} = '';  
                 $wafproxy{'saml'}{$key} = '';  
                 if ($curralias{$key}) {  
                     $changes{'alias'} = 1;  
                 }  
                 if ($currsaml{$key}) {  
                     $changes{'saml'} = 1;  
                 }  
             }  
             if ($wafproxy{'alias'}{$key} eq '') {  
                 if ($curralias{$key}) {  
                     $expirecache{$key} = 1;  
                 }  
                 delete($wafproxy{'alias'}{$key});  
             }  
             if ($wafproxy{'saml'}{$key} eq '') {  
                 if ($currsaml{$key}) {  
                     $expiresaml{$key} = 1;  
                 }  
                 delete($wafproxy{'saml'}{$key});  
             }  
         }  
         unless (keys(%{$wafproxy{'alias'}})) {  
             delete($wafproxy{'alias'});  
         }  
         unless (keys(%{$wafproxy{'saml'}})) {  
             delete($wafproxy{'saml'});  
         }  
         # Localization for values in %warn occurs in &mt() calls separately.  
         my %warn = (  
                      trusted => 'trusted IP range(s)',  
                      vpnint => 'internal IP range(s) for VPN sessions(s)',  
                      vpnext => 'IP range(s) for backend WAF connections',  
                    );  
         foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext','sslopt') {  
             my $possible = $env{'form.wafproxy_'.$item};  
             $possible =~ s/^\s+|\s+$//g;  
             if ($possible ne '') {  
                 if ($item eq 'remoteip') {  
                     if ($possible =~ /^[mhn]$/) {  
                         $wafproxy{$item} = $possible;  
                     }  
                 } elsif ($item eq 'ipheader') {  
                     if ($wafproxy{'remoteip'} eq 'h') {  
                         $wafproxy{$item} = $possible;  
                     }  
                 } elsif ($item eq 'sslopt') {  
                     if ($possible =~ /^0|1$/) {  
                         $wafproxy{$item} = $possible;  
                     }  
                 } else {  
                     my (@ok,$count);  
                     if (($item eq 'vpnint') || ($item eq 'vpnext')) {  
                         unless ($env{'form.wafproxy_vpnaccess'}) {  
                             $possible = '';  
                         }  
                     } elsif ($item eq 'trusted') {  
                         unless ($wafproxy{'remoteip'} eq 'h') {  
                             $possible = '';  
                         }  
                     }  
                     unless ($possible eq '') {  
                         $possible =~ s/[\r\n]+/\s/g;  
                         $possible =~ s/\s*-\s*/-/g;  
                         $possible =~ s/\s+/,/g;  
                         $possible =~ s/,+/,/g;  
                     }  
                     $count = 0;  
                     if ($possible ne '') {  
                         foreach my $poss (split(/\,/,$possible)) {  
                             $count ++;  
                             $poss = &validate_ip_pattern($poss);  
                             if ($poss ne '') {  
                                 push(@ok,$poss);  
                             }  
                         }  
                         my $diff = $count - scalar(@ok);  
                         if ($diff) {  
                             push(@warnings,'<li>'.  
                                  &mt('[quant,_1,IP] invalid and excluded from saved value for [_2]',  
                                      $diff,$warn{$item}).  
                                  '</li>');  
                         }  
                         if (@ok) {  
                             my @cidr_list;  
                             foreach my $item (@ok) {  
                                 @cidr_list = &Net::CIDR::cidradd($item,@cidr_list);  
                             }  
                             $wafproxy{$item} = join(',',@cidr_list);  
                         }  
                     }  
                 }  
                 if ($wafproxy{$item} ne $currvalue{$item}) {  
                     $changes{$item} = 1;  
                 }  
             } elsif ($currvalue{$item}) {  
                 $changes{$item} = 1;  
             }  
         }  
     } else {  
         if (keys(%curralias)) {  
             $changes{'alias'} = 1;  
         }  
         if (keys(%currsaml)) {  
             $changes{'saml'} = 1;  
         }  
         if (keys(%currvalue)) {  
             foreach my $key (keys(%currvalue)) {  
                 $changes{$key} = 1;  
             }  
         }  
     }  
     if (keys(%changes)) {  
         my %defaultshash = (  
                               wafproxy => \%wafproxy,  
                            );  
         my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,  
                                                  $dom);  
         if ($putresult eq 'ok') {  
             my $cachetime = 24*60*60;  
             my (%domdefaults,$updatedomdefs);  
             foreach my $item ('ipheader','trusted','vpnint','vpnext','sslopt') {  
                 if ($changes{$item}) {  
                     unless ($updatedomdefs) {  
                         %domdefaults = &Apache::lonnet::get_domain_defaults($dom);  
                         $updatedomdefs = 1;  
                     }  
                     if ($wafproxy{$item}) {  
                         $domdefaults{'waf_'.$item} = $wafproxy{$item};  
                     } elsif (exists($domdefaults{'waf_'.$item})) {  
                         delete($domdefaults{'waf_'.$item});  
                     }  
                 }  
             }  
             if ($updatedomdefs) {  
                 &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);  
                 if (ref($lastactref) eq 'HASH') {  
                     $lastactref->{'domdefaults'} = 1;  
                 }  
             }  
             if ((exists($wafproxy{'alias'})) || (keys(%expirecache))) {  
                 my %updates = %expirecache;  
                 foreach my $key (keys(%expirecache)) {  
                     &Apache::lonnet::devalidate_cache_new('proxyalias',$key);  
                 }  
                 if (ref($wafproxy{'alias'}) eq 'HASH') {  
                     my $cachetime = 24*60*60;  
                     foreach my $key (keys(%{$wafproxy{'alias'}})) {  
                         $updates{$key} = 1;  
                         &Apache::lonnet::do_cache_new('proxyalias',$key,$wafproxy{'alias'}{$key},  
                                                       $cachetime);  
                     }  
                 }  
                 if (ref($lastactref) eq 'HASH') {  
                     $lastactref->{'proxyalias'} = \%updates;  
                 }  
             }  
             if ((exists($wafproxy{'saml'})) || (keys(%expiresaml))) {  
                 my %samlupdates = %expiresaml;  
                 foreach my $key (keys(%expiresaml)) {  
                     &Apache::lonnet::devalidate_cache_new('proxysaml',$key);  
                 }  
                 if (ref($wafproxy{'saml'}) eq 'HASH') {  
                     my $cachetime = 24*60*60;  
                     foreach my $key (keys(%{$wafproxy{'saml'}})) {  
                         $samlupdates{$key} = 1;  
                         &Apache::lonnet::do_cache_new('proxysaml',$key,$wafproxy{'saml'}{$key},  
                                                       $cachetime);  
                     }  
                 }  
                 if (ref($lastactref) eq 'HASH') {  
                     $lastactref->{'proxysaml'} = \%samlupdates;  
                 }  
             }  
             $output = &mt('Changes were made to Web Application Firewall/Reverse Proxy').'<ul>';  
             foreach my $item ('alias','saml','remoteip','ipheader','trusted','vpnint','vpnext','sslopt') {  
                 if ($changes{$item}) {  
                     if ($item eq 'alias') {  
                         my $numaliased = 0;  
                         if (ref($wafproxy{'alias'}) eq 'HASH') {  
                             my $shown;  
                             if (keys(%{$wafproxy{'alias'}})) {  
                                 foreach my $server (sort(keys(%{$wafproxy{'alias'}}))) {  
                                     $shown .= '<li>'.&mt('[_1] aliased by [_2]',  
                                                          &Apache::lonnet::hostname($server),  
                                                          $wafproxy{'alias'}{$server}).'</li>';  
                                     $numaliased ++;  
                                 }  
                                 if ($numaliased) {  
                                     $output .= '<li>'.&mt('Aliases for hostnames set to: [_1]',  
                                                           '<ul>'.$shown.'</ul>').'</li>';  
                                 }  
                             }  
                         }  
                         unless ($numaliased) {  
                             $output .= '<li>'.&mt('Aliases deleted for hostnames').'</li>';  
                         }  
                     } elsif ($item eq 'saml') {  
                         my $shown;  
                         if (ref($wafproxy{'saml'}) eq 'HASH') {  
                             if (keys(%{$wafproxy{'saml'}})) {  
                                 $shown = join(', ',sort(keys(%{$wafproxy{'saml'}})));  
                             }  
                         }  
                         if ($shown) {  
                             $output .= '<li>'.&mt('Alias used by SSO Auth for: [_1]',  
                                                   $shown).'</li>';  
                         } else {  
                             $output .= '<li>'.&mt('No alias used for SSO Auth').'</li>';  
                         }  
                     } else {  
                         if ($item eq 'remoteip') {  
                             my %ip_methods = &remoteip_methods();  
                             if ($wafproxy{$item} =~ /^[mh]$/) {  
                                 $output .= '<li>'.&mt("Method for determining user's IP set to: [_1]",  
                                                       $ip_methods{$wafproxy{$item}}).'</li>';  
                             } else {  
                                 if (($env{'form.wafproxy_'.$dom}) && (ref($wafproxy{'alias'}) eq 'HASH')) {  
                                     $output .= '<li>'.&mt("No method in use to get user's real IP (will report IP used by WAF).").  
                                                '</li>';  
                                 } else {  
                                     $output .= '<li>'.&mt('WAF/Reverse Proxy not in use').'</li>';  
                                 }  
                             }  
                         } elsif ($item eq 'ipheader') {  
                             if ($wafproxy{$item}) {  
                                 $output .= '<li>'.&mt('Request header with remote IP set to: [_1]',  
                                                       $wafproxy{$item}).'</li>';  
                             } else {  
                                 $output .= '<li>'.&mt('Request header with remote IP deleted').'</li>';  
                             }  
                         } elsif ($item eq 'trusted') {  
                             if ($wafproxy{$item}) {  
                                 $output .= '<li>'.&mt('Trusted IP range(s) set to: [_1]',  
                                                       $wafproxy{$item}).'</li>';  
                             } else {  
                                 $output .= '<li>'.&mt('Trusted IP range(s) deleted').'</li>';  
                             }  
                         } elsif ($item eq 'vpnint') {  
                             if ($wafproxy{$item}) {  
                                 $output .= '<li>'.&mt('Internal IP Range(s) for VPN sessions set to: [_1]',  
                                                        $wafproxy{$item}).'</li>';  
                             } else {  
                                 $output .= '<li>'.&mt('Internal IP Range(s) for VPN sessions deleted').'</li>';  
                             }  
                         } elsif ($item eq 'vpnext') {  
                             if ($wafproxy{$item}) {  
                                 $output .= '<li>'.&mt('IP Range(s) for backend WAF connections set to: [_1]',  
                                                        $wafproxy{$item}).'</li>';  
                             } else {  
                                 $output .= '<li>'.&mt('IP Range(s) for backend WAF connections deleted').'</li>';  
                             }  
                         } elsif ($item eq 'sslopt') {  
                             if ($wafproxy{$item}) {  
                                 $output .= '<li>'.&mt('WAF/Reverse Proxy expected to forward requests to https on LON-CAPA node, regardless of original protocol in web browser (http or https).').'</li>';  
                             } else {  
                                 $output .= '<li>'.&mt('WAF/Reverse Proxy expected to preserve original protocol in web browser (either http or https) when forwarding to LON-CAPA node.').'</li>';  
                             }  
                         }  
                     }  
                 }  
             }  
         } else {  
             $output = '<span class="LC_error">'.  
                       &mt('An error occurred: [_1]',$putresult).'</span>';  
         }  
     } elsif (keys(%canset)) {  
         $output = &mt('No changes made to Web Application Firewall/Reverse Proxy settings');  
     }  
     if (@warnings) {  
         $output .= '<br />'.&mt('Warnings:').'<ul>'.  
                        join("\n",@warnings).'</ul>';  
     }  
     return $output;  
 }  
   
 sub validate_ip_pattern {  
     my ($pattern) = @_;  
     if ($pattern =~ /^([^-]+)\-([^-]+)$/) {  
         my ($start,$end) = ($1,$2);  
         if ((&Net::CIDR::cidrvalidate($start)) && (&Net::CIDR::cidrvalidate($end))) {  
             if (($start !~ m{/}) && ($end !~ m{/})) {  
                 return $start.'-'.$end;  
             }  
         }  
     } elsif ($pattern ne '') {  
         $pattern = &Net::CIDR::cidrvalidate($pattern);  
         if ($pattern ne '') {  
             return $pattern;  
         }  
     }  
     return;  
 }  
   
 sub modify_usersessions {  sub modify_usersessions {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my @hostingtypes = ('version','excludedomain','includedomain');      my @hostingtypes = ('version','excludedomain','includedomain');
Line 18606  sub modify_usersessions { Line 12551  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 18762  sub modify_usersessions { Line 12707  sub modify_usersessions {
         }          }
     }      }
     $defaultshash{'usersessions'}{'offloadnow'} = {};      $defaultshash{'usersessions'}{'offloadnow'} = {};
     $defaultshash{'usersessions'}{'offloadoth'} = {};  
     my @offloadnow = &Apache::loncommon::get_env_multiple('form.offloadnow');      my @offloadnow = &Apache::loncommon::get_env_multiple('form.offloadnow');
     my @okoffload;      my @okoffload;
     if (@offloadnow) {      if (@offloadnow) {
Line 18779  sub modify_usersessions { Line 12723  sub modify_usersessions {
             }              }
         }          }
     }      }
     my @offloadoth = &Apache::loncommon::get_env_multiple('form.offloadoth');  
     my @okoffloadoth;  
     if (@offloadoth) {  
         foreach my $server (@offloadoth) {  
             if (&Apache::lonnet::hostname($server) ne '') {  
                 unless (grep(/^\Q$server\E$/,@okoffloadoth)) {  
                     push(@okoffloadoth,$server);  
                 }  
             }  
         }  
         if (@okoffloadoth) {  
             foreach my $lonhost (@okoffloadoth) {  
                 $defaultshash{'usersessions'}{'offloadoth'}{$lonhost} = 1;  
             }  
         }  
     }  
     if (ref($domconfig{'usersessions'}) eq 'HASH') {      if (ref($domconfig{'usersessions'}) eq 'HASH') {
         if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') {          if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') {
             if (ref($changes{'spares'}) eq 'HASH') {              if (ref($changes{'spares'}) eq 'HASH') {
Line 18805  sub modify_usersessions { Line 12733  sub modify_usersessions {
         } else {          } else {
             $savespares = 1;              $savespares = 1;
         }          }
         foreach my $offload ('offloadnow','offloadoth') {          if (ref($domconfig{'usersessions'}{'offloadnow'}) eq 'HASH') {
             if (ref($domconfig{'usersessions'}{$offload}) eq 'HASH') {              foreach my $lonhost (keys(%{$domconfig{'usersessions'}{'offloadnow'}})) {
                 foreach my $lonhost (keys(%{$domconfig{'usersessions'}{$offload}})) {                  unless ($defaultshash{'usersessions'}{'offloadnow'}{$lonhost}) {
                     unless ($defaultshash{'usersessions'}{$offload}{$lonhost}) {                      $changes{'offloadnow'} = 1;
                         $changes{$offload} = 1;                      last;
                         last;  
                     }  
                 }                  }
                 unless ($changes{$offload}) {              }
                     foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{$offload}})) {              unless ($changes{'offloadnow'}) {
                         unless ($domconfig{'usersessions'}{$offload}{$lonhost}) {                  foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{'offloadnow'}})) { 
                             $changes{$offload} = 1;                      unless ($domconfig{'usersessions'}{'offloadnow'}{$lonhost}) {
                             last;                          $changes{'offloadnow'} = 1;
                         }                          last;
                     }                      }
                 }                  }
             } else {  
                 if (($offload eq 'offloadnow') && (@okoffload)) {  
                      $changes{'offloadnow'} = 1;  
                 }  
                 if (($offload eq 'offloadoth') && (@okoffloadoth)) {  
                     $changes{'offloadoth'} = 1;  
                 }  
             }              }
         }          } elsif (@okoffload) {
     } else {  
         if (@okoffload) {  
             $changes{'offloadnow'} = 1;              $changes{'offloadnow'} = 1;
         }          }
         if (@okoffloadoth) {      } elsif (@okoffload) {
             $changes{'offloadoth'} = 1;          $changes{'offloadnow'} = 1;
         }  
     }      }
     my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');      my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');
     if ((keys(%changes) > 0) || ($savespares)) {      if ((keys(%changes) > 0) || ($savespares)) {
Line 18853  sub modify_usersessions { Line 12769  sub modify_usersessions {
                 if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {                  if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
                     $domdefaults{'offloadnow'} = $defaultshash{'usersessions'}{'offloadnow'};                      $domdefaults{'offloadnow'} = $defaultshash{'usersessions'}{'offloadnow'};
                 }                  }
                 if (ref($defaultshash{'usersessions'}{'offloadoth'}) eq 'HASH') {  
                     $domdefaults{'offloadoth'} = $defaultshash{'usersessions'}{'offloadoth'};  
                 }  
             }              }
             my $cachetime = 24*60*60;              my $cachetime = 24*60*60;
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);              &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
             &Apache::lonnet::do_cache_new('usersessions',$dom,$defaultshash{'usersessions'},3600);  
             if (ref($lastactref) eq 'HASH') {              if (ref($lastactref) eq 'HASH') {
                 $lastactref->{'domdefaults'} = 1;                  $lastactref->{'domdefaults'} = 1;
                 $lastactref->{'usersessions'} = 1;  
             }              }
             if (keys(%changes) > 0) {              if (keys(%changes) > 0) {
                 my %lt = &usersession_titles();                  my %lt = &usersession_titles();
Line 18929  sub modify_usersessions { Line 12840  sub modify_usersessions {
                 if ($changes{'offloadnow'}) {                  if ($changes{'offloadnow'}) {
                     if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {                      if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
                         if (keys(%{$defaultshash{'usersessions'}{'offloadnow'}}) > 0) {                          if (keys(%{$defaultshash{'usersessions'}{'offloadnow'}}) > 0) {
                             $resulttext .= '<li>'.&mt('Switch any active user on next access, for server(s):').'<ul>';                              $resulttext .= '<li>'.&mt('Switch active users on next access, for server(s):').'<ul>';
                             foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadnow'}}))) {                              foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadnow'}}))) {
                                 $resulttext .= '<li>'.$lonhost.'</li>';                                  $resulttext .= '<li>'.$lonhost.'</li>';
                             }                              }
                             $resulttext .= '</ul>';                              $resulttext .= '</ul>';
                         } else {                          } else {
                             $resulttext .= '<li>'.&mt('No servers now set to switch any active user on next access.');                              $resulttext .= '<li>'.&mt('No servers now set to switch active users on next access.');
                         }                          }
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('No servers now set to switch any active user on next access.').'</li>';                          $resulttext .= '<li>'.&mt('No servers now set to switch active users on next access.').'</li>';
                     }                      }
                 }                  }
                 if ($changes{'offloadoth'}) {                  $resulttext .= '</ul>';
                     if (ref($defaultshash{'usersessions'}{'offloadoth'}) eq 'HASH') {              } else {
                         if (keys(%{$defaultshash{'usersessions'}{'offloadoth'}}) > 0) {                  $resulttext = $nochgmsg;
                             $resulttext .= '<li>'.&mt('Switch other institutions on next access, for server(s):').'<ul>';              }
                             foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadoth'}}))) {          } else {
                                 $resulttext .= '<li>'.$lonhost.'</li>';              $resulttext = '<span class="LC_error">'.
                             &mt('An error occurred: [_1]',$putresult).'</span>';
           }
       } else {
           $resulttext = $nochgmsg;
       }
       return $resulttext;
   }
   
   sub modify_ssl {
       my ($dom,$lastactref,%domconfig) = @_;
       my (%by_ip,%by_location,@intdoms,@instdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
       my @locations = sort(keys(%by_location));
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my (%defaultshash,%changes);
       my $action = 'ssl';
       my @prefixes = ('connect','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 = (
                     connect      => \@connecttypes,
                     replication  => \@reptypes,
                   );
       foreach my $prefix (sort(keys(%types))) {
           foreach my $type (@{$types{$prefix}}) {
               if ($prefix eq 'connect') {
                   my $value = 'yes';
                   if ($env{'form.'.$prefix.'_'.$type} =~ /^(no|req)$/) {
                       $value = $env{'form.'.$prefix.'_'.$type};
                   }
                   if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
                       if ($domconfig{$action}{$prefix}{$type} ne '') {
                           if ($value ne $domconfig{$action}{$prefix}{$type}) {
                               $changes{$prefix}{$type} = 1;
                           }
                           $defaultshash{$action}{$prefix}{$type} = $value;
                       } else {
                           $defaultshash{$action}{$prefix}{$type} = $value;
                           $changes{$prefix}{$type} = 1;
                       }
                   } else {
                       $defaultshash{$action}{$prefix}{$type} = $value;
                       $changes{$prefix}{$type} = 1;
                   }
                   if (($type eq 'dom') && (keys(%servers) == 1)) {
                       delete($changes{$prefix}{$type});
                   } elsif (($type eq 'intdom') && (@instdoms == 1)) {
                       delete($changes{$prefix}{$type});
                   } elsif (($type eq 'other') && (keys(%by_location) == 0)) { 
                       delete($changes{$prefix}{$type});
                   }
               } elsif ($prefix eq 'replication') {
                   if (@locations > 0) {
                       my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
                       my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
                       my @okvals;
                       foreach my $val (@vals) {
                           if ($val =~ /:/) {
                               my @items = split(/:/,$val);
                               foreach my $item (@items) {
                                   if (ref($by_location{$item}) eq 'ARRAY') {
                                       push(@okvals,$item);
                                   }
                             }                              }
                             $resulttext .= '</ul>';  
                         } else {                          } else {
                             $resulttext .= '<li>'.&mt('No servers now set to switch other institutions on next access.');                              if (ref($by_location{$val}) eq 'ARRAY') {
                                   push(@okvals,$val);
                               }
                           }
                       }
                       @okvals = sort(@okvals);
                       if (ref($domconfig{$action}) eq 'HASH') {
                           if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
                               if (ref($domconfig{$action}{$prefix}{$type}) eq 'ARRAY') {
                                   if ($inuse == 0) {
                                       $changes{$prefix}{$type} = 1;
                                   } else {
                                       $defaultshash{$action}{$prefix}{$type} = \@okvals;
                                       my @changed = &Apache::loncommon::compare_arrays($domconfig{$action}{$prefix}{$type},$defaultshash{$action}{$prefix}{$type});
                                       if (@changed > 0) {
                                           $changes{$prefix}{$type} = 1;
                                       }
                                   }
                               } else {
                                   if ($inuse == 1) {
                                       $defaultshash{$action}{$prefix}{$type} = \@okvals;
                                       $changes{$prefix}{$type} = 1;
                                   }
                               }
                           } else {
                               if ($inuse == 1) {
                                   $defaultshash{$action}{$prefix}{$type} = \@okvals;
                                   $changes{$prefix}{$type} = 1;
                               }
                           }
                       } else {
                           if ($inuse == 1) {
                               $defaultshash{$action}{$prefix}{$type} = \@okvals;
                               $changes{$prefix}{$type} = 1;
                           }
                       }
                   }
               }
           }
       }
       my $nochgmsg = &mt('No changes made to LON-CAPA SSL settings');
       if (keys(%changes) > 0) {
           my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                                    $dom);
           if ($putresult eq 'ok') {
               if (ref($defaultshash{$action}) eq 'HASH') {
                   if (ref($defaultshash{$action}{'replication'}) eq 'HASH') {
                       $domdefaults{'replication'} = $defaultshash{$action}{'replication'};
                   }
                   if (ref($defaultshash{$action}{'connect'}) eq 'HASH') {
                       $domdefaults{'connect'} = $domconfig{$action}{'connect'};
                   }
               }
               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 'connect') {
                                               $newvalue = $titles{$defaultshash{$action}{$prefix}{$type}};
                                           } elsif (ref($defaultshash{$action}{$prefix}{$type}) eq 'ARRAY') {
                                               if (@{$defaultshash{$action}{$prefix}{$type}} > 0) {
                                                   $newvalue = join(', ',@{$defaultshash{$action}{$prefix}{$type}});
                                               }
                                           }
                                       }
                                       if ($newvalue eq '') {
                                           $resulttext .= '<li>'.&mt('[_1] set to: none',$titles{$type}).'</li>';
                                       } else {
                                           $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$titles{$type},$newvalue).'</li>';
                                       }
                                   }
                               }
                           }
                           $resulttext .= '</ul>';
                       }
                   }
               } else {
                   $resulttext = $nochgmsg;
               }
           } else {
               $resulttext = '<span class="LC_error">'.
                             &mt('An error occurred: [_1]',$putresult).'</span>';
           }
       } else {
           $resulttext = $nochgmsg;
       }
       return $resulttext;
   }
   
   sub modify_trust {
       my ($dom,$lastactref,%domconfig) = @_;
       my (%by_ip,%by_location,@intdoms,@instdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
       my @locations = sort(keys(%by_location));
       my @prefixes = qw(content shared enroll othcoau coaurem domroles catalog reqcrs msg);
       my @types = ('exc','inc');
       my (%defaultshash,%changes);
       foreach my $prefix (@prefixes) {
           $defaultshash{'trust'}{$prefix} = {};
       }
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
       my $resulttext;
       foreach my $prefix (@prefixes) {
           foreach my $type (@types) {
               my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
               my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
               my @okvals;
               foreach my $val (@vals) {
                   if ($val =~ /:/) {
                       my @items = split(/:/,$val);
                       foreach my $item (@items) {
                           if (ref($by_location{$item}) eq 'ARRAY') {
                               push(@okvals,$item);
                           }
                       }
                   } else {
                       if (ref($by_location{$val}) eq 'ARRAY') {
                           push(@okvals,$val);
                       }
                   }
               }
               @okvals = sort(@okvals);
               if (ref($domconfig{'trust'}) eq 'HASH') {
                   if (ref($domconfig{'trust'}{$prefix}) eq 'HASH') {
                       if (ref($domconfig{'trust'}{$prefix}{$type}) eq 'ARRAY') {
                           if ($inuse == 0) {
                               $changes{$prefix}{$type} = 1;
                           } else {
                               $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                               my @changed = &Apache::loncommon::compare_arrays($domconfig{'trust'}{$prefix}{$type},$defaultshash{'trust'}{$prefix}{$type});
                               if (@changed > 0) {
                                   $changes{$prefix}{$type} = 1;
                               }
                         }                          }
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('No servers now set to switch other institutions on next access.').'</li>';                          if ($inuse == 1) {
                               $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                               $changes{$prefix}{$type} = 1;
                           }
                       }
                   } else {
                       if ($inuse == 1) {
                           $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                           $changes{$prefix}{$type} = 1;
                       }
                   }
               } else {
                   if ($inuse == 1) {
                       $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                       $changes{$prefix}{$type} = 1;
                   }
               }
           }
       }
       my $nochgmsg = &mt('No changes made to trust settings.');
       if (keys(%changes) > 0) {
           my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                                    $dom);
           if ($putresult eq 'ok') {
               if (ref($defaultshash{'trust'}) eq 'HASH') {
                   foreach my $prefix (@prefixes) {
                       if (ref($defaultshash{'trust'}{$prefix}) eq 'HASH') {
                           $domdefaults{'trust'.$prefix} = $defaultshash{'trust'}{$prefix};
                       }
                   }
               }
               my $cachetime = 24*60*60;
               &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
               }
               if (keys(%changes) > 0) {
                   my %lt = &trust_titles();
                   $resulttext = &mt('Changes made:').'<ul>';
                   foreach my $prefix (@prefixes) {
                       if (ref($changes{$prefix}) eq 'HASH') {
                           $resulttext .= '<li>'.$lt{$prefix}.'<ul>';
                           foreach my $type (@types) {
                               if (defined($changes{$prefix}{$type})) {
                                   my $newvalue;
                                   if (ref($defaultshash{'trust'}) eq 'HASH') {
                                       if (ref($defaultshash{'trust'}{$prefix})) {
                                           if (ref($defaultshash{'trust'}{$prefix}{$type}) eq 'ARRAY') {
                                               if (@{$defaultshash{'trust'}{$prefix}{$type}} > 0) {
                                                   $newvalue = join(', ',@{$defaultshash{'trust'}{$prefix}{$type}});
                                               }
                                           }
                                       }
                                   }
                                   if ($newvalue eq '') {
                                       $resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';
                                   } else {
                                       $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';
                                   }
                               }
                           }
                           $resulttext .= '</ul>';
                     }                      }
                 }                  }
                 $resulttext .= '</ul>';                  $resulttext .= '</ul>';
Line 18981  sub modify_loadbalancing { Line 13165  sub modify_loadbalancing {
     my @sparestypes = ('primary','default');      my @sparestypes = ('primary','default');
     my %typetitles = &sparestype_titles();      my %typetitles = &sparestype_titles();
     my $resulttext;      my $resulttext;
     my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);      my (%currbalancer,%currtargets,%currrules,%existing);
     if (ref($domconfig{'loadbalancing'}) eq 'HASH') {      if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
         %existing = %{$domconfig{'loadbalancing'}};          %existing = %{$domconfig{'loadbalancing'}};
     }      }
     &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,      &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
                               \%currtargets,\%currrules,\%currcookies);                                \%currtargets,\%currrules);
     my ($saveloadbalancing,%defaultshash,%changes);      my ($saveloadbalancing,%defaultshash,%changes);
     my ($alltypes,$othertypes,$titles) =      my ($alltypes,$othertypes,$titles) =
         &loadbalancing_titles($dom,$intdom,$usertypes,$types);          &loadbalancing_titles($dom,$intdom,$usertypes,$types);
Line 19038  sub modify_loadbalancing { Line 13222  sub modify_loadbalancing {
             }              }
             $defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto;              $defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto;
         }          }
         if ($env{'form.loadbalancing_cookie_'.$i}) {  
             $defaultshash{'loadbalancing'}{$balancer}{'cookie'} = 1;  
             if (exists($currbalancer{$balancer})) {  
                 unless ($currcookies{$balancer}) {  
                     $changes{'curr'}{$balancer}{'cookie'} = 1;  
                 }  
             }  
         } elsif (exists($currbalancer{$balancer})) {  
             if ($currcookies{$balancer}) {  
                 $changes{'curr'}{$balancer}{'cookie'} = 1;  
             }  
         }  
         if (ref($currtargets{$balancer}) eq 'HASH') {          if (ref($currtargets{$balancer}) eq 'HASH') {
             foreach my $sparetype (@sparestypes) {              foreach my $sparetype (@sparestypes) {
                 if (ref($currtargets{$balancer}{$sparetype}) eq 'ARRAY') {                  if (ref($currtargets{$balancer}{$sparetype}) eq 'ARRAY') {
Line 19087  sub modify_loadbalancing { Line 13259  sub modify_loadbalancing {
                 }                  }
                 if ($rule eq 'specific') {                  if ($rule eq 'specific') {
                     my $specifiedhost = $env{'form.loadbalancing_singleserver_'.$i.'_'.$type};                      my $specifiedhost = $env{'form.loadbalancing_singleserver_'.$i.'_'.$type};
                     if (exists($servers{$specifiedhost})) {                      if (exists($servers{$specifiedhost})) { 
                         $rule = $specifiedhost;                          $rule = $specifiedhost;
                     }                      }
                 }                  }
Line 19163  sub modify_loadbalancing { Line 13335  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') ||
                                                  ($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) {                                                   ($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) { 
                                             if (($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) {                                              if (($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) {
                                                 foreach my $sparetype (@sparestypes) {                                                  foreach my $sparetype (@sparestypes) {
                                                     if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {                                                      if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
Line 19203  sub modify_loadbalancing { Line 13375  sub modify_loadbalancing {
                                 }                                  }
                             }                              }
                         }                          }
                         if ($changes{'curr'}{$balancer}{'cookie'}) {                          if (keys(%toupdate)) {
                             if ($currcookies{$balancer}) {                              my %thismachine;
                                 $resulttext .= '<li>'.&mt('Load Balancer: [_1] -- cookie use disabled',                              my $updatedhere;
                                                           $balancer).'</li>';                              my $cachetime = 60*60*24;
                             } else {                              map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
                                 $resulttext .= '<li>'.&mt('Load Balancer: [_1] -- cookie use enabled',                              foreach my $lonhost (keys(%toupdate)) {
                                                           $balancer).'</li>';                                  if ($thismachine{$lonhost}) {
                             }                                      unless ($updatedhere) {
                         }                                          &Apache::lonnet::do_cache_new('loadbalancing',$dom,
                     }                                                                        $defaultshash{'loadbalancing'},
                 }                                                                        $cachetime);
                 if (keys(%toupdate)) {                                          $updatedhere = 1;
                     my %thismachine;                                      }
                     my $updatedhere;                                  } else {
                     my $cachetime = 60*60*24;                                      my $cachekey = &escape('loadbalancing').':'.&escape($dom);
                     map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();                                      &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
                     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]);  
                         }                          }
                     }                      }
                 }                  }
Line 19291  sub recurse_cat_deletes { Line 13454  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 = &Apache::lonnet::get_active_domroles($dom,['dc']);      my %domcoords = &get_active_dcs($dom);
     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 19441  sub lonbalance_targets_js { Line 13619  sub lonbalance_targets_js {
     }      }
     push(@alltypes,'default','_LC_adv','_LC_author','_LC_internetdom','_LC_external');      push(@alltypes,'default','_LC_adv','_LC_author','_LC_internetdom','_LC_external');
     $allinsttypes = join("','",@alltypes);      $allinsttypes = join("','",@alltypes);
     my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);      my (%currbalancer,%currtargets,%currrules,%existing);
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         %existing = %{$settings};          %existing = %{$settings};
     }      }
     &get_loadbalancers_config($servers,\%existing,\%currbalancer,      &get_loadbalancers_config($servers,\%existing,\%currbalancer,
                               \%currtargets,\%currrules,\%currcookies);                                \%currtargets,\%currrules);
     my $balancers = join("','",sort(keys(%currbalancer)));      my $balancers = join("','",sort(keys(%currbalancer)));
     return <<"END";      return <<"END";
   
Line 19899  function updateCaptcha(caller,context) { Line 14077  function updateCaptcha(caller,context) {
             privtext.innerHTML = "$lt{'priv'}";              privtext.innerHTML = "$lt{'priv'}";
             versionitem.type = 'text';              versionitem.type = 'text';
             versionitem.size = '3';              versionitem.size = '3';
             versiontext.innerHTML = "$lt{'ver'}";              versiontext.innerHTML = "$lt{'ver'}"; 
         } else {          } else {
             pubitem.type = 'hidden';              pubitem.type = 'hidden';
             privitem.type = 'hidden';              privitem.type = 'hidden';
Line 19931  function toggleDisplay(domForm,caller) { Line 14109  function toggleDisplay(domForm,caller) {
         var optionsElement = domForm.coursecredits;          var optionsElement = domForm.coursecredits;
         var checkval = 1;          var checkval = 1;
         var dispval = 'block';          var dispval = 'block';
         var selfcreateRegExp = /^cancreate_emailverified/;  
         if (caller == 'emailoptions') {          if (caller == 'emailoptions') {
             optionsElement = domForm.cancreate_email;               optionsElement = domForm.cancreate_email; 
         }          }
Line 19942  function toggleDisplay(domForm,caller) { Line 14119  function toggleDisplay(domForm,caller) {
             optionsElement = domForm.canclone;              optionsElement = domForm.canclone;
             checkval = 'instcode';              checkval = 'instcode';
         }          }
         if (selfcreateRegExp.test(caller)) {  
             optionsElement = domForm.elements[caller];  
             checkval = 'other';  
             dispval = 'inline'  
         }  
         if (optionsElement.length) {          if (optionsElement.length) {
             var currval;              var currval;
             for (var i=0; i<optionsElement.length; i++) {              for (var i=0; i<optionsElement.length; i++) {
Line 19978  sub captcha_phrases { Line 14150  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)',                   ver => 'ReCAPTCHA version (1 or 2)', 
     );      );
 }  }
   
Line 19988  sub devalidate_remote_domconfs { Line 14160  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','ltitools','usersessions',      my @posscached = ('domainconfig','domdefaults','ltitools');
                       'directorysrch','passwdconf','cats','proxyalias','proxysaml',  
                       'ipaccess');  
     my %cache_by_lonhost;  
     if (exists($cachekeys->{'samllanding'})) {  
         if (ref($cachekeys->{'samllanding'}) eq 'HASH') {  
             my %landing = %{$cachekeys->{'samllanding'}};  
             my %domservers = &Apache::lonnet::get_servers($dom);  
             if (keys(%domservers)) {  
                 foreach my $server (keys(%domservers)) {  
                     my @cached;  
                     next if ($thismachine{$server});  
                     if ($landing{$server}) {  
                         push(@cached,&escape('samllanding').':'.&escape($server));  
                     }  
                     if (@cached) {  
                         $cache_by_lonhost{$server} = \@cached;  
                     }  
                 }  
             }  
         }  
     }  
     if (keys(%servers)) {      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;
             foreach my $name (@posscached) {              foreach my $name (@posscached) {
                 if ($cachekeys->{$name}) {                  if ($cachekeys->{$name}) {
                     if (($name eq 'proxyalias') || ($name eq 'proxysaml')) {                      push(@cached,&escape($name).':'.&escape($dom));
                         if (ref($cachekeys->{$name}) eq 'HASH') {  
                             foreach my $key (keys(%{$cachekeys->{$name}})) {  
                                 push(@cached,&escape($name).':'.&escape($key));  
                             }  
                         }  
                     } else {  
                         push(@cached,&escape($name).':'.&escape($dom));  
                     }  
                 }                  }
             }              }
             if ((exists($cache_by_lonhost{$server})) &&  
                 (ref($cache_by_lonhost{$server}) eq 'ARRAY')) {  
                 push(@cached,@{$cache_by_lonhost{$server}});  
             }  
             if (@cached) {              if (@cached) {
                 &Apache::lonnet::remote_devalidate_cache($server,\@cached);                  &Apache::lonnet::remote_devalidate_cache($server,\@cached);
             }              }

Removed from v.1.160.6.118.2.12  
changed lines
  Added in v.1.284


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