Diff for /loncom/interface/domainprefs.pm between versions 1.160.6.6 and 1.303

version 1.160.6.6, 2012/09/25 20:38:47 version 1.303, 2017/07/26 19:45:45
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/
 #  #
 #  #
 ###############################################################  ###############################################################
 ##############################################################  ###############################################################
   
 =pod  =pod
   
Line 45  described at http://www.lon-capa.org. Line 46  described at http://www.lon-capa.org.
 =head1 OVERVIEW  =head1 OVERVIEW
   
 Each institution using LON-CAPA will typically have a single domain designated   Each institution using LON-CAPA will typically have a single domain designated 
 for use by individuals affliated with the institution.  Accordingly, each domain  for use by individuals affiliated with the institution.  Accordingly, each domain
 may define a default set of logos and a color scheme which can be used to "brand"  may define a default set of logos and a color scheme which can be used to "brand"
 the LON-CAPA instance. In addition, an institution will typically have a language  the LON-CAPA instance. In addition, an institution will typically have a language
 and timezone which are used for the majority of courses.  and timezone which are used for the majority of courses.
Line 86  $dom,$settings,$rowtotal,$action. Line 87  $dom,$settings,$rowtotal,$action.
   
 $dom is the domain, $settings is a reference to a hash of current settings for  $dom is the domain, $settings is a reference to a hash of current settings for
 the current context, $rowtotal is a reference to the scalar used to record the   the current context, $rowtotal is a reference to the scalar used to record the 
 number of rows displayed on the page, and $action is the context (quotas,  number of rows displayed on the page, and $action is the context (quotas, 
 requestcourses or requestauthor).  requestcourses or requestauthor).
   
 The print_quotas routine was orginally created to display/store information  The print_quotas routine was orginally created to display/store information
Line 94  about default quota sizes for portfolio Line 95  about default quota sizes for portfolio
 institutional affiliation in the domain (e.g., Faculty, Staff, Student etc.),   institutional affiliation in the domain (e.g., Faculty, Staff, Student etc.), 
 but is now also used to manage availability of user tools:   but is now also used to manage availability of user tools: 
 i.e., blogs, aboutme page, and portfolios, and the course request tool,  i.e., blogs, aboutme page, and portfolios, and the course request tool,
 used by course owners to request creation of a course.  used by course owners to request creation of a course, and to display/store
   default quota sizes for Authoring Spaces.
   
 Outputs: 1  Outputs: 1
   
Line 102  $datatable  - HTML containing form eleme Line 104  $datatable  - HTML containing form eleme
   
 In the case of course requests, radio buttons are displayed for each institutional  In the case of course requests, radio buttons are displayed for each institutional
 affiliate type (and also default, and _LC_adv) for each of the course types   affiliate type (and also default, and _LC_adv) for each of the course types 
 (official, unofficial and community).  In each case the radio buttons allow the   (official, unofficial, community, textbook, and placement).  
 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 163  use Apache::lonhtmlcommon(); Line 165  use Apache::lonhtmlcommon();
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonmsg();  use Apache::lonmsg();
 use Apache::lonconfigsettings;  use Apache::lonconfigsettings;
   use Apache::lonuserutils();
   use Apache::loncoursequeueadmin();
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
 use LONCAPA::Enrollment;  use LONCAPA::Enrollment;
 use LONCAPA::lonauthcgi();  use LONCAPA::lonauthcgi();
   use LONCAPA::SSL;
 use File::Copy;  use File::Copy;
 use Locale::Language;  use Locale::Language;
 use DateTime::TimeZone;  use DateTime::TimeZone;
 use DateTime::Locale;  use DateTime::Locale;
   use Time::HiRes qw( sleep );
   
 my $registered_cleanup;  my $registered_cleanup;
 my $modified_urls;  my $modified_urls;
Line 210  sub handler { Line 216  sub handler {
                 'quotas','autoenroll','autoupdate','autocreate',                  'quotas','autoenroll','autoupdate','autocreate',
                 'directorysrch','usercreation','usermodification',                  'directorysrch','usercreation','usermodification',
                 'contacts','defaults','scantron','coursecategories',                  'contacts','defaults','scantron','coursecategories',
                 'serverstatuses','requestcourses','usersessions',                  'serverstatuses','requestcourses','helpsettings',
                 'loadbalancing','requestauthor'],$dom);                  'coursedefaults','usersessions','loadbalancing',
                   'requestauthor','selfenrollment','inststatus',
                   'ltitools','ssl','trust'],$dom);
       if (ref($domconfig{'ltitools'}) eq 'HASH') {
           my %encconfig =
               &Apache::lonnet::get_dom('encconfig',['ltitools'],$dom);
           if (ref($encconfig{'ltitools'}) eq 'HASH') {
               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};
                       }
                   }
               }
           }
       }
     my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',      my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
                        'autoupdate','autocreate','directorysrch','contacts',                         'autoupdate','autocreate','directorysrch','contacts',
                        'usercreation','usermodification','scantron',                         'usercreation','selfcreation','usermodification','scantron',
                        'requestcourses','requestauthor','coursecategories',                         'requestcourses','requestauthor','coursecategories',
                        'serverstatuses','usersessions');                         'serverstatuses','helpsettings','coursedefaults',
     if (keys(%servers) > 1) {                         'ltitools','selfenrollment','usersessions','ssl','trust');
       my %existing;
       if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
           %existing = %{$domconfig{'loadbalancing'}};
       }
       if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
         push(@prefs_order,'loadbalancing');          push(@prefs_order,'loadbalancing');
     }      }
     my %prefs = (      my %prefs = (
Line 232  sub handler { Line 258  sub handler {
                                  col2 => '',},                                   col2 => '',},
                                 {col1 => 'Administrator Settings',                                  {col1 => 'Administrator Settings',
                                  col2 => '',}],                                   col2 => '',}],
                         print => \&print_rolecolors,
                         modify => \&modify_rolecolors,
                     },                      },
         'login' =>          'login' =>
                     { text => 'Log-in page options',                      { text => 'Log-in page options',
Line 239  sub handler { Line 267  sub handler {
                       header => [{col1 => 'Log-in Page Items',                        header => [{col1 => 'Log-in Page Items',
                                   col2 => '',},                                    col2 => '',},
                                  {col1 => 'Log-in Help',                                   {col1 => 'Log-in Help',
                                     col2 => 'Value'},
                                    {col1 => 'Custom HTML in document head',
                                   col2 => 'Value'}],                                    col2 => 'Value'}],
                         print => \&print_login,
                         modify => \&modify_login,
                     },                      },
         'defaults' =>           'defaults' => 
                     { text => 'Default authentication/language/timezone/portal',                      { text => 'Default authentication/language/timezone/portal/types',
                       help => 'Domain_Configuration_LangTZAuth',                        help => 'Domain_Configuration_LangTZAuth',
                       header => [{col1 => 'Setting',                        header => [{col1 => 'Setting',
                                   col2 => 'Value'}],                                    col2 => 'Value'},
                                    {col1 => 'Internal Authentication',
                                     col2 => 'Value'},
                                    {col1 => 'Institutional user types',
                                     col2 => 'Assignable to non-institutional users'}],
                         print => \&print_defaults,
                         modify => \&modify_defaults,
                     },                      },
         'quotas' =>           'quotas' => 
                     { text => 'Blogs, personal web pages, webDAV, portfolios',                      { 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',
                                   col3 => 'Portfolio quota',}],                                    col3 => 'Quotas, MB; (Authoring requires role)',}],
                         print => \&print_quotas,
                         modify => \&modify_quotas,
                     },                      },
         'autoenroll' =>          'autoenroll' =>
                    { text => 'Auto-enrollment settings',                     { text => 'Auto-enrollment settings',
                      help => 'Domain_Configuration_Auto_Enrollment',                       help => 'Domain_Configuration_Auto_Enrollment',
                      header => [{col1 => 'Configuration setting',                       header => [{col1 => 'Configuration setting',
                                  col2 => 'Value(s)'}],                                   col2 => 'Value(s)'}],
                        print => \&print_autoenroll,
                        modify => \&modify_autoenroll,
                    },                     },
         'autoupdate' =>           'autoupdate' => 
                    { text => 'Auto-update settings',                     { text => 'Auto-update settings',
Line 268  sub handler { Line 310  sub handler {
                                 {col1 => 'Setting',                                  {col1 => 'Setting',
                                  col2 => 'Affiliation'},                                   col2 => 'Affiliation'},
                                 {col1 => 'User population',                                  {col1 => 'User population',
                                  col2 => 'Updateable user data'}],                                   col2 => 'Updatable user data'}],
                        print => \&print_autoupdate,
                        modify => \&modify_autoupdate,
                   },                    },
         'autocreate' =>           'autocreate' => 
                   { text => 'Auto-course creation settings',                    { text => 'Auto-course creation settings',
                      help => 'Domain_Configuration_Auto_Creation',                       help => 'Domain_Configuration_Auto_Creation',
                      header => [{col1 => 'Configuration Setting',                       header => [{col1 => 'Configuration Setting',
                                  col2 => 'Value',}],                                   col2 => 'Value',}],
                        print => \&print_autocreate,
                        modify => \&modify_autocreate,
                   },                    },
         'directorysrch' =>           'directorysrch' => 
                   { text => 'Institutional directory searches',                    { text => 'Directory searches',
                     help => 'Domain_Configuration_InstDirectory_Search',                      help => 'Domain_Configuration_InstDirectory_Search',
                     header => [{col1 => 'Setting',                      header => [{col1 => 'Institutional Directory Setting',
                                   col2 => 'Value',},
                                  {col1 => 'LON-CAPA Directory Setting',
                                 col2 => 'Value',}],                                  col2 => 'Value',}],
                       print => \&print_directorysrch,
                       modify => \&modify_directorysrch,
                   },                    },
         'contacts' =>          'contacts' =>
                   { text => 'Contact Information',                    { text => 'E-mail addresses and helpform',
                     help => 'Domain_Configuration_Contact_Info',                      help => 'Domain_Configuration_Contact_Info',
                     header => [{col1 => 'Setting',                      header => [{col1 => 'Default e-mail addresses',
                                 col2 => 'Value',}],                                  col2 => 'Value',},
                                  {col1 => 'Recipient(s) for notifications',
                                   col2 => 'Value',},
                                  {col1 => 'Ask helpdesk form settings',
                                   col2 => 'Value',},],
                       print => \&print_contacts,
                       modify => \&modify_contacts,
                   },                    },
   
         'usercreation' =>           'usercreation' => 
                   { text => 'User creation',                    { text => 'User creation',
                     help => 'Domain_Configuration_User_Creation',                      help => 'Domain_Configuration_User_Creation',
Line 298  sub handler { Line 353  sub handler {
                                 col2 => 'Usernames which may be created',},                                  col2 => 'Usernames which may be created',},
                                {col1 => 'Context',                                 {col1 => 'Context',
                                 col2 => 'Assignable authentication types'}],                                  col2 => 'Assignable authentication types'}],
                       print => \&print_usercreation,
                       modify => \&modify_usercreation,
                     },
           'selfcreation' => 
                     { text => 'Users self-creating accounts',
                       help => 'Domain_Configuration_Self_Creation', 
                       header => [{col1 => 'Self-creation with institutional username',
                                   col2 => 'Enabled?'},
                                  {col1 => 'Institutional user type (login/SSO self-creation)',
                                   col2 => 'Information user can enter'},
                                  {col1 => 'Self-creation with e-mail verification',
                                   col2 => 'Settings'}],
                       print => \&print_selfcreation,
                       modify => \&modify_selfcreation,
                   },                    },
         'usermodification' =>          'usermodification' =>
                   { text => 'User modification',                    { text => 'User modification',
                     help => 'Domain_Configuration_User_Modification',                      help => 'Domain_Configuration_User_Modification',
                     header => [{col1 => 'Target user has role',                      header => [{col1 => 'Target user has role',
                                 col2 => 'User information updateable in author context'},                                  col2 => 'User information updatable in author context'},
                                {col1 => 'Target user has role',                                 {col1 => 'Target user has role',
                                 col2 => 'User information updateable in course context'},                                  col2 => 'User information updatable in course context'}],
                                {col1 => "Status of user",                      print => \&print_usermodification,
                                 col2 => 'Information settable when self-creating account (if directory data blank)'}],                      modify => \&modify_usermodification,
                   },                    },
         'scantron' =>          'scantron' =>
                   { text => 'Bubblesheet format file',                    { text => 'Bubblesheet format file',
Line 315  sub handler { Line 384  sub handler {
                     header => [ {col1 => 'Item',                      header => [ {col1 => 'Item',
                                  col2 => '',                                   col2 => '',
                               }],                                }],
                       print => \&print_scantron,
                       modify => \&modify_scantron,
                   },                    },
         'requestcourses' =>           'requestcourses' => 
                  {text => 'Request creation of courses',                   {text => 'Request creation of courses',
Line 322  sub handler { Line 393  sub handler {
                   header => [{col1 => 'User affiliation',                    header => [{col1 => 'User affiliation',
                               col2 => 'Availability/Processing of requests',},                                col2 => 'Availability/Processing of requests',},
                              {col1 => 'Setting',                               {col1 => 'Setting',
                               col2 => 'Value'}],                                col2 => 'Value'},
                                {col1 => 'Available textbooks',
                                 col2 => ''},
                                {col1 => 'Available templates',
                                 col2 => ''},
                                {col1 => 'Validation (not official courses)',
                                 col2 => 'Value'},],
                     print => \&print_quotas,
                     modify => \&modify_quotas,
                  },                   },
         'requestauthor' =>          'requestauthor' =>
                  {text => 'Request authoring space',                   {text => 'Request Authoring Space',
                   help => 'Domain_Configuration_Request_Author',                    help => 'Domain_Configuration_Request_Author',
                   header => [{col1 => 'User affiliation',                    header => [{col1 => 'User affiliation',
                               col2 => 'Availability/Processing of requests',},                                col2 => 'Availability/Processing of requests',},
                              {col1 => 'Setting',                               {col1 => 'Setting',
                               col2 => 'Value'}],                                col2 => 'Value'}],
                     print => \&print_quotas,
                     modify => \&modify_quotas,
                  },                   },
         'coursecategories' =>          'coursecategories' =>
                   { text => 'Cataloging of courses/communities',                    { text => 'Cataloging of courses/communities',
                     help => 'Domain_Configuration_Cataloging_Courses',                      help => 'Domain_Configuration_Cataloging_Courses',
                     header => [{col1 => 'Category settings',                      header => [{col1 => 'Catalog type/availability',
                                   col2 => '',},
                                  {col1 => 'Category settings for standard catalog',
                                 col2 => '',},                                  col2 => '',},
                                {col1 => 'Categories',                                 {col1 => 'Categories',
                                 col2 => '',                                  col2 => '',
                                }],                                 }],
                       print => \&print_coursecategories,
                       modify => \&modify_coursecategories,
                   },                    },
         'serverstatuses' =>          'serverstatuses' =>
                  {text   => 'Access to server status pages',                   {text   => 'Access to server status pages',
Line 348  sub handler { Line 433  sub handler {
                               col2 => 'Other named users',                                col2 => 'Other named users',
                               col3 => 'Specific IPs',                                col3 => 'Specific IPs',
                             }],                              }],
                     print => \&print_serverstatuses,
                     modify => \&modify_serverstatuses,
                    },
           'helpsettings' =>
                    {text   => 'Support settings',
                     help   => 'Domain_Configuration_Help_Settings',
                     header => [{col1 => 'Help Page Settings (logged-in users)',
                                 col2 => 'Value'},
                                {col1 => 'Helpdesk Roles',
                                 col2 => 'Settings'},],
                     print  => \&print_helpsettings,
                     modify => \&modify_helpsettings,
                    },
           'coursedefaults' => 
                    {text => 'Course/Community defaults',
                     help => 'Domain_Configuration_Course_Defaults',
                     header => [{col1 => 'Defaults which can be overridden in each course by a CC',
                                 col2 => 'Value',},
                                {col1 => 'Defaults which can be overridden for each course by a DC',
                                 col2 => 'Value',},],
                     print => \&print_coursedefaults,
                     modify => \&modify_coursedefaults,
                    },
           'selfenrollment' => 
                    {text   => 'Self-enrollment in Course/Community',
                     help   => 'Domain_Configuration_Selfenrollment',
                     header => [{col1 => 'Configuration Rights',
                                 col2 => 'Configured by Course Personnel or Domain Coordinator?'},
                                {col1 => 'Defaults',
                                 col2 => 'Value'},
                                {col1 => 'Self-enrollment validation (optional)',
                                 col2 => 'Value'},],
                     print => \&print_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',
Line 358  sub handler { Line 485  sub handler {
                               col2 => 'Rules'},                                col2 => 'Rules'},
                              {col1 => "Hosting domain's own users elsewhere",                               {col1 => "Hosting domain's own users elsewhere",
                               col2 => 'Rules'}],                                col2 => 'Rules'}],
                     print => \&print_usersessions,
                     modify => \&modify_usersessions,
                  },                   },
          'loadbalancing' =>          'loadbalancing' =>
                  {text  => 'Dedicated Load Balancer',                   {text  => 'Dedicated Load Balancer(s)',
                   help  => 'Domain_Configuration_Load_Balancing',                    help  => 'Domain_Configuration_Load_Balancing',
                   header => [{col1 => 'Server',                    header => [{col1 => 'Balancers',
                               col2 => 'Default destinations',                                col2 => 'Default destinations',
                               col3 => 'User affliation',                                col3 => 'User affiliation',
                               col4 => 'Overrides'},                                col4 => 'Overrides'},
                             ],                              ],
                     print => \&print_loadbalancing,
                     modify => \&modify_loadbalancing,
                    },
           'ltitools' => 
                    {text => 'External Tools (LTI)',
                     help => 'Domain_Configuration_LTI_Tools',
                     header => [{col1 => 'Setting',
                                 col2 => 'Value',}],
                     print => \&print_ltitools,
                     modify => \&modify_ltitools,
                    },
           'ssl' =>
                    {text  => 'LON-CAPA Network (SSL)',
                     help  => 'Domain_Configuration_Network_SSL',
                     header => [{col1 => 'Server',
                                 col2 => 'Certificate Status'},
                                {col1 => 'Connections to other servers',
                                 col2 => 'Rules'},
                                {col1 => 'Connections from other servers',
                                 col2 => 'Rules'},
                                {col1 => "Replicating domain's published content",
                                 col2 => 'Rules'}],
                     print => \&print_ssl,
                     modify => \&modify_ssl,
                    },
           'trust' =>
                    {text   => 'Trust Settings',
                     help   => 'Domain_Configuration_Trust',
                     header => [{col1 => "Access to this domain's content by others",
                                 col2 => 'Rules'},
                                {col1 => "Access to other domain's content by this domain",
                                 col2 => 'Rules'},
                                {col1 => "Enrollment in this domain's courses by others",
                                 col2 => 'Rules',},
                                {col1 => "Co-author roles in this domain for others",
                                 col2 => 'Rules',},
                                {col1 => "Co-author roles for this domain's users elsewhere",
                                 col2 => 'Rules',},
                                {col1 => "Domain roles in this domain assignable to others",
                                 col2 => 'Rules'},
                                {col1 => "Course catalog for this domain displayed elsewhere",
                                 col2 => 'Rules'},
                                {col1 => "Requests for creation of courses in this domain by others",
                                 col2 => 'Rules'},
                                {col1 => "Users in other domains can send messages to this domain",
                                 col2 => 'Rules'},],
                     print => \&print_trust,
                     modify => \&modify_trust,
                  },                   },
     );      );
     if (keys(%servers) > 1) {      if (keys(%servers) > 1) {
Line 377  sub handler { Line 554  sub handler {
                                        {col1 => 'Log-in Page Items',                                         {col1 => 'Log-in Page Items',
                                         col2 => ''},                                          col2 => ''},
                                        {col1 => 'Log-in Help',                                         {col1 => 'Log-in Help',
                                           col2 => 'Value'},
                                          {col1 => 'Custom HTML in document head',
                                         col2 => 'Value'}],                                          col2 => 'Value'}],
                               print => \&print_login,
                               modify => \&modify_login,
                            };                             };
     }      }
   
     my @roles = ('student','coordinator','author','admin');      my @roles = ('student','coordinator','author','admin');
     my @actions = &Apache::loncommon::get_env_multiple('form.actions');      my @actions = &Apache::loncommon::get_env_multiple('form.actions');
     &Apache::lonhtmlcommon::add_breadcrumb      &Apache::lonhtmlcommon::add_breadcrumb
     ({href=>"javascript:changePage(document.$phase,'pickactions')",      ({href=>"javascript:changePage(document.$phase,'pickactions')",
       text=>"Settings to display/modify"});        text=>"Settings to display/modify"});
     my $confname = $dom.'-domainconfig';      my $confname = $dom.'-domainconfig';
   
     if ($phase eq 'process') {      if ($phase eq 'process') {
         &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,\@roles);          my $result = &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,
                                                                 \%prefs,\%domconfig,$confname,\@roles);
           if ((ref($result) eq 'HASH') && (keys(%{$result}))) {
               $r->rflush();
               &devalidate_remote_domconfs($dom,$result);
           }
     } elsif ($phase eq 'display') {      } elsif ($phase eq 'display') {
         my $js = &recaptcha_js();          my $js = &recaptcha_js().
         if (keys(%servers) > 1) {                   &toggle_display_js();
           if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
             my ($othertitle,$usertypes,$types) =              my ($othertitle,$usertypes,$types) =
                 &Apache::loncommon::sorted_inst_types($dom);                  &Apache::loncommon::sorted_inst_types($dom);
             $js .= &lonbalance_targets_js($dom,$types,\%servers).              $js .= &lonbalance_targets_js($dom,$types,\%servers,
                                             $domconfig{'loadbalancing'}).
                    &new_spares_js().                     &new_spares_js().
                    &common_domprefs_js().                     &common_domprefs_js().
                    &Apache::loncommon::javascript_array_indexof();                     &Apache::loncommon::javascript_array_indexof();
         }          }
           if (grep(/^requestcourses$/,@actions)) {
               my $javascript_validations;
               my $coursebrowserjs=&Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'}); 
               $js .= <<END;
   <script type="text/javascript">
   $javascript_validations
   </script>
   $coursebrowserjs
   END
           }
           if (grep(/^contacts$/,@actions)) {
               $js .= &contacts_javascript();
           }
         &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);          &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);
     } else {      } else {
   # check if domconfig user exists for the domain.
           my $servadm = $r->dir_config('lonAdmEMail');
           my ($configuserok,$author_ok,$switchserver) =
               &config_check($dom,$confname,$servadm);
           unless ($configuserok eq 'ok') {
               &Apache::lonconfigsettings::print_header($r,$phase,$context);
               $r->print(&mt('The domain configuration user "[_1]" has yet to be created.',
                             $confname).
                         '<br />'
               );
               if ($switchserver) {
                   $r->print(&mt('Ordinarily, that domain configuration user is created when the ./UPDATE script is run to install LON-CAPA for the first time.').
                             '<br />'.
                             &mt('However, that does not apply when new domains are added to a multi-domain server, and ./UPDATE has not been run recently.').
                             '<br />'.
                             &mt('The "[_1]" user can be created automatically when a Domain Coordinator visits the web-based "Set domain configuration" screen, in a session hosted on the primary library server.',$confname).
                             '<br />'.
                             &mt('To do that now, use the following link: [_1]',$switchserver)
                   );
               } else {
                   $r->print(&mt('To create that user from the command line run the ./UPDATE script found in the top level directory of the extracted LON-CAPA tarball.').
                             '<br />'.
                             &mt('Once that is done, you will be able to use the web-based "Set domain configuration" to configure the domain')
                   );
               }
               $r->print(&Apache::loncommon::end_page());
               return OK;
           }
         if (keys(%domconfig) == 0) {          if (keys(%domconfig) == 0) {
             my $primarylibserv = &Apache::lonnet::domain($dom,'primary');              my $primarylibserv = &Apache::lonnet::domain($dom,'primary');
             my @ids=&Apache::lonnet::current_machine_ids();              my @ids=&Apache::lonnet::current_machine_ids();
Line 439  sub handler { Line 670  sub handler {
 }  }
   
 sub process_changes {  sub process_changes {
     my ($r,$dom,$confname,$action,$roles,$values) = @_;      my ($r,$dom,$confname,$action,$roles,$values,$lastactref) = @_;
     my %domconfig;      my %domconfig;
     if (ref($values) eq 'HASH') {      if (ref($values) eq 'HASH') {
         %domconfig = %{$values};          %domconfig = %{$values};
     }      }
     my $output;      my $output;
     if ($action eq 'login') {      if ($action eq 'login') {
         $output = &modify_login($r,$dom,$confname,%domconfig);          $output = &modify_login($r,$dom,$confname,$lastactref,%domconfig);
     } elsif ($action eq 'rolecolors') {      } elsif ($action eq 'rolecolors') {
         $output = &modify_rolecolors($r,$dom,$confname,$roles,          $output = &modify_rolecolors($r,$dom,$confname,$roles,
                                      %domconfig);                                       $lastactref,%domconfig);
     } elsif ($action eq 'quotas') {      } elsif ($action eq 'quotas') {
         $output = &modify_quotas($dom,$action,%domconfig);          $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);
     } elsif ($action eq 'autoenroll') {      } elsif ($action eq 'autoenroll') {
         $output = &modify_autoenroll($dom,%domconfig);          $output = &modify_autoenroll($dom,$lastactref,%domconfig);
     } elsif ($action eq 'autoupdate') {      } elsif ($action eq 'autoupdate') {
         $output = &modify_autoupdate($dom,%domconfig);          $output = &modify_autoupdate($dom,%domconfig);
     } elsif ($action eq 'autocreate') {      } elsif ($action eq 'autocreate') {
         $output = &modify_autocreate($dom,%domconfig);          $output = &modify_autocreate($dom,%domconfig);
     } elsif ($action eq 'directorysrch') {      } elsif ($action eq 'directorysrch') {
         $output = &modify_directorysrch($dom,%domconfig);          $output = &modify_directorysrch($dom,$lastactref,%domconfig);
     } elsif ($action eq 'usercreation') {      } elsif ($action eq 'usercreation') {
         $output = &modify_usercreation($dom,%domconfig);          $output = &modify_usercreation($dom,%domconfig);
       } elsif ($action eq 'selfcreation') {
           $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') {
         $output = &modify_contacts($dom,%domconfig);          $output = &modify_contacts($dom,$lastactref,%domconfig);
     } elsif ($action eq 'defaults') {      } elsif ($action eq 'defaults') {
         $output = &modify_defaults($dom,$r);          $output = &modify_defaults($dom,$lastactref,%domconfig);
     } elsif ($action eq 'scantron') {      } elsif ($action eq 'scantron') {
         $output = &modify_scantron($r,$dom,$confname,%domconfig);          $output = &modify_scantron($r,$dom,$confname,$lastactref,%domconfig);
     } elsif ($action eq 'coursecategories') {      } elsif ($action eq 'coursecategories') {
         $output = &modify_coursecategories($dom,%domconfig);          $output = &modify_coursecategories($dom,$lastactref,%domconfig);
     } elsif ($action eq 'serverstatuses') {      } elsif ($action eq 'serverstatuses') {
         $output = &modify_serverstatuses($dom,%domconfig);          $output = &modify_serverstatuses($dom,%domconfig);
     } elsif ($action eq 'requestcourses') {      } elsif ($action eq 'requestcourses') {
         $output = &modify_quotas($dom,$action,%domconfig);          $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);
     } elsif ($action eq 'requestauthor') {      } elsif ($action eq 'requestauthor') {
         $output = &modify_quotas($dom,$action,%domconfig);          $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);
       } elsif ($action eq 'helpsettings') {
           $output = &modify_helpsettings($r,$dom,$confname,$lastactref,%domconfig);
       } elsif ($action eq 'coursedefaults') {
           $output = &modify_coursedefaults($dom,$lastactref,%domconfig);
       } elsif ($action eq 'selfenrollment') {
           $output = &modify_selfenrollment($dom,$lastactref,%domconfig)
     } elsif ($action eq 'usersessions') {      } elsif ($action eq 'usersessions') {
         $output = &modify_usersessions($dom,%domconfig);          $output = &modify_usersessions($dom,$lastactref,%domconfig);
     } elsif ($action eq 'loadbalancing') {      } elsif ($action eq 'loadbalancing') {
         $output = &modify_loadbalancing($dom,%domconfig);          $output = &modify_loadbalancing($dom,%domconfig);
       } elsif ($action eq 'ltitools') {
           $output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig);
       } elsif ($action eq 'ssl') {
           $output = &modify_ssl($dom,$lastactref,%domconfig);
       } elsif ($action eq 'trust') {
           $output = &modify_trust($dom,$lastactref,%domconfig);
     }      }
     return $output;      return $output;
 }  }
Line 492  sub print_config_box { Line 737  sub print_config_box {
     my $output;      my $output;
     if ($action eq 'coursecategories') {      if ($action eq 'coursecategories') {
         $output = &coursecategories_javascript($settings);          $output = &coursecategories_javascript($settings);
       } elsif ($action eq 'defaults') {
           $output = &defaults_javascript($settings); 
       } elsif ($action eq 'helpsettings') {
           my (%privs,%levelscurrent);
           my %full=();
           my %levels=(
                        course => {},
                        domain => {},
                        system => {},
                      );
           my $context = 'domain';
           my $crstype = 'Course';
           my $formname = 'display';
           &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
           my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
           $output =
               &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full, 
                                                         \@templateroles);
     }      }
     $output .=       $output .=
          '<table class="LC_nested_outer">           '<table class="LC_nested_outer">
           <tr>            <tr>
            <th align="left" valign="middle"><span class="LC_nobreak">'.             <th align="left" valign="middle"><span class="LC_nobreak">'.
Line 508  sub print_config_box { Line 771  sub print_config_box {
     if ($numheaders > 1) {      if ($numheaders > 1) {
         my $colspan = '';          my $colspan = '';
         my $rightcolspan = '';          my $rightcolspan = '';
         if (($action eq 'rolecolors') || ($action eq 'coursecategories') ||          if (($action eq 'rolecolors') || ($action eq 'defaults') ||
             (($action eq 'login') && ($numheaders < 3))) {              ($action eq 'directorysrch') ||
               (($action eq 'login') && ($numheaders < 4))) {
             $colspan = ' colspan="2"';              $colspan = ' colspan="2"';
         }          }
         if ($action eq 'usersessions') {          if ($action eq 'usersessions') {
Line 524  sub print_config_box { Line 788  sub print_config_box {
               <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') {          if (($action eq 'autoupdate') || ($action eq 'usercreation') || ($action eq 'selfcreation') ||
             $output .= &print_autoupdate('top',$dom,$settings,\$rowtotal);              ($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') ||
         } elsif ($action eq 'usercreation') {              ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'ssl') ||
             $output .= &print_usercreation('top',$dom,$settings,\$rowtotal);              ($action eq 'directorysrch') || ($action eq 'trust') || ($action eq 'helpsettings') ||
         } elsif ($action eq 'usermodification') {              ($action eq 'contacts')) {
             $output .= &print_usermodification('top',$dom,$settings,\$rowtotal);              $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'coursecategories') {          } elsif ($action eq 'coursecategories') {
             $output .= &print_coursecategories('top',$dom,$item,$settings,\$rowtotal);              $output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal);
         } elsif ($action eq 'login') {          } elsif ($action eq 'login') {
             if ($numheaders == 3) {              if ($numheaders == 4) {
                 $colspan = ' colspan="2"';                  $colspan = ' colspan="2"';
                 $output .= &print_login('service',$dom,$confname,$phase,$settings,\$rowtotal);                  $output .= &print_login('service',$dom,$confname,$phase,$settings,\$rowtotal);
             } else {              } else {
                 $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal);                  $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal);
             }              }
         } elsif ($action eq 'requestcourses') {          } elsif (($action eq 'requestcourses') || ($action eq 'requestauthor')) {
             $output .= &print_quotas($dom,$settings,\$rowtotal,$action);  
         } elsif ($action eq 'requestauthor') {  
             $output .= &print_quotas($dom,$settings,\$rowtotal,$action);              $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
         } elsif ($action eq 'usersessions') {  
             $output .= &print_usersessions('top',$dom,$settings,\$rowtotal);   
         } elsif ($action eq 'rolecolors') {          } elsif ($action eq 'rolecolors') {
             $output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal);              $output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal);
         }          }
Line 556  sub print_config_box { Line 816  sub print_config_box {
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col1'}).'</td>';                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col1'}).'</td>
         $output .= '  
               <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col2'}).'</td>                <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col2'}).'</td>
              </tr>';               </tr>';
             $rowtotal ++;              $rowtotal ++;
         if ($action eq 'autoupdate') {          if (($action eq 'autoupdate') || ($action eq 'usercreation') ||
             $output .= &print_autoupdate('middle',$dom,$settings,\$rowtotal).'              ($action eq 'selfcreation') || ($action eq 'selfenrollment') ||
               ($action eq 'usersessions') || ($action eq 'coursecategories') || 
               ($action eq 'trust') || ($action eq 'contacts') || ($action eq 'defaults')) {
               if ($action eq 'coursecategories') {
                   $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);
                   $colspan = ' colspan="2"';
               } elsif ($action eq 'trust') {
                   $output .= $item->{'print'}->('shared',$dom,$settings,\$rowtotal);
               } else {
                   $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);
               }
               if ($action eq 'trust') {
                   $output .= '
               </table>
             </td>
            </tr>';
                   my @trusthdrs = qw(2 3 4 5 6 7);
                   my @prefixes = qw(enroll othcoau coaurem domroles catalog reqcrs);
                   for (my $i=0; $i<@trusthdrs; $i++) {
                       $output .= '
            <tr>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[$trusthdrs[$i]]->{'col1'}).'</td>
                 <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[$trusthdrs[$i]]->{'col2'}).'</td></tr>'.
                              $item->{'print'}->($prefixes[$i],$dom,$settings,\$rowtotal).'
               </table>
             </td>
            </tr>';
                   }
                   $output .= '
            <tr>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[8]->{'col1'}).'</td>
                 <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[8]->{'col2'}).'</td></tr>'.
                              $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
               } else {
                   $output .= '
            </table>             </table>
           </td>            </td>
          </tr>           </tr>
Line 571  sub print_config_box { Line 870  sub print_config_box {
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>      </tr>'.                <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
             &print_autoupdate('bottom',$dom,$settings,\$rowtotal);               </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 'usercreation') {          } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||
             $output .= &print_usercreation('middle',$dom,$settings,\$rowtotal).'                   ($action eq 'defaults') || ($action eq 'directorysrch') ||
            </table>                   ($action eq 'helpsettings')) {
               $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
           } elsif ($action eq 'ssl') {
               $output .= $item->{'print'}->('connto',$dom,$settings,\$rowtotal).'
               </table>
           </td>            </td>
          </tr>           </tr>
          <tr>           <tr>
Line 584  sub print_config_box { Line 893  sub print_config_box {
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>             </tr>'.                <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td></tr>'.
             &print_usercreation('bottom',$dom,$settings,\$rowtotal);                             $item->{'print'}->('connfrom',$dom,$settings,\$rowtotal).'
             $rowtotal ++;              </table>
         } elsif ($action eq 'usermodification') {  
             $output .= &print_usermodification('middle',$dom,$settings,\$rowtotal).'  
            </table>  
           </td>            </td>
          </tr>           </tr>
          <tr>           <tr>
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>      </tr>'.                <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td></tr>'.
                        &print_usermodification('bottom',$dom,$settings,\$rowtotal);                             $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
             $rowtotal ++;  
         } elsif ($action eq 'coursecategories') {  
             $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);  
         } elsif ($action eq 'login') {          } elsif ($action eq 'login') {
             if ($numheaders == 3) {              if ($numheaders == 4) {
                 $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'                  $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'
            </table>             </table>
           </td>            </td>
Line 613  sub print_config_box { Line 916  sub print_config_box {
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td>      </tr>'.                <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td></tr>'.
                        &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);                         &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);
                 $rowtotal ++;                  $rowtotal ++;
             } else {              } else {
                 $output .= &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);                  $output .= &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);
             }              }
               $output .= '
              </table>
             </td>
            </tr>
            <tr>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">';
               if ($numheaders == 4) {
                   $output .= '
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
                 <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td>
                </tr>';
               } else {
                   $output .= '
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
                 <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
                </tr>';
               }
               $rowtotal ++;
               $output .= &print_login('headtag',$dom,$confname,$phase,$settings,\$rowtotal);
         } elsif ($action eq 'requestcourses') {          } elsif ($action eq 'requestcourses') {
             $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);              $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);
         } elsif ($action eq 'requestauthor') {              $rowtotal ++;
             $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);              $output .= &print_studentcode($settings,\$rowtotal).'
         } elsif ($action eq 'usersessions') {  
             $output .= &print_usersessions('middle',$dom,$settings,\$rowtotal).'  
            </table>             </table>
           </td>            </td>
          </tr>           </tr>
Line 633  sub print_config_box { Line 955  sub print_config_box {
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">               <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>                <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>      </tr>'.                <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td> </tr>'.
                        &print_usersessions('bottom',$dom,$settings,\$rowtotal);                         &textbookcourses_javascript($settings).
                          &print_textbookcourses($dom,'textbooks',$settings,\$rowtotal).'
               </table>
              </td>
             </tr>
            <tr>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
                 <td class="LC_right_item">'.&mt($item->{'header'}->[3]->{'col2'}).'</td> </tr>'.
                          &print_textbookcourses($dom,'templates',$settings,\$rowtotal).'
               </table>
              </td>
             </tr>
             <tr>
              <td>
               <table class="LC_nested">
                <tr class="LC_info_row">
                 <td class="LC_left_item"'.$colspan.' valign="top">'.&mt($item->{'header'}->[4]->{'col1'}).'</td>
                 <td class="LC_right_item" valign="top">'.&mt($item->{'header'}->[4]->{'col2'}).'</td>
                </tr>'.
               &print_validation_rows('requestcourses',$dom,$settings,\$rowtotal);
           } elsif ($action eq 'requestauthor') {
               $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);
             $rowtotal ++;              $rowtotal ++;
         } elsif ($action eq 'coursedefaults') {  
             $output .= &print_coursedefaults('bottom',$dom,$settings,\$rowtotal);  
         } elsif ($action eq 'rolecolors') {          } elsif ($action eq 'rolecolors') {
             $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'              $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'
            </table>             </table>
Line 672  sub print_config_box { Line 1016  sub print_config_box {
            <td>             <td>
             <table class="LC_nested">              <table class="LC_nested">
              <tr class="LC_info_row">';               <tr class="LC_info_row">';
         if (($action eq 'login') || ($action eq 'directorysrch')) {          if ($action eq 'login') {
             $output .= '                $output .= '  
               <td class="LC_left_item" colspan="2">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';                <td class="LC_left_item" colspan="2">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
         } elsif ($action eq 'serverstatuses') {          } elsif ($action eq 'serverstatuses') {
Line 716  sub print_config_box { Line 1060  sub print_config_box {
         $rowtotal ++;          $rowtotal ++;
         if ($action eq 'quotas') {          if ($action eq 'quotas') {
             $output .= &print_quotas($dom,$settings,\$rowtotal,$action);              $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
         } elsif ($action eq 'autoenroll') {          } elsif (($action eq 'autoenroll') || ($action eq 'autocreate') || 
             $output .= &print_autoenroll($dom,$settings,\$rowtotal);                   ($action eq 'serverstatuses') || ($action eq 'loadbalancing') || 
         } elsif ($action eq 'autocreate') {                   ($action eq 'ltitools')) {
             $output .= &print_autocreate($dom,$settings,\$rowtotal);              $output .= $item->{'print'}->($dom,$settings,\$rowtotal);
         } elsif ($action eq 'directorysrch') {  
             $output .= &print_directorysrch($dom,$settings,\$rowtotal);  
         } elsif ($action eq 'contacts') {  
             $output .= &print_contacts($dom,$settings,\$rowtotal);  
         } elsif ($action eq 'defaults') {  
             $output .= &print_defaults($dom,\$rowtotal);  
         } elsif ($action eq 'scantron') {          } elsif ($action eq 'scantron') {
             $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);              $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);
         } elsif ($action eq 'serverstatuses') {  
             $output .= &print_serverstatuses($dom,$settings,\$rowtotal);  
         } elsif ($action eq 'helpsettings') {  
             $output .= &print_helpsettings($dom,$confname,$settings,\$rowtotal);  
         } elsif ($action eq 'loadbalancing') {  
             $output .= &print_loadbalancing($dom,$settings,\$rowtotal);  
         }          }
     }      }
     $output .= '      $output .= '
Line 776  sub print_login { Line 1108  sub print_login {
                           '<td><select name="'.$lonhost.'_server">'.                            '<td><select name="'.$lonhost.'_server">'.
                           '<option value=""'.$direct.'>'.$choices{'directlogin'}.                            '<option value=""'.$direct.'>'.$choices{'directlogin'}.
                           '</option>';                            '</option>';
             foreach my $hostid (keys(%servers)) {              foreach my $hostid (sort(keys(%servers))) {
                 next if ($servers{$hostid} eq $servers{$lonhost});                  next if ($servers{$hostid} eq $servers{$lonhost});
                 my $selected = '';                  my $selected = '';
                 if (ref($disallowed{$lonhost}) eq 'HASH') {                  if (ref($disallowed{$lonhost}) eq 'HASH') {
Line 819  sub print_login { Line 1151  sub print_login {
     } elsif ($caller eq 'page') {      } elsif ($caller eq 'page') {
         my %defaultchecked = (           my %defaultchecked = ( 
                                'coursecatalog' => 'on',                                 'coursecatalog' => 'on',
                                  'helpdesk'      => 'on',
                                'adminmail'     => 'off',                                 'adminmail'     => 'off',
                                'newuser'       => 'off',                                 'newuser'       => 'off',
                              );                               );
         my @toggles = ('coursecatalog','adminmail','newuser');          my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');
         my (%checkedon,%checkedoff);          my (%checkedon,%checkedoff);
         foreach my $item (@toggles) {          foreach my $item (@toggles) {
             if ($defaultchecked{$item} eq 'on') {               if ($defaultchecked{$item} eq 'on') { 
Line 1029  sub print_login { Line 1362  sub print_login {
             $itemcount ++;              $itemcount ++;
         }          }
         $datatable .= &captcha_choice('login',$settings,$itemcount);          $datatable .= &captcha_choice('login',$settings,$itemcount);
       } elsif ($caller eq 'headtag') {
           my %domservers = &Apache::lonnet::get_servers($dom);
           my $choice = $choices{'headtag'};
           $css_class = ' class="LC_odd_row"';
           $datatable .= '<tr'.$css_class.'><td colspan="2">'.$choice.'</td>'.
                         '<td align="left"><table><tr><th>'.$choices{'hostid'}.'</th>'.
                         '<th>'.$choices{'current'}.'</th>'.
                         '<th>'.$choices{'action'}.'</th>'.
                         '<th>'.$choices{'exempt'}.'</th></tr>'."\n";
           my (%currurls,%currexempt);
           if (ref($settings) eq 'HASH') {
               if (ref($settings->{'headtag'}) eq 'HASH') {
                   foreach my $lonhost (keys(%{$settings->{'headtag'}})) {
                       if (ref($settings->{'headtag'}{$lonhost}) eq 'HASH') {
                           $currurls{$lonhost} = $settings->{'headtag'}{$lonhost}{'url'};
                           $currexempt{$lonhost} = $settings->{'headtag'}{$lonhost}{'exempt'};
                       }
                   }
               }
           }
           my %lt = &Apache::lonlocal::texthash(
                                                  del  => 'Delete?',
                                                  rep  => 'Replace:',
                                                  upl  => 'Upload:',
                                                  curr => 'View contents',
                                                  none => 'None',
           );
           my $switchserver = &check_switchserver($dom,$confname);
           foreach my $lonhost (sort(keys(%domservers))) {
               my $exempt = &check_exempt_addresses($currexempt{$lonhost});
               $datatable .= '<tr><td>'.$domservers{$lonhost}.'</td>';
               if ($currurls{$lonhost}) {
                   $datatable .= '<td class="LC_right_item"><a href="'.
                                 "javascript:void(open('$currurls{$lonhost}?inhibitmenu=yes','Custom_HeadTag',
                                 'menubar=0,toolbar=1,scrollbars=1,width=600,height=500,resizable=yes'))".
                                 '">'.$lt{'curr'}.'</a></td>'.
                                 '<td><span class="LC_nobreak"><label>'.
                                 '<input type="checkbox" name="loginheadtag_del" value="'.$lonhost.'" />'.
                                 $lt{'del'}.'</label>&nbsp;'.$lt{'rep'}.'</span>';
               } else {
                   $datatable .= '<td class="LC_right_item">'.$lt{'none'}.'</td><td>'.$lt{'upl'};
               }
               $datatable .='<br />';
               if ($switchserver) {
                   $datatable .= &mt('Upload to library server: [_1]',$switchserver);
               } else {
                   $datatable .= '<input type="file" name="loginheadtag_'.$lonhost.'" />';
               }
               $datatable .= '</td><td><input type="textbox" name="loginheadtagexempt_'.$lonhost.'" value="'.$exempt.'" /></td></tr>';
           }
           $datatable .= '</table></td></tr>';
     }      }
     return $datatable;      return $datatable;
 }  }
Line 1038  sub login_choices { Line 1422  sub login_choices {
         &Apache::lonlocal::texthash (          &Apache::lonlocal::texthash (
             coursecatalog => 'Display Course/Community Catalog link?',              coursecatalog => 'Display Course/Community Catalog link?',
             adminmail     => "Display Administrator's E-mail Address?",              adminmail     => "Display Administrator's E-mail Address?",
               helpdesk      => 'Display "Contact Helpdesk" link',
             disallowlogin => "Login page requests redirected",              disallowlogin => "Login page requests redirected",
             hostid        => "Server",              hostid        => "Server",
             server        => "Redirect to:",              server        => "Redirect to:",
Line 1061  sub login_choices { Line 1446  sub login_choices {
             link          => "Link",              link          => "Link",
             alink         => "Active link",              alink         => "Active link",
             vlink         => "Visited link",              vlink         => "Visited link",
               headtag       => "Custom markup",
               action        => "Action",
               current       => "Current",
         );          );
     return %choices;      return %choices;
 }  }
Line 1075  sub print_rolecolors { Line 1463  sub print_rolecolors {
     my %designhash = &Apache::loncommon::get_domainconf($dom);      my %designhash = &Apache::loncommon::get_domainconf($dom);
     my %defaultdesign = %Apache::loncommon::defaultdesign;      my %defaultdesign = %Apache::loncommon::defaultdesign;
     my (%is_custom,%designs);      my (%is_custom,%designs);
     my %defaults = (      my %defaults = &role_defaults($role,\@bgs,\@links,\@images);
                    img => $defaultdesign{$role.'.img'},  
                    font => $defaultdesign{$role.'.font'},  
    fontmenu => $defaultdesign{$role.'.fontmenu'},  
                    );  
     foreach my $item (@bgs) {  
         $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item};  
     }  
     foreach my $item (@links) {  
         $defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item};  
     }  
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{$role}) eq 'HASH') {          if (ref($settings->{$role}) eq 'HASH') {
             if ($settings->{$role}->{'img'} ne '') {              if ($settings->{$role}->{'img'} ne '') {
Line 1146  sub print_rolecolors { Line 1524  sub print_rolecolors {
     return $datatable;      return $datatable;
 }  }
   
   sub role_defaults {
       my ($role,$bgs,$links,$images,$logintext) = @_;
       my %defaults;
       unless ((ref($bgs) eq 'ARRAY') && (ref($links) eq 'ARRAY') && (ref($images) eq 'ARRAY')) {
           return %defaults;
       }
       my %defaultdesign = %Apache::loncommon::defaultdesign;
       if ($role eq 'login') {
           %defaults = (
                          font => $defaultdesign{$role.'.font'},
                       );
           if (ref($logintext) eq 'ARRAY') {
               foreach my $item (@{$logintext}) {
                   $defaults{'logintext'}{$item} = $defaultdesign{$role.'.'.$item};
               }
           }
           foreach my $item (@{$images}) {
               $defaults{'showlogo'}{$item} = 1;
           }
       } else {
           %defaults = (
                          img => $defaultdesign{$role.'.img'},
                          font => $defaultdesign{$role.'.font'},
                          fontmenu => $defaultdesign{$role.'.fontmenu'},
                       );
       }
       foreach my $item (@{$bgs}) {
           $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item};
       }
       foreach my $item (@{$links}) {
           $defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item};
       }
       foreach my $item (@{$images}) {
           $defaults{$item} = $defaultdesign{$role.'.'.$item};
       }
       return %defaults;
   }
   
 sub display_color_options {  sub display_color_options {
     my ($dom,$confname,$phase,$role,$itemcount,$choices,$is_custom,$defaults,$designs,      my ($dom,$confname,$phase,$role,$itemcount,$choices,$is_custom,$defaults,$designs,
         $images,$bgs,$links,$alt_text,$rowtotal,$logintext) = @_;          $images,$bgs,$links,$alt_text,$rowtotal,$logintext) = @_;
Line 1158  sub display_color_options { Line 1574  sub display_color_options {
     } else {      } else {
         $datatable .= '<td>&nbsp;</td>';          $datatable .= '<td>&nbsp;</td>';
     }      }
     my $fontlink = &color_pick($phase,$role,'font',$choices->{'font'},$designs->{'font'});      my $current_color = $designs->{'font'} ? $designs->{'font'} : $defaults->{'font'};
   
     $datatable .= '<td><span class="LC_nobreak">'.      $datatable .= '<td><span class="LC_nobreak">'.
                   '<input type="text" size="10" name="'.$role.'_font"'.                    '<input type="text" class="colorchooser" size="10" name="'.$role.'_font"'.
                   ' value="'.$designs->{'font'}.'" />&nbsp;'.$fontlink.                    ' value="'.$current_color.'" />&nbsp;'.
                   '&nbsp;<span id="css_'.$role.'_font" style="background-color: '.                    '&nbsp;</td></tr>';
                   $designs->{'font'}.';">&nbsp;&nbsp;&nbsp;</span>'.  
                   '</span></td></tr>';  
     unless ($role eq 'login') {       unless ($role eq 'login') { 
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                       '<td>'.$choices->{'fontmenu'}.'</td>';                        '<td>'.$choices->{'fontmenu'}.'</td>';
Line 1173  sub display_color_options { Line 1588  sub display_color_options {
         } else {          } else {
             $datatable .= '<td>&nbsp;</td>';              $datatable .= '<td>&nbsp;</td>';
         }          }
         $fontlink = &color_pick($phase,$role,'fontmenu',$choices->{'fontmenu'},$designs->{'fontmenu'});   $current_color = $designs->{'fontmenu'} ?
       $designs->{'fontmenu'} : $defaults->{'fontmenu'};
         $datatable .= '<td><span class="LC_nobreak">'.          $datatable .= '<td><span class="LC_nobreak">'.
                       '<input type="text" size="10" name="'.$role.'_fontmenu"'.                        '<input class="colorchooser" type="text" size="10" name="'
                       ' value="'.$designs->{'fontmenu'}.'" />&nbsp;'.$fontlink.        .$role.'_fontmenu"'.
                       '&nbsp;<span id="css_'.$role.'_fontmenu" style="background-color: '.                        ' value="'.$current_color.'" />&nbsp;'.
                       $designs->{'fontmenu'}.';">&nbsp;&nbsp;&nbsp;</span>'.                        '&nbsp;</td></tr>';
                       '</span></td></tr>';  
     }      }
     my $switchserver = &check_switchserver($dom,$confname);      my $switchserver = &check_switchserver($dom,$confname);
     foreach my $img (@{$images}) {      foreach my $img (@{$images}) {
Line 1194  sub display_color_options { Line 1609  sub display_color_options {
                     &login_header_options($img,$role,$defaults,$is_custom,$choices);                      &login_header_options($img,$role,$defaults,$is_custom,$choices);
                 $logincolors =                  $logincolors =
                     &login_text_colors($img,$role,$logintext,$phase,$choices,                      &login_text_colors($img,$role,$logintext,$phase,$choices,
                                             $designs);                                         $designs,$defaults);
             } elsif ($img ne 'domlogo') {              } elsif ($img ne 'domlogo') {
                 $datatable.= &logo_display_options($img,$defaults,$designs);                  $datatable.= &logo_display_options($img,$defaults,$designs);
             }              }
Line 1273  sub display_color_options { Line 1688  sub display_color_options {
                 $datatable .= &image_changes($is_custom->{$img},$alt_text->{$img},$img_import,                  $datatable .= &image_changes($is_custom->{$img},$alt_text->{$img},$img_import,
                                              $showfile,$fullsize,$role,$img,$imgfile,$logincolors);                                               $showfile,$fullsize,$role,$img,$imgfile,$logincolors);
             } else {              } else {
                 $datatable .= '<td colspan="2" class="LC_right_item"><br />'.                  $datatable .= '<td>&nbsp;</td><td class="LC_left_item">'.
                               &mt('Upload:');                                &mt('Upload:').'<br />';
             }              }
         } else {          } else {
             $datatable .= '<td colspan="2" class="LC_right_item"><br />'.              $datatable .= '<td>&nbsp;</td><td class="LC_left_item">'.
                           &mt('Upload:');                            &mt('Upload:').'<br />';
         }          }
         if ($switchserver) {          if ($switchserver) {
             $datatable .= &mt('Upload to library server: [_1]',$switchserver);              $datatable .= &mt('Upload to library server: [_1]',$switchserver);
Line 1306  sub display_color_options { Line 1721  sub display_color_options {
     }      }
     $datatable .= '<td class="LC_right_item">'.      $datatable .= '<td class="LC_right_item">'.
                   '<table border="0"><tr>';                    '<table border="0"><tr>';
   
     foreach my $item (@{$bgs}) {      foreach my $item (@{$bgs}) {
         my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'bgs'}{$item});          $datatable .= '<td align="center">'.$choices->{$item};
         $datatable .= '<td align="center">'.$link;   my $color = $designs->{'bgs'}{$item} ? $designs->{'bgs'}{$item} : $defaults->{'bgs'}{$item};
         if ($designs->{'bgs'}{$item}) {          if ($designs->{'bgs'}{$item}) {
             $datatable .= '&nbsp;<span id="css_'.$role.'_'.$item.'" style="background-color: '.$designs->{'bgs'}{$item}.';">&nbsp;&nbsp;&nbsp;</span>';              $datatable .= '&nbsp;';
         }          }
         $datatable .= '<br /><input type="text" size="8" name="'.$role.'_'.$item.'" value="'.$designs->{'bgs'}{$item}.          $datatable .= '<br /><input type="text" class="colorchooser" size="8" name="'.$role.'_'.$item.'" value="'.$color.
                       '" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>';                        '" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>';
     }      }
     $datatable .= '</tr></table></td></tr>';      $datatable .= '</tr></table></td></tr>';
Line 1334  sub display_color_options { Line 1750  sub display_color_options {
     $datatable .= '<td class="LC_right_item">'.      $datatable .= '<td class="LC_right_item">'.
                   '<table border="0"><tr>';                    '<table border="0"><tr>';
     foreach my $item (@{$links}) {      foreach my $item (@{$links}) {
         $datatable .= '<td align="center">'."\n".   my $color = $designs->{'links'}{$item} ? $designs->{'links'}{$item} : $defaults->{'links'}{$item};
                       &color_pick($phase,$role,$item,$choices->{$item},          $datatable .= '<td align="center">'.$choices->{$item}."\n";
                                   $designs->{'links'}{$item});  
         if ($designs->{'links'}{$item}) {          if ($designs->{'links'}{$item}) {
             $datatable.='&nbsp;<span id="css_'.$role.'_'.$item.'" style="background-color: '.$designs->{'links'}{$item}.';">&nbsp;&nbsp;&nbsp;</span>';              $datatable.='&nbsp;';
         }          }
         $datatable .= '<br /><input type="text" size="8" name="'.$role.'_'.$item.'" value="'.$designs->{'links'}{$item}.          $datatable .= '<br /><input type="text" size="8" class="colorchooser" name="'.$role.'_'.$item.'" value="'.$color.
                       '" /></td>';                        '" /></td>';
     }      }
     $$rowtotal += $itemcount;      $$rowtotal += $itemcount;
Line 1394  sub login_header_options  { Line 1809  sub login_header_options  {
 }  }
   
 sub login_text_colors {  sub login_text_colors {
     my ($img,$role,$logintext,$phase,$choices,$designs) = @_;      my ($img,$role,$logintext,$phase,$choices,$designs,$defaults) = @_;
     my $color_menu = '<table border="0"><tr>';      my $color_menu = '<table border="0"><tr>';
     foreach my $item (@{$logintext}) {      foreach my $item (@{$logintext}) {
         my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'logintext'}{$item});          $color_menu .= '<td align="center">'.$choices->{$item};
         $color_menu .= '<td align="center">'.$link;          my $color = $designs->{'logintext'}{$item} ? $designs->{'logintext'}{$item} : $defaults->{'logintext'}{$item};
         if ($designs->{'logintext'}{$item}) {          $color_menu .= '<br /><input type="text" class="colorchooser" size="8" name="'.$role.'_'.$item.'" value="'.$color.
             $color_menu .= '&nbsp;<span id="css_'.$role.'_'.$item.'" style="background-color: '.$designs->{'logintext'}{$item}.';">&nbsp;&nbsp;&nbsp;</span>';                        '" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>';
         }  
         $color_menu .= '<br /><input type="text" size="8" name="'.$role.'_'.$item.'" value="'.  
                        $designs->{'logintext'}{$item}.'" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>'.  
                        '<td>&nbsp;</td>';  
     }      }
     $color_menu .= '</tr></table><br />';      $color_menu .= '</tr></table><br />';
     return $color_menu;      return $color_menu;
Line 1436  sub image_changes { Line 1847  sub image_changes {
                        $role.'_del_'.$img.'" value="1" />'.&mt('Delete?').                         $role.'_del_'.$img.'" value="1" />'.&mt('Delete?').
                        '</label>&nbsp;'.&mt('Replace:').'</span><br />';                         '</label>&nbsp;'.&mt('Replace:').'</span><br />';
         } else {          } else {
             $output .= '<td valign="bottom">'.$logincolors.&mt('Upload:').'<br />';              $output .= '<td valign="middle">'.$logincolors.&mt('Upload:').'<br />';
         }          }
     }      }
     return $output;      return $output;
 }  }
   
 sub color_pick {  
     my ($phase,$role,$item,$desc,$curcol) = @_;  
     my $link = '<a href="javascript:pjump('."'color_custom','".$desc.  
                "','".$curcol."','".$role.'_'.$item."','parmform.pres','psub'".  
                ');">'.$desc.'</a>';  
     return $link;  
 }  
   
 sub print_quotas {  sub print_quotas {
     my ($dom,$settings,$rowtotal,$action) = @_;      my ($dom,$settings,$rowtotal,$action) = @_;
     my $context;      my $context;
Line 1458  sub print_quotas { Line 1861  sub print_quotas {
     } else {      } else {
         $context = $action;          $context = $action;
     }      }
     my ($datatable,$defaultquota,@usertools,@options,%validations);      my ($datatable,$defaultquota,$authorquota,@usertools,@options,%validations);
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);      my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
     my $typecount = 0;      my $typecount = 0;
     my ($css_class,%titles);      my ($css_class,%titles);
     if ($context eq 'requestcourses') {      if ($context eq 'requestcourses') {
         @usertools = ('official','unofficial','community');          @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 1477  sub print_quotas { Line 1880  sub print_quotas {
     }      }
     if (ref($types) eq 'ARRAY') {      if (ref($types) eq 'ARRAY') {
         foreach my $type (@{$types}) {          foreach my $type (@{$types}) {
             my $currdefquota;              my ($currdefquota,$currauthorquota);
             unless (($context eq 'requestcourses') ||              unless (($context eq 'requestcourses') ||
                     ($context eq 'requestauthor')) {                      ($context eq 'requestauthor')) {
                 if (ref($settings) eq 'HASH') {                  if (ref($settings) eq 'HASH') {
                     if (ref($settings->{defaultquota}) eq 'HASH') {                      if (ref($settings->{defaultquota}) eq 'HASH') {
                         $currdefquota = $settings->{defaultquota}->{$type};                           $currdefquota = $settings->{defaultquota}->{$type};
                     } else {                      } else {
                         $currdefquota = $settings->{$type};                          $currdefquota = $settings->{$type};
                     }                      }
                       if (ref($settings->{authorquota}) eq 'HASH') {
                           $currauthorquota = $settings->{authorquota}->{$type};
                       }
                 }                  }
             }              }
             if (defined($usertypes->{$type})) {              if (defined($usertypes->{$type})) {
Line 1599  sub print_quotas { Line 2005  sub print_quotas {
                 unless (($context eq 'requestcourses') ||                  unless (($context eq 'requestcourses') ||
                         ($context eq 'requestauthor')) {                          ($context eq 'requestauthor')) {
                     $datatable .=                       $datatable .= 
                               '<td class="LC_right_item"><span class="LC_nobreak">'.                                '<td class="LC_right_item">'.
                                 '<span class="LC_nobreak">'.&mt('Portfolio').':&nbsp;'.
                               '<input type="text" name="quota_'.$type.                                '<input type="text" name="quota_'.$type.
                               '" value="'.$currdefquota.                                '" value="'.$currdefquota.
                               '" size="5" /> Mb</span></td>';                                '" size="5" /></span>'.('&nbsp;' x 2).
                                 '<span class="LC_nobreak">'.&mt('Authoring').':&nbsp;'.
                                 '<input type="text" name="authorquota_'.$type.
                                 '" value="'.$currauthorquota.
                                 '" size="5" /></span></td>';
                 }                  }
                 $datatable .= '</tr>';                  $datatable .= '</tr>';
             }              }
Line 1610  sub print_quotas { Line 2021  sub print_quotas {
     }      }
     unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {      unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
         $defaultquota = '20';          $defaultquota = '20';
           $authorquota = '500';
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if (ref($settings->{'defaultquota'}) eq 'HASH') {              if (ref($settings->{'defaultquota'}) eq 'HASH') {
                 $defaultquota = $settings->{'defaultquota'}->{'default'};                  $defaultquota = $settings->{'defaultquota'}->{'default'};
             } elsif (defined($settings->{'default'})) {              } elsif (defined($settings->{'default'})) {
                 $defaultquota = $settings->{'default'};                  $defaultquota = $settings->{'default'};
             }              }
               if (ref($settings->{'authorquota'}) eq 'HASH') {
                   $authorquota = $settings->{'authorquota'}->{'default'};
               }
         }          }
     }      }
     $typecount ++;      $typecount ++;
Line 1681  sub print_quotas { Line 2096  sub print_quotas {
         } elsif ($context eq 'requestauthor') {          } elsif ($context eq 'requestauthor') {
             my $curroption;              my $curroption;
             if (ref($settings) eq 'HASH') {              if (ref($settings) eq 'HASH') {
                 if (ref($settings->{'requestauthor'}) eq 'HASH') {                  $curroption = $settings->{'default'};
                     $curroption = $settings->{'requestauthor'};  
                 }  
             }              }
             if (!$curroption) {              if (!$curroption) {
                 $curroption = 'norequest';                  $curroption = 'norequest';
Line 1728  sub print_quotas { Line 2141  sub print_quotas {
     }      }
     $datatable .= '</td>';      $datatable .= '</td>';
     unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {      unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
         $datatable .= '<td class="LC_right_item"><span class="LC_nobreak">'.          $datatable .= '<td class="LC_right_item">'.
                         '<span class="LC_nobreak">'.&mt('Portfolio').':&nbsp;'.
                       '<input type="text" name="defaultquota" value="'.                        '<input type="text" name="defaultquota" value="'.
                       $defaultquota.'" size="5" /> Mb</span></td>';                        $defaultquota.'" size="5" /></span>'.('&nbsp;' x2).
                         '<span class="LC_nobreak">'.&mt('Authoring').':&nbsp;'.
                         '<input type="text" name="authorquota" value="'.
                         $authorquota.'" size="5" /></span></td>';
     }      }
     $datatable .= '</tr>';      $datatable .= '</tr>';
     $typecount ++;      $typecount ++;
     $css_class = $typecount%2?' class="LC_odd_row"':'';      $css_class = $typecount%2?' class="LC_odd_row"':'';
     $datatable .= '<tr'.$css_class.'>'.      $datatable .= '<tr'.$css_class.'>'.
                   '<td>'.&mt('LON-CAPA Advanced Users').' ';                    '<td>'.&mt('LON-CAPA Advanced Users').'<br />';
     if ($context eq 'requestcourses') {      if ($context eq 'requestcourses') {
         $datatable .= &mt('(overrides affiliation, if set)').          $datatable .= &mt('(overrides affiliation, if set)').
                       '</td>'.                        '</td>'.
Line 1828  sub print_quotas { Line 2245  sub print_quotas {
                     $checked = ' checked="checked"';                      $checked = ' checked="checked"';
                 }                  }
                 $datatable .= '<span class="LC_nobreak"><label>'.                  $datatable .= '<span class="LC_nobreak"><label>'.
                               '<input type="radio" name="crsreq_'.$item.                                '<input type="radio" name="authorreq__LC_adv"'.
                               '__LC_adv" value="'.$val.'"'.$checked.' />'.                                ' value="'.$val.'"'.$checked.' />'.
                               $titles{$option}.'</label></span>&nbsp; ';                                $titles{$option}.'</label></span>&nbsp; ';
             }              }
         } else {          } else {
Line 1863  sub print_quotas { Line 2280  sub print_quotas {
   
 sub print_requestmail {  sub print_requestmail {
     my ($dom,$action,$settings,$rowtotal) = @_;      my ($dom,$action,$settings,$rowtotal) = @_;
     my ($now,$datatable,%dompersonnel,@domcoord,@currapproval,$rows);      my ($now,$datatable,%currapp);
     $now = time;      $now = time;
     $rows = 0;  
     %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc'],$now,$now);  
     foreach my $server (keys(%dompersonnel)) {  
         foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {  
             my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user);  
             if (!grep(/^$uname:$udom$/,@domcoord)) {  
                 push(@domcoord,$uname.':'.$udom);  
             }  
         }  
     }  
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{'notify'}) eq 'HASH') {          if (ref($settings->{'notify'}) eq 'HASH') {
             if ($settings->{'notify'}{'approval'} ne '') {              if ($settings->{'notify'}{'approval'} ne '') {
                @currapproval = split(',',$settings->{'notify'}{'approval'});                  map {$currapp{$_}=1;} split(/,/,$settings->{'notify'}{'approval'});
             }              }
         }          }
     }      }
     if (@currapproval) {      my $numinrow = 2;
         foreach my $dc (@currapproval) {      my $css_class;
             unless (grep(/^\Q$dc\E$/,@domcoord)) {      $css_class = ($$rowtotal%2? ' class="LC_odd_row"':'');
                 push(@domcoord,$dc);  
             }  
         }  
     }  
     @domcoord = sort(@domcoord);  
     my $numinrow = 4;  
     my $numdc = @domcoord;  
     my $css_class = 'class="LC_odd_row"';  
     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');
       } elsif ($action eq 'requestauthor') {
           $text = &mt('Receive notification of Authoring Space requests requiring approval');
     } else {      } else {
         $text = &mt('Receive notification of authoring space requests requiring approval')         $text = &mt('Receive notification of queued requests for self-created user accounts requiring approval');
     }      }
     $datatable = '<tr '.$css_class.'>'.      $datatable = '<tr'.$css_class.'>'.
                  ' <td>'.$text.'</td>'.                   ' <td>'.$text.'</td>'.
                  ' <td class="LC_left_item">';                   ' <td class="LC_left_item">';
     if (@domcoord > 0) {      my ($numdc,$table,$rows) = &active_dc_picker($dom,$numinrow,'checkbox',
         $datatable .= '<table>';                                                   $action.'notifyapproval',%currapp);
         for (my $i=0; $i<$numdc; $i++) {      if ($numdc > 0) {
             my $rem = $i%($numinrow);          $datatable .= $table;
             if ($rem == 0) {      } else {
                 if ($i > 0) {          $datatable .= &mt('There are no active Domain Coordinators');
                     $datatable .= '</tr>';      }
       $datatable .='</td></tr>';
       return $datatable;
   }
   
   sub print_studentcode {
       my ($settings,$rowtotal) = @_;
       my $rownum = 0; 
       my ($output,%current);
       my @crstypes = ('official','unofficial','community','textbook','placement');
       if (ref($settings) eq 'HASH') {
           if (ref($settings->{'uniquecode'}) eq 'HASH') {
               foreach my $type (@crstypes) {
                   $current{$type} = $settings->{'uniquecode'}{$type};
               }
           }
       }
       $output .= '<tr>'.
                  '<td class="LC_left_item">'.&mt('Generate unique six character code as course identifier?').'</td>'.
                  '<td class="LC_left_item">';
       foreach my $type (@crstypes) {
           my $check = ' ';
           if ($current{$type}) {
               $check = ' checked="checked" ';
           }
           $output .= '<span class="LC_nobreak"><label>'.
                      '<input type="checkbox" name="uniquecode" value="'.$type.'"'.$check.'/>'.
                      &mt($type).'</label></span>'.('&nbsp;'x2).' ';
       }
       $output .= '</td></tr>';
       $$rowtotal ++;
       return $output;
   }
   
   sub print_textbookcourses {
       my ($dom,$type,$settings,$rowtotal) = @_;
       my $rownum = 0;
       my $css_class;
       my $itemcount = 1;
       my $maxnum = 0;
       my $bookshash;
       if (ref($settings) eq 'HASH') {
           $bookshash = $settings->{$type};
       }
       my %ordered;
       if (ref($bookshash) eq 'HASH') {
           foreach my $item (keys(%{$bookshash})) {
               if (ref($bookshash->{$item}) eq 'HASH') {
                   my $num = $bookshash->{$item}{'order'};
                   $ordered{$num} = $item;
               }
           }
       }
       my $confname = $dom.'-domainconfig';
       my $switchserver = &check_switchserver($dom,$confname);
       my $maxnum = scalar(keys(%ordered));
       my $datatable;
       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 $key = $ordered{$items[$i]};
               my %coursehash=&Apache::lonnet::coursedescription($key);
               my $coursetitle = $coursehash{'description'};
               my ($subject,$title,$author,$publisher,$image,$imgsrc,$cdom,$cnum);
               if (ref($bookshash->{$key}) eq 'HASH') {
                   $subject = $bookshash->{$key}->{'subject'};
                   $title = $bookshash->{$key}->{'title'};
                   if ($type eq 'textbooks') {
                       $publisher = $bookshash->{$key}->{'publisher'};
                       $author = $bookshash->{$key}->{'author'};
                       $image = $bookshash->{$key}->{'image'};
                       if ($image ne '') {
                           my ($path,$imagefile) = ($image =~ m{^(.+)/([^/]+)$});
                           my $imagethumb = "$path/tn-".$imagefile;
                           $imgsrc = '<img src="'.$imagethumb.'" alt="'.&mt('Textbook image').'" />';
                       }
                 }                  }
                 $datatable .= '<tr>';  
                 $rows ++;  
             }              }
             my $check = ' ';              my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$type".'_'."$key','$type'".');"';
             if (grep(/^\Q$domcoord[$i]\E$/,@currapproval)) {              $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
                 $check = ' checked="checked" ';                           .'<select name="'.$type.'_'.$key.'"'.$chgstr.'>';
             }              for (my $k=0; $k<=$maxnum; $k++) {
             my ($uname,$udom) = split(':',$domcoord[$i]);                  my $vpos = $k+1;
             my $fullname = &Apache::loncommon::plainname($uname,$udom);                  my $selstr;
             if ($i == $numdc-1) {                  if ($k == $i) {
                 my $colsleft = $numinrow-$rem;                      $selstr = ' selected="selected" ';
                 if ($colsleft > 1) {                  }
                     $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">';                  $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                 } else {              }
                     $datatable .= '<td class="LC_left_item">';              $datatable .= '</select>'.('&nbsp;'x2).
                   '<label><input type="checkbox" name="'.$type.'_del" value="'.$key.'" />'.
                   &mt('Delete?').'</label></span></td>'.
                   '<td colspan="2">'.
                   '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_subject_'.$i.'" value="'.$subject.'" /></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="'.$type.'_title_'.$i.'" value="'.$title.'" /></span> ';
               if ($type eq 'textbooks') {
                   $datatable .= ('&nbsp;'x2).
                                 '<span class="LC_nobreak">'.&mt('Publisher:').'<input type="text" size="10" name="'.$type.'_publisher_'.$i.'" value="'.$publisher.'" /></span> '.
                                 ('&nbsp;'x2).
                                 '<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="'.$type.'_author_'.$i.'" value="'.$author.'" /></span> '.
                                 ('&nbsp;'x2).
                                 '<span class="LC_nobreak">'.&mt('Thumbnail:');
                   if ($image) {
                       $datatable .= $imgsrc.
                                     '<label><input type="checkbox" name="'.$type.'_image_del"'.
                                     ' value="'.$key.'" />'.&mt('Delete?').'</label></span> '.
                                     '<span class="LC_nobreak">&nbsp;'.&mt('Replace:').'&nbsp;';
                   }
                   if ($switchserver) {
                       $datatable .= &mt('Upload to library server: [_1]',$switchserver);
                   } else {
                       $datatable .= '<input type="file" name="'.$type.'_image_'.$i.'" value="" />';
                   }
               }
               $datatable .= '<input type="hidden" name="'.$type.'_id_'.$i.'" value="'.$type.'_'.$key.'" /></span> '.
                             '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.
                             $coursetitle.'</span></td></tr>'."\n";
               $itemcount ++;
           }
       }
       $css_class = $itemcount%2?' class="LC_odd_row"':'';
       my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$type"."_addbook_pos','$type'".');"';
       $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
                     '<input type="hidden" name="'.$type.'_maxnum" value="'.$maxnum.'" />'."\n".
                     '<select name="'.$type.'_addbook_pos"'.$chgstr.'>';
       for (my $k=0; $k<$maxnum+1; $k++) {
           my $vpos = $k+1;
           my $selstr;
           if ($k == $maxnum) {
               $selstr = ' selected="selected" ';
           }
           $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
       }
       $datatable .= '</select>&nbsp;'."\n".
                     '<input type="checkbox" name="'.$type.'_addbook" value="1" />'.&mt('Add').'</td>'."\n".
                     '<td colspan="2">'.
                     '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_addbook_subject" value="" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="'.$type.'_addbook_title" value="" /></span> '."\n".
                     ('&nbsp;'x2);
       if ($type eq 'textbooks') {
           $datatable .= '<span class="LC_nobreak">'.&mt('Publisher:').'<input type="text" size="10" name="'.$type.'_addbook_publisher" value="" /></span> '."\n".
                         ('&nbsp;'x2).
                         '<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="'.$type.'_addbook_author" value="" /></span> '."\n".
                         ('&nbsp;'x2).
                         '<span class="LC_nobreak">'.&mt('Image:').'&nbsp;';
           if ($switchserver) {
               $datatable .= &mt('Upload to library server: [_1]',$switchserver);
           } else {
               $datatable .= '<input type="file" name="'.$type.'_addbook_image" value="" />';
           }
       }
       $datatable .= '</span>'."\n".
                     '<span class="LC_nobreak">'.&mt('LON-CAPA course:').'&nbsp;'.
                     &Apache::loncommon::select_dom_form($env{'request.role.domain'},$type.'_addbook_cdom').
                     '<input type="text" size="25" name="'.$type.'_addbook_cnum" value="" />'.
                     &Apache::loncommon::selectcourse_link
                         ('display',$type.'_addbook_cnum',$type.'_addbook_cdom',undef,undef,undef,'Course');
                     '</span></td>'."\n".
                     '</tr>'."\n";
       $itemcount ++;
       return $datatable;
   }
   
   sub textbookcourses_javascript {
       my ($settings) = @_;
       return unless(ref($settings) eq 'HASH');
       my (%ordered,%total,%jstext);
       foreach my $type ('textbooks','templates') {
           $total{$type} = 0;
           if (ref($settings->{$type}) eq 'HASH') {
               foreach my $item (keys(%{$settings->{$type}})) {
                   if (ref($settings->{$type}->{$item}) eq 'HASH') {
                       my $num = $settings->{$type}->{$item}{'order'};
                       $ordered{$type}{$num} = $item;
                   }
               }
               $total{$type} = scalar(keys(%{$settings->{$type}}));
           }
           my @jsarray = ();
           foreach my $item (sort {$a <=> $b } (keys(%{$ordered{$type}}))) {
               push(@jsarray,$ordered{$type}{$item});
           }
           $jstext{$type} = '    var '.$type.' = Array('."'".join("','",@jsarray)."'".');'."\n";
       }
       return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   function reorderBooks(form,item,caller) {
       var changedVal;
   $jstext{'textbooks'};
   $jstext{'templates'};
       var newpos;
       var maxh;
       if (caller == 'textbooks') {  
           newpos = 'textbooks_addbook_pos';
           maxh = 1 + $total{'textbooks'};
       } else {
           newpos = 'templates_addbook_pos';
           maxh = 1 + $total{'templates'};
       }
       var current = new Array;
       var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
       if (item == newpos) {
           changedVal = newitemVal;
       } else {
           changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
           current[newitemVal] = newpos;
       }
       if (caller == 'textbooks') {
           for (var i=0; i<textbooks.length; i++) {
               var elementName = 'textbooks_'+textbooks[i];
               if (elementName != item) {
                   if (form.elements[elementName]) {
                       var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
                       current[currVal] = elementName;
                 }                  }
             } else {  
                 $datatable .= '<td class="LC_left_item">';  
             }              }
             $datatable .= '<span class="LC_nobreak"><label>'.  
                           '<input type="checkbox" name="reqapprovalnotify" '.  
                           'value="'.$domcoord[$i].'"'.$check.'/>'.  
                           $fullname.'</label></span></td>';  
         }          }
         $datatable .= '</tr></table>';      }
       if (caller == 'templates') {
           for (var i=0; i<templates.length; i++) {
               var elementName = 'templates_'+templates[i];
               if (elementName != item) {
                   if (form.elements[elementName]) {
                       var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
                       current[currVal] = elementName;
                   }
               }
           }
       }
       var oldVal;
       for (var j=0; j<maxh; j++) {
           if (current[j] == undefined) {
               oldVal = j;
           }
       }
       if (oldVal < changedVal) {
           for (var k=oldVal+1; k<=changedVal ; k++) {
              var elementName = current[k];
              form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
           }
     } else {      } else {
         $datatable .= &mt('There are no active Domain Coordinators');          for (var k=changedVal; k<oldVal; k++) {
         $rows ++;              var elementName = current[k];
               form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
           }
     }      }
     $datatable .='</td></tr>';      return;
     $$rowtotal += $rows;  }
     return $datatable;  
   // ]]>
   </script>
   
   ENDSCRIPT
   }
   
   sub ltitools_javascript {
       my ($settings) = @_;
       return unless(ref($settings) eq 'HASH');
       my (%ordered,$total,%jstext);
       $total = 0;
       foreach my $item (keys(%{$settings})) {
           if (ref($settings->{$item}) eq 'HASH') {
               my $num = $settings->{$item}{'order'};
               $ordered{$num} = $item;
           }
       }
       $total = scalar(keys(%{$settings}));
       my @jsarray = ();
       foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
           push(@jsarray,$ordered{$item});
       }
       my $jstext = '    var ltitools = Array('."'".join("','",@jsarray)."'".');'."\n";
       return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   function reorderLTI(form,item) {
       var changedVal;
   $jstext
       var newpos = 'ltitools_add_pos';
       var maxh = 1 + $total;
       var current = new Array;
       var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
       if (item == newpos) {
           changedVal = newitemVal;
       } else {
           changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
           current[newitemVal] = newpos;
       }
       for (var i=0; i<ltitools.length; i++) {
           var elementName = 'ltitools_'+ltitools[i];
           if (elementName != item) {
               if (form.elements[elementName]) {
                   var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
                   current[currVal] = elementName;
               }
           }
       }
       var oldVal;
       for (var j=0; j<maxh; j++) {
           if (current[j] == undefined) {
               oldVal = j;
           }
       }
       if (oldVal < changedVal) {
           for (var k=oldVal+1; k<=changedVal ; k++) {
              var elementName = current[k];
              form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
           }
       } else {
           for (var k=changedVal; k<oldVal; k++) {
               var elementName = current[k];
               form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   ENDSCRIPT
 }  }
   
 sub print_autoenroll {  sub print_autoenroll {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my $autorun = &Apache::lonnet::auto_run(undef,$dom),      my $autorun = &Apache::lonnet::auto_run(undef,$dom),
     my ($defdom,$runon,$runoff,$coownerson,$coownersoff);      my ($defdom,$runon,$runoff,$coownerson,$coownersoff,$failsafe);
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (exists($settings->{'run'})) {          if (exists($settings->{'run'})) {
             if ($settings->{'run'} eq '0') {              if ($settings->{'run'} eq '0') {
Line 1981  sub print_autoenroll { Line 2673  sub print_autoenroll {
         if (exists($settings->{'sender_domain'})) {          if (exists($settings->{'sender_domain'})) {
             $defdom = $settings->{'sender_domain'};              $defdom = $settings->{'sender_domain'};
         }          }
           if (exists($settings->{'autofailsafe'})) {
               $failsafe = $settings->{'autofailsafe'};
           }
     } else {      } else {
         if ($autorun) {          if ($autorun) {
             $runon = ' checked="checked" ';              $runon = ' checked="checked" ';
Line 2016  sub print_autoenroll { Line 2711  sub print_autoenroll {
                   $coownerson.' value="1" />'.&mt('Yes').'</label>&nbsp;'.                    $coownerson.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                   '<label><input type="radio" name="autoassign_coowners"'.                    '<label><input type="radio" name="autoassign_coowners"'.
                   $coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.                    $coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.
                   '</tr>';                    '</tr><tr>'.
     $$rowtotal += 3;                    '<td>'.&mt('Failsafe for no drops when institutional data missing').'</td>'.
                     '<td class="LC_right_item"><span class="LC_nobreak">'.
                     '<input type="text" name="autoenroll_failsafe"'.
                     ' value="'.$failsafe.'" size="4" /></td></tr>';
       $$rowtotal += 4;
     return $datatable;      return $datatable;
 }  }
   
Line 2092  sub print_autoupdate { Line 2791  sub print_autoupdate {
   
 sub print_autocreate {  sub print_autocreate {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$settings,$rowtotal) = @_;
     my (%createon,%createoff);      my (%createon,%createoff,%currhash);
     my $curr_dc;  
     my @types = ('xml','req');      my @types = ('xml','req');
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         foreach my $item (@types) {          foreach my $item (@types) {
Line 2106  sub print_autocreate { Line 2804  sub print_autocreate {
                 }                  }
             }              }
         }          }
         $curr_dc = $settings->{'xmldc'};          if ($settings->{'xmldc'} ne '') {
               $currhash{$settings->{'xmldc'}} = 1;
           }
     } else {      } else {
         foreach my $item (@types) {          foreach my $item (@types) {
             $createoff{$item} = ' checked="checked" ';              $createoff{$item} = ' checked="checked" ';
Line 2114  sub print_autocreate { Line 2814  sub print_autocreate {
         }          }
     }      }
     $$rowtotal += 2;      $$rowtotal += 2;
       my $numinrow = 2;
     my $datatable='<tr class="LC_odd_row">'.      my $datatable='<tr class="LC_odd_row">'.
                   '<td>'.&mt('Create pending official courses from XML files').'</td>'.                    '<td>'.&mt('Create pending official courses from XML files').'</td>'.
                   '<td class="LC_right_item"><span class="LC_nobreak"><label>'.                    '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
Line 2128  sub print_autocreate { Line 2829  sub print_autocreate {
                   $createon{'req'}.' value="1" />'.&mt('Yes').'</label>&nbsp;'.                    $createon{'req'}.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                   '<label><input type="radio" name="autocreate_req"'.                    '<label><input type="radio" name="autocreate_req"'.
                   $createoff{'req'}.' value="0" />'.&mt('No').'</label></span>';                    $createoff{'req'}.' value="0" />'.&mt('No').'</label></span>';
     my ($numdc,$dctable) = &active_dc_picker($dom,$curr_dc);      my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',
                                                      'autocreate_xmldc',%currhash);
       $datatable .= '</td></tr><tr class="LC_odd_row"><td>';
     if ($numdc > 1) {      if ($numdc > 1) {
         $datatable .= '</td></tr><tr class="LC_odd_row"><td>'.          $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)').
                       &mt('Course creation processed as: (choose Dom. Coord.)').                        '</td><td class="LC_left_item">';
                       '</td><td class="LC_left_item">'.$dctable.'</td></tr>';  
         $$rowtotal ++ ;  
     } else {      } else {
         $datatable .= $dctable.'</td></tr>';          $datatable .= &mt('Course creation processed as:').
                         '</td><td class="LC_right_item">';
     }      }
       $datatable .= $dctable.'</td></tr>';
       $$rowtotal += $rows;
     return $datatable;      return $datatable;
 }  }
   
 sub print_directorysrch {  sub print_directorysrch {
     my ($dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my $srchon = ' ';      my $datatable;
     my $srchoff = ' checked="checked" ';      if ($position eq 'top') {
     my ($exacton,$containson,$beginson);          my $instsrchon = ' ';
     my $localon = ' ';          my $instsrchoff = ' checked="checked" ';
     my $localoff = ' checked="checked" ';          my ($exacton,$containson,$beginson);
     if (ref($settings) eq 'HASH') {          my $instlocalon = ' ';
         if ($settings->{'available'} eq '1') {          my $instlocaloff = ' checked="checked" ';
             $srchon = $srchoff;          if (ref($settings) eq 'HASH') {
             $srchoff = ' ';              if ($settings->{'available'} eq '1') {
         }                  $instsrchon = $instsrchoff;
         if ($settings->{'localonly'} eq '1') {                  $instsrchoff = ' ';
             $localon = $localoff;              }
             $localoff = ' ';              if ($settings->{'localonly'} eq '1') {
         }                  $instlocalon = $instlocaloff;
         if (ref($settings->{'searchtypes'}) eq 'ARRAY') {                  $instlocaloff = ' ';
             foreach my $type (@{$settings->{'searchtypes'}}) {              }
                 if ($type eq 'exact') {              if (ref($settings->{'searchtypes'}) eq 'ARRAY') {
                   foreach my $type (@{$settings->{'searchtypes'}}) {
                       if ($type eq 'exact') {
                           $exacton = ' checked="checked" ';
                       } elsif ($type eq 'contains') {
                           $containson = ' checked="checked" ';
                       } elsif ($type eq 'begins') {
                           $beginson = ' checked="checked" ';
                       }
                   }
               } else {
                   if ($settings->{'searchtypes'} eq 'exact') {
                       $exacton = ' checked="checked" ';
                   } elsif ($settings->{'searchtypes'} eq 'contains') {
                       $containson = ' checked="checked" ';
                   } elsif ($settings->{'searchtypes'} eq 'specify') {
                     $exacton = ' checked="checked" ';                      $exacton = ' checked="checked" ';
                 } elsif ($type eq 'contains') {  
                     $containson = ' checked="checked" ';                      $containson = ' checked="checked" ';
                 } elsif ($type eq 'begins') {  
                     $beginson = ' checked="checked" ';  
                 }                  }
             }              }
         } else {  
             if ($settings->{'searchtypes'} eq 'exact') {  
                 $exacton = ' checked="checked" ';  
             } elsif ($settings->{'searchtypes'} eq 'contains') {  
                 $containson = ' checked="checked" ';  
             } elsif ($settings->{'searchtypes'} eq 'specify') {  
                 $exacton = ' checked="checked" ';  
                 $containson = ' checked="checked" ';  
             }  
         }          }
     }          my ($searchtitles,$titleorder) = &sorted_searchtitles();
     my ($searchtitles,$titleorder) = &sorted_searchtitles();          my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
   
     my $numinrow = 4;          my $numinrow = 4;
     my $cansrchrow = 0;          my $cansrchrow = 0;
     my $datatable='<tr class="LC_odd_row">'.          $datatable='<tr class="LC_odd_row">'.
                   '<td colspan="2"><span class ="LC_nobreak">'.&mt('Directory search available?').'</span></td>'.                     '<td colspan="2"><span class ="LC_nobreak">'.&mt('Institutional directory search available?').'</span></td>'.
                   '<td class="LC_right_item"><span class="LC_nobreak"><label>'.                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                   '<input type="radio" name="dirsrch_available"'.                     '<input type="radio" name="dirsrch_available"'.
                   $srchon.' value="1" />'.&mt('Yes').'</label>&nbsp;'.                     $instsrchon.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                   '<label><input type="radio" name="dirsrch_available"'.                     '<label><input type="radio" name="dirsrch_available"'.
                   $srchoff.' value="0" />'.&mt('No').'</label></span></td>'.                     $instsrchoff.' value="0" />'.&mt('No').'</label></span></td>'.
                   '</tr><tr>'.                     '</tr><tr>'.
                   '<td colspan="2"><span class ="LC_nobreak">'.&mt('Other domains can search?').'</span></td>'.                     '<td colspan="2"><span class ="LC_nobreak">'.&mt('Other domains can search institution?').'</span></td>'.
                   '<td class="LC_right_item"><span class="LC_nobreak"><label>'.                     '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                   '<input type="radio" name="dirsrch_localonly"'.                     '<input type="radio" name="dirsrch_instlocalonly"'.
                   $localoff.' value="0" />'.&mt('Yes').'</label>&nbsp;'.                     $instlocaloff.' value="0" />'.&mt('Yes').'</label>&nbsp;'.
                   '<label><input type="radio" name="dirsrch_localonly"'.                     '<label><input type="radio" name="dirsrch_instlocalonly"'.
                   $localon.' value="1" />'.&mt('No').'</label></span></td>'.                     $instlocalon.' value="1" />'.&mt('No').'</label></span></td>'.
                   '</tr>';                     '</tr>';
     $$rowtotal += 2;          $$rowtotal += 2;
     if (ref($usertypes) eq 'HASH') {          if (ref($usertypes) eq 'HASH') {
         if (keys(%{$usertypes}) > 0) {              if (keys(%{$usertypes}) > 0) {
             $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,                  $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,
                                          $numinrow,$othertitle,'cansearch');                                               $numinrow,$othertitle,'cansearch');
             $cansrchrow = 1;                  $cansrchrow = 1;
               }
         }          }
     }          if ($cansrchrow) {
     if ($cansrchrow) {              $$rowtotal ++;
         $$rowtotal ++;              $datatable .= '<tr>';
         $datatable .= '<tr>';          } else {
     } else {              $datatable .= '<tr class="LC_odd_row">';
         $datatable .= '<tr class="LC_odd_row">';          }
     }          $datatable .= '<td><span class ="LC_nobreak">'.&mt('Supported search methods').
     $datatable .= '<td><span class ="LC_nobreak">'.&mt('Supported search methods').                        '</span></td><td class="LC_left_item" colspan="2"><table><tr>';
                   '</span></td><td class="LC_left_item" colspan="2"><table><tr>';          foreach my $title (@{$titleorder}) {
     foreach my $title (@{$titleorder}) {              if (defined($searchtitles->{$title})) {
         if (defined($searchtitles->{$title})) {                  my $check = ' ';
             my $check = ' ';                  if (ref($settings) eq 'HASH') {
             if (ref($settings) eq 'HASH') {                      if (ref($settings->{'searchby'}) eq 'ARRAY') {
                 if (ref($settings->{'searchby'}) eq 'ARRAY') {                          if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) {
                     if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) {                              $check = ' checked="checked" ';
                         $check = ' checked="checked" ';                          }
                     }                      }
                 }                  }
                   $datatable .= '<td class="LC_left_item">'.
                                 '<span class="LC_nobreak"><label>'.
                                 '<input type="checkbox" name="searchby" '.
                                 'value="'.$title.'"'.$check.'/>'.
                                 $searchtitles->{$title}.'</label></span></td>';
             }              }
             $datatable .= '<td class="LC_left_item">'.  
                           '<span class="LC_nobreak"><label>'.  
                           '<input type="checkbox" name="searchby" '.  
                           'value="'.$title.'"'.$check.'/>'.  
                           $searchtitles->{$title}.'</label></span></td>';  
         }          }
     }          $datatable .= '</tr></table></td></tr>';
     $datatable .= '</tr></table></td></tr>';          $$rowtotal ++;
     $$rowtotal ++;          if ($cansrchrow) {
     if ($cansrchrow) {              $datatable .= '<tr class="LC_odd_row">';
         $datatable .= '<tr class="LC_odd_row">';          } else {
               $datatable .= '<tr>';
           }
           $datatable .= '<td><span class ="LC_nobreak">'.&mt('Search latitude').'</span></td>'.   
                         '<td class="LC_left_item" colspan="2">'.
                         '<span class="LC_nobreak"><label>'.
                         '<input type="checkbox" name="searchtypes" '.
                         $exacton.' value="exact" />'.&mt('Exact match').
                         '</label>&nbsp;'.
                         '<label><input type="checkbox" name="searchtypes" '.
                         $beginson.' value="begins" />'.&mt('Begins with').
                         '</label>&nbsp;'.
                         '<label><input type="checkbox" name="searchtypes" '.
                         $containson.' value="contains" />'.&mt('Contains').
                         '</label></span></td></tr>';
           $$rowtotal ++;
     } else {      } else {
         $datatable .= '<tr>';          my $domsrchon = ' checked="checked" ';
           my $domsrchoff = ' ';
           my $domlocalon = ' ';
           my $domlocaloff = ' checked="checked" ';
           if (ref($settings) eq 'HASH') {
               if ($settings->{'lclocalonly'} eq '1') {
                   $domlocalon = $domlocaloff;
                   $domlocaloff = ' ';
               }
               if ($settings->{'lcavailable'} eq '0') {
                   $domsrchoff = $domsrchon;
                   $domsrchon = ' ';
               }
           }
           $datatable='<tr class="LC_odd_row">'.
                         '<td colspan="2"><span class ="LC_nobreak">'.&mt('LON-CAPA directory search available?').'</span></td>'.
                         '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                         '<input type="radio" name="dirsrch_domavailable"'.
                         $domsrchon.' value="1" />'.&mt('Yes').'</label>&nbsp;'.
                         '<label><input type="radio" name="dirsrch_domavailable"'.
                         $domsrchoff.' value="0" />'.&mt('No').'</label></span></td>'.
                         '</tr><tr>'.
                         '<td colspan="2"><span class ="LC_nobreak">'.&mt('Other domains can search LON-CAPA domain?').'</span></td>'.
                         '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
                         '<input type="radio" name="dirsrch_domlocalonly"'.
                         $domlocaloff.' value="0" />'.&mt('Yes').'</label>&nbsp;'.
                         '<label><input type="radio" name="dirsrch_domlocalonly"'.
                         $domlocalon.' value="1" />'.&mt('No').'</label></span></td>'.
                         '</tr>';
           $$rowtotal += 2;
     }      }
     $datatable .= '<td><span class ="LC_nobreak">'.&mt('Search latitude').'</span></td>'.     
                   '<td class="LC_left_item" colspan="2">'.  
                   '<span class="LC_nobreak"><label>'.  
                   '<input type="checkbox" name="searchtypes" '.  
                   $exacton.' value="exact" />'.&mt('Exact match').  
                   '</label>&nbsp;'.  
                   '<label><input type="checkbox" name="searchtypes" '.  
                   $beginson.' value="begins" />'.&mt('Begins with').  
                   '</label>&nbsp;'.  
                   '<label><input type="checkbox" name="searchtypes" '.  
                   $containson.' value="contains" />'.&mt('Contains').  
                   '</label></span></td></tr>';  
     $$rowtotal ++;  
     return $datatable;      return $datatable;
 }  }
   
 sub print_contacts {  sub print_contacts {
     my ($dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my $datatable;      my $datatable;
     my @contacts = ('adminemail','supportemail');      my @contacts = ('adminemail','supportemail');
     my (%checked,%to,%otheremails,%bccemails);      my (%checked,%to,%otheremails,%bccemails,%includestr,%includeloc,%currfield,
     my @mailings = ('errormail','packagesmail','lonstatusmail','helpdeskmail',          $maxsize,$fields,$fieldtitles,$fieldoptions,$possoptions,@mailings);
                     'requestsmail');      if ($position eq 'top') {
     foreach my $type (@mailings) {          if (ref($settings) eq 'HASH') {
         $otheremails{$type} = '';              foreach my $item (@contacts) {
     }                  if (exists($settings->{$item})) {
     $bccemails{'helpdeskmail'} = '';                      $to{$item} = $settings->{$item};
     if (ref($settings) eq 'HASH') {                  }
         foreach my $item (@contacts) {  
             if (exists($settings->{$item})) {  
                 $to{$item} = $settings->{$item};  
             }              }
         }          }
       } elsif ($position eq 'middle') {
           @mailings = ('errormail','packagesmail','lonstatusmail','requestsmail',
                        'updatesmail','idconflictsmail');
         foreach my $type (@mailings) {          foreach my $type (@mailings) {
             if (exists($settings->{$type})) {              $otheremails{$type} = '';
                 if (ref($settings->{$type}) eq 'HASH') {          }
                     foreach my $item (@contacts) {      } else {
                         if ($settings->{$type}{$item}) {          @mailings = ('helpdeskmail','otherdomsmail');
                             $checked{$type}{$item} = ' checked="checked" ';          foreach my $type (@mailings) {
               $otheremails{$type} = '';
           }
           $bccemails{'helpdeskmail'} = '';
           $bccemails{'otherdomsmail'} = '';
           $includestr{'helpdeskmail'} = '';
           $includestr{'otherdomsmail'} = '';
           ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();
       }
       if (ref($settings) eq 'HASH') {
           unless ($position eq 'top') {
               foreach my $type (@mailings) {
                   if (exists($settings->{$type})) {
                       if (ref($settings->{$type}) eq 'HASH') {
                           foreach my $item (@contacts) {
                               if ($settings->{$type}{$item}) {
                                   $checked{$type}{$item} = ' checked="checked" ';
                               }
                           }
                           $otheremails{$type} = $settings->{$type}{'others'};
                           if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                               $bccemails{$type} = $settings->{$type}{'bcc'};
                               if ($settings->{$type}{'include'} ne '') {
                                   ($includeloc{$type},$includestr{$type}) = split(/:/,$settings->{$type}{'include'},2);
                                   $includestr{$type} = &unescape($includestr{$type});
                               }
                         }                          }
                     }                      }
                     $otheremails{$type} = $settings->{$type}{'others'};                  } elsif ($type eq 'lonstatusmail') {
                     if ($type eq 'helpdeskmail') {                      $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';
                         $bccemails{$type} = $settings->{$type}{'bcc'};                  }
               }
           }
           if ($position eq 'bottom') {
               foreach my $type (@mailings) {
                   $bccemails{$type} = $settings->{$type}{'bcc'};
                   if ($settings->{$type}{'include'} ne '') {
                       ($includeloc{$type},$includestr{$type}) = split(/:/,$settings->{$type}{'include'},2);
                       $includestr{$type} = &unescape($includestr{$type});
                   }
               }
               if (ref($settings->{'helpform'}) eq 'HASH') {
                   if (ref($fields) eq 'ARRAY') {
                       foreach my $field (@{$fields}) {
                           $currfield{$field} = $settings->{'helpform'}{$field};
                     }                      }
                 }                  }
             } elsif ($type eq 'lonstatusmail') {                  if (exists($settings->{'helpform'}{'maxsize'})) {
                 $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';                      $maxsize = $settings->{'helpform'}{'maxsize'};
                   } else {
                       $maxsize = '1.0';
                   }
               } else {
                   if (ref($fields) eq 'ARRAY') {
                       foreach my $field (@{$fields}) {
                           $currfield{$field} = 'yes';
                       }
                   }
                   $maxsize = '1.0';
             }              }
         }          }
     } else {      } else {
         $to{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};          if ($position eq 'top') {
         $to{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'};              $to{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};
         $checked{'errormail'}{'adminemail'} = ' checked="checked" ';              $to{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'};
         $checked{'packagesmail'}{'adminemail'} = ' checked="checked" ';              $checked{'errormail'}{'adminemail'} = ' checked="checked" ';
         $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';              $checked{'packagesmail'}{'adminemail'} = ' checked="checked" ';
         $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';               $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';
         $checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';              $checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';
               $checked{'updatesmail'}{'adminemail'} = ' checked="checked" ';
               $checked{'idconflictsmail'}{'adminemail'} = ' checked="checked" ';
           } elsif ($position eq 'bottom') {
               $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';
               $checked{'otherdomsmail'}{'supportemail'} = ' checked="checked" ';
               if (ref($fields) eq 'ARRAY') {
                   foreach my $field (@{$fields}) {
                       $currfield{$field} = 'yes';
                   }
               }
               $maxsize = '1.0';
           }
     }      }
     my ($titles,$short_titles) = &contact_titles();      my ($titles,$short_titles) = &contact_titles();
     my $rownum = 0;      my $rownum = 0;
     my $css_class;      my $css_class;
     foreach my $item (@contacts) {      if ($position eq 'top') {
         $rownum ++;          foreach my $item (@contacts) {
         $css_class = $rownum%2?' class="LC_odd_row"':'';              $css_class = $rownum%2?' class="LC_odd_row"':'';
         $datatable .= '<tr'.$css_class.'>'.               $datatable .= '<tr'.$css_class.'>'. 
                   '<td><span class="LC_nobreak">'.$titles->{$item}.                            '<td><span class="LC_nobreak">'.$titles->{$item}.
                   '</span></td><td class="LC_right_item">'.                            '</span></td><td class="LC_right_item">'.
                   '<input type="text" name="'.$item.'" value="'.                            '<input type="text" name="'.$item.'" value="'.
                   $to{$item}.'" /></td></tr>';                            $to{$item}.'" /></td></tr>';
               $rownum ++;
           }
       } else {
           foreach my $type (@mailings) {
               $css_class = $rownum%2?' class="LC_odd_row"':'';
               $datatable .= '<tr'.$css_class.'>'.
                             '<td><span class="LC_nobreak">'.
                             $titles->{$type}.': </span></td>'.
                             '<td class="LC_left_item">';
               if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                   $datatable .= '<fieldset><legend>'.&mt('E-mail recipient(s)').'</legend>';
               }
               $datatable .= '<span class="LC_nobreak">';
               foreach my $item (@contacts) {
                   $datatable .= '<label>'.
                                 '<input type="checkbox" name="'.$type.'"'.
                                 $checked{$type}{$item}.
                                 ' value="'.$item.'" />'.$short_titles->{$item}.
                                 '</label>&nbsp;';
               }
               $datatable .= '</span><br />'.&mt('Others').':&nbsp;&nbsp;'.
                             '<input type="text" name="'.$type.'_others" '.
                             'value="'.$otheremails{$type}.'"  />';
               my %locchecked;
               if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                   foreach my $loc ('s','b') {
                       if ($includeloc{$type} eq $loc) {
                           $locchecked{$loc} = ' checked="checked"';
                           last;
                       }
                   }
                   $datatable .= '<br />'.&mt('Bcc:').('&nbsp;'x6).
                                 '<input type="text" name="'.$type.'_bcc" '.
                                 'value="'.$bccemails{$type}.'"  /></fieldset>'.
                                 '<fieldset><legend>'.&mt('Optional added text').'</legend>'.
                                 &mt('Text automatically added to e-mail:').' '.
                                 '<input type="text" name="'.$type.'_includestr" value="'.$includestr{$type}.'" /><br >'.
                                 '<span class="LC_nobreak">'.&mt('Location:').'&nbsp;'.
                                 '<label><input type="radio" name="'.$type.'_includeloc" value="s"'.$locchecked{'s'}.' />'.&mt('in subject').'</label>'.
                                 ('&nbsp;'x2).
                                 '<label><input type="radio" name="'.$type.'_includeloc" value="b"'.$locchecked{'b'}.' />'.&mt('in body').'</label>'.
                                 '</span></fieldset>';
               }
               $datatable .= '</td></tr>'."\n";
               $rownum ++;
           }
     }      }
     foreach my $type (@mailings) {      if ($position eq 'middle') {
         $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;
       } elsif ($position eq 'bottom') {
         $css_class = $rownum%2?' class="LC_odd_row"':'';          $css_class = $rownum%2?' class="LC_odd_row"':'';
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                       '<td><span class="LC_nobreak">'.                        '<td>'.&mt('Extra helpdesk form fields:').'<br />'.
                       $titles->{$type}.': </span></td>'.                        &mt('(e-mail, subject, and description always shown)').
                       '<td class="LC_left_item">'.                        '</td><td class="LC_left_item">';
                       '<span class="LC_nobreak">';          if ((ref($fields) eq 'ARRAY') && (ref($fieldtitles) eq 'HASH') &&
         foreach my $item (@contacts) {              (ref($fieldoptions) eq 'HASH') && (ref($possoptions) eq 'HASH')) {
             $datatable .= '<label>'.              $datatable .= '<table><tr><th>'.&mt('Field').'</th><th>'.&mt('Status').'</th></tr>';
                           '<input type="checkbox" name="'.$type.'"'.              foreach my $field (@{$fields}) {
                           $checked{$type}{$item}.                  $datatable .= '<tr><td>'.$fieldtitles->{$field};
                           ' value="'.$item.'" />'.$short_titles->{$item}.                  if (($field eq 'screenshot') || ($field eq 'cc')) {
                           '</label>&nbsp;';                      $datatable .= ' '.&mt('(logged-in users)');
         }                  }
         $datatable .= '</span><br />'.&mt('Others').':&nbsp;&nbsp;'.                  $datatable .='</td><td>';
                       '<input type="text" name="'.$type.'_others" '.                  my $clickaction;
                       'value="'.$otheremails{$type}.'"  />';                  if ($field eq 'screenshot') {
         if ($type eq 'helpdeskmail') {                      $clickaction = ' onclick="screenshotSize(this);"';
             $datatable .= '<br />'.&mt('Bcc:').('&nbsp;'x6).                  }
                           '<input type="text" name="'.$type.'_bcc" '.                  if (ref($possoptions->{$field}) eq 'ARRAY') {
                           'value="'.$bccemails{$type}.'"  />';                      foreach my $option (@{$possoptions->{$field}}) {
                           my $checked;
                           if ($currfield{$field} eq $option) {
                               $checked = ' checked="checked"';
                           }
                           $datatable .= '<span class="LC_nobreak"><label>'.
                                         '<input type="radio" name="helpform_'.$field.'" '.
                                         'value="'.$option.'"'.$checked.$clickaction.' />'.$fieldoptions->{$option}.
                                         '</label></span>'.('&nbsp;'x2);
                       }
                   }
                   if ($field eq 'screenshot') {
                       my $display;
                       if ($currfield{$field} eq 'no') {
                           $display = ' style="display:none"';
                       }
                       $datatable .= '</td></tr><tr id="help_screenshotsize"'.$display.' />'.
                                     '<td>'.&mt('Maximum size for upload (MB)').'</td><td>'.
                                     '<input type="text" size="5" name="helpform_maxsize" value="'.$maxsize.'" />';
                   }
                   $datatable .= '</td></tr>';
               }
               $datatable .= '</table>';
         }          }
         $datatable .= '</td></tr>'."\n";          $datatable .= '</td></tr>'."\n";
           $rownum ++;
     }      }
     $$rowtotal += $rownum;      $$rowtotal += $rownum;
     return $datatable;      return $datatable;
 }  }
   
   sub contacts_javascript {
       return <<"ENDSCRIPT";
   
   <script type="text/javascript">
   // <![CDATA[
   
   function screenshotSize(field) {
       if (document.getElementById('help_screenshotsize')) {
           if (field.value == 'no') {
               document.getElementById('help_screenshotsize').style.display="none";
           } else {
               document.getElementById('help_screenshotsize').style.display="";
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   ENDSCRIPT
   }
   
 sub print_helpsettings {  sub print_helpsettings {
     my ($dom,$confname,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
       my $confname = $dom.'-domainconfig';
       my $formname = 'display';
     my ($datatable,$itemcount);      my ($datatable,$itemcount);
     $itemcount = 1;      if ($position eq 'top') {
     my (%choices,%defaultchecked,@toggles);          $itemcount = 1;
     $choices{'submitbugs'} = &mt('Display link to: [_1]?',          my (%choices,%defaultchecked,@toggles);
                                  &Apache::loncommon::modal_link('http://bugs.loncapa.org',          $choices{'submitbugs'} = &mt('Display link to: [_1]?',
                                  &mt('LON-CAPA bug tracker'),600,500));                                       &Apache::loncommon::modal_link('http://bugs.loncapa.org',
     %defaultchecked = ('submitbugs' => 'on');                                       &mt('LON-CAPA bug tracker'),600,500));
     @toggles = ('submitbugs',);          %defaultchecked = ('submitbugs' => 'on');
           @toggles = ('submitbugs');
     ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,          ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
                                                  \%choices,$itemcount);                                                       \%choices,$itemcount);
           $$rowtotal ++;
       } else {
           my $css_class;
           my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');
           my (%customroles,%ordered,%current);
           if (ref($settings) eq 'HASH') {
               if (ref($settings->{'adhoc'}) eq 'HASH') {
                   %current = %{$settings->{'adhoc'}};
               }
           }
           my $count = 0;
           foreach my $key (sort(keys(%existing))) {
               if ($key=~/^rolesdef\_(\w+)$/) {
                   my $rolename = $1;
                   my (%privs,$order);
                   ($privs{'system'},$privs{'domain'},$privs{'course'}) = split(/\_/,$existing{$key});
                   $customroles{$rolename} = \%privs;
                   if (ref($current{$rolename}) eq 'HASH') {
                       $order = $current{$rolename}{'order'};
                   }
                   if ($order eq '') {
                       $order = $count;
                   }
                   $ordered{$order} = $rolename;
                   $count++;
               }
           }
           my $maxnum = scalar(keys(%ordered));
           my @roles_by_num = ();
           foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
               push(@roles_by_num,$item);
           }
           my $context = 'domprefs';
           my $crstype = 'Course';
           my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
           my @accesstypes = ('all','dh','da','none');
           my ($numstatustypes,@jsarray);
           if (ref($types) eq 'ARRAY') {
               if (@{$types} > 0) {
                   $numstatustypes = scalar(@{$types});
                   push(@accesstypes,'status');
                   @jsarray = ('bystatus');
               }
           }
           my %domhelpdesk = &Apache::lonnet::get_active_domroles($dom,['dh','da']);
           if (keys(%domhelpdesk)) {
               push(@accesstypes,('inc','exc'));
               push(@jsarray,('notinc','notexc'));
           }
           my $hiddenstr = join("','",@jsarray);
           $datatable .= &helpsettings_javascript(\@roles_by_num,$maxnum,$hiddenstr,$formname);
           my $context = 'domprefs';
           my $crstype = 'Course';
           my $prefix = 'helproles_';
           my $add_class = 'LC_hidden';
           foreach my $num (@roles_by_num) {
               my $role = $ordered{$num};
               my ($desc,$access,@statuses);
               if (ref($current{$role}) eq 'HASH') {
                   $desc = $current{$role}{'desc'};
                   $access = $current{$role}{'access'};
                   if (ref($current{$role}{'insttypes'}) eq 'ARRAY') {
                       @statuses = @{$current{$role}{'insttypes'}};
                   }
               }
               if ($desc eq '') {
                   $desc = $role;
               }
               my $identifier = 'custhelp'.$num;
               my %full=();
               my %levels= (
                            course => {},
                            domain => {},
                            system => {},
                           );
               my %levelscurrent=(
                                  course => {},
                                  domain => {},
                                  system => {},
                                 );
               &Apache::lonuserutils::custom_role_privs($customroles{$role},\%full,\%levels,\%levelscurrent);
               my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
               $css_class = $itemcount%2?' class="LC_odd_row"':'';
               my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$num."_pos'".');"';
               $datatable .= '<tr '.$css_class.'><td valign="top"><b>'.$role.'</b><br />'.
                             '<select name="helproles_'.$num.'_pos"'.$chgstr.'>';
               for (my $k=0; $k<=$maxnum; $k++) {
                   my $vpos = $k+1;
                   my $selstr;
                   if ($k == $num) {
                       $selstr = ' selected="selected" ';
                   }
                   $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
               }
               $datatable .= '</select>'.('&nbsp;'x2).
                             '<input type="hidden" name="helproles_'.$num.'" value="'.$role.'" />'.
                             '</td>'.
                             '<td><fieldset><legend>'.&mt('Role name').'</legend>'.
                             &mt('Name shown to users:').
                             '<input type="text" name="helproles_'.$num.'_desc" value="'.$desc.'" />'.
                             '</fieldset>'.
                             &helpdeskroles_access($dom,$prefix,$num,$add_class,$current{$role},\@accesstypes,
                                                   $othertitle,$usertypes,$types,\%domhelpdesk).
                             '<fieldset>'.
                             '<legend>'.&mt('Role privileges').&adhocbutton($prefix,$num,'privs','show').'</legend>'.
                             &Apache::lonuserutils::custom_role_table($crstype,\%full,\%levels,
                                                                      \%levelscurrent,$identifier,
                                                                      'LC_hidden',$prefix.$num.'_privs').
                             '</fieldset></td>';
               $itemcount ++;
           }
           $css_class = $itemcount%2?' class="LC_odd_row"':'';
           my $newcust = 'custhelp'.$count;
           my (%privs,%levelscurrent);
           my %full=();
           my %levels= (
                        course => {},
                        domain => {},
                        system => {},
                       );
           &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
           my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
           my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$count."_pos'".');"';
           $datatable .= '<tr '.$css_class.'><td valign="top"><span class="LC_nobreak"><label>'.
                         '<input type="hidden" name="helproles_maxnum" value="'.$maxnum.'" />'."\n".
                         '<select name="helproles_'.$count.'_pos"'.$chgstr.'>';
           for (my $k=0; $k<$maxnum+1; $k++) {
               my $vpos = $k+1;
               my $selstr;
               if ($k == $maxnum) {
                   $selstr = ' selected="selected" ';
               }
               $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
           }
           $datatable .= '</select>&nbsp;'."\n".
                         '<input type="checkbox" name="newcusthelp" value="'.$count.'" />'. &mt('Add').
                         '</label></span></td>'.
                         '<td><fieldset><legend>'.&mt('Role name').'</legend>'.
                         '<span class="LC_nobreak">'.
                         &mt('Internal name:').
                         '<input type="text" size="10" name="custhelpname'.$count.'" value="" />'.
                         '</span>'.('&nbsp;'x4).
                         '<span class="LC_nobreak">'.
                         &mt('Name shown to users:').
                         '<input type="text" size="20" name="helproles_'.$count.'_desc" value="" />'.
                         '</span></fieldset>'.
                          &helpdeskroles_access($dom,$prefix,$count,'',undef,\@accesstypes,$othertitle,
                                                $usertypes,$types,\%domhelpdesk).
                         '<fieldset><legend>'.&mt('Role privileges').'</legend>'.
                         &Apache::lonuserutils::custom_role_header($context,$crstype,
                                                                   \@templateroles,$newcust).
                         &Apache::lonuserutils::custom_role_table('Course',\%full,\%levels,
                                                                  \%levelscurrent,$newcust).
                         '</fieldset></td></tr>';
           $count ++;
           $$rowtotal += $count;
       }
     return $datatable;      return $datatable;
 }  }
   
   sub adhocbutton {
       my ($prefix,$num,$field,$visibility) = @_;
       my %lt = &Apache::lonlocal::texthash(
                                             show => 'Show details',
                                             hide => 'Hide details',
                                           );
       return '<span style="text-decoration:line-through; font-weight: normal;">'.('&nbsp;'x10).
              '</span>'.('&nbsp;'x2).'<input type="button" id="'.$prefix.$num.'_'.$field.'_vis"'.
              ' value="'.$lt{$visibility}.'" style="height:20px;" '.
              'onclick="toggleHelpdeskItem('."'$num','$field'".');" />'.('&nbsp;'x2);
   }
   
   sub helpsettings_javascript {
       my ($roles_by_num,$total,$hiddenstr,$formname) = @_;
       return unless(ref($roles_by_num) eq 'ARRAY');
       my %html_js_lt = &Apache::lonlocal::texthash(
                                             show => 'Show details',
                                             hide => 'Hide details',
                                           );
       &html_escape(\%html_js_lt);
       my $jstext = '    var helproles = Array('."'".join("','",@{$roles_by_num})."'".');'."\n";
       return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   
   function reorderHelpRoles(form,item) {
       var changedVal;
   $jstext
       var newpos = 'helproles_${total}_pos';
       var maxh = 1 + $total;
       var current = new Array();
       var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
       if (item == newpos) {
           changedVal = newitemVal;
       } else {
           changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
           current[newitemVal] = newpos;
       }
       for (var i=0; i<helproles.length; i++) {
           var elementName = 'helproles_'+helproles[i]+'_pos';
           if (elementName != item) {
               if (form.elements[elementName]) {
                   var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
                   current[currVal] = elementName;
               }
           }
       }
       var oldVal;
       for (var j=0; j<maxh; j++) {
           if (current[j] == undefined) {
               oldVal = j;
           }
       }
       if (oldVal < changedVal) {
           for (var k=oldVal+1; k<=changedVal ; k++) {
              var elementName = current[k];
              form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
           }
       } else {
           for (var k=changedVal; k<oldVal; k++) {
               var elementName = current[k];
               form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
           }
       }
       return;
   }
   
   function helpdeskAccess(num) {
       var curraccess = null;
       if (document.$formname.elements['helproles_'+num+'_access'].length) {
           for (var i=0; i<document.$formname.elements['helproles_'+num+'_access'].length; i++) {
               if (document.$formname.elements['helproles_'+num+'_access'][i].checked) {
                   curraccess = document.$formname.elements['helproles_'+num+'_access'][i].value;
               }
           }
       }
       var shown = Array();
       var hidden = Array();
       if (curraccess == 'none') {
           hidden = Array('$hiddenstr');
       } else {
           if (curraccess == 'status') {
               shown = Array('bystatus');
               hidden = Array('notinc','notexc');
           } else {
               if (curraccess == 'exc') {
                   shown = Array('notexc');
                   hidden = Array('notinc','bystatus');
               }
               if (curraccess == 'inc') {
                   shown = Array('notinc');
                   hidden = Array('notexc','bystatus');
               }
               if ((curraccess == 'all') || (curraccess == 'dh') || (curraccess == 'da')) {
                   hidden = Array('notinc','notexc','bystatus');
               }
           }
       }
       if (hidden.length > 0) {
           for (var i=0; i<hidden.length; i++) {
               if (document.getElementById('helproles_'+num+'_'+hidden[i])) {
                   document.getElementById('helproles_'+num+'_'+hidden[i]).style.display = 'none';
               }
           }
       }
       if (shown.length > 0) {
           for (var i=0; i<shown.length; i++) {
               if (document.getElementById('helproles_'+num+'_'+shown[i])) {
                   if (shown[i] == 'privs') {
                       document.getElementById('helproles_'+num+'_'+shown[i]).style.display = 'block';
                   } else {
                       document.getElementById('helproles_'+num+'_'+shown[i]).style.display = 'inline-block';
                   }
               }
           }
       }
       return;
   }
   
   function toggleHelpdeskItem(num,field) {
       if (document.getElementById('helproles_'+num+'_'+field)) {
           if (document.getElementById('helproles_'+num+'_'+field).className.match(/(?:^|\\s)LC_hidden(?!\\S)/)) {
               document.getElementById('helproles_'+num+'_'+field).className =
                   document.getElementById('helproles_'+num+'_'+field).className.replace(/(?:^|\\s)LC_hidden(?!\\S)/g ,'');
               if (document.getElementById('helproles_'+num+'_'+field+'_vis')) {
                   document.getElementById('helproles_'+num+'_'+field+'_vis').value = '$html_js_lt{hide}';
               }
           } else {
               document.getElementById('helproles_'+num+'_'+field).className += ' LC_hidden';
               if (document.getElementById('helproles_'+num+'_'+field+'_vis')) {
                   document.getElementById('helproles_'+num+'_'+field+'_vis').value = '$html_js_lt{show}';
               }
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   ENDSCRIPT
   }
   
   sub helpdeskroles_access {
       my ($dom,$prefix,$num,$add_class,$current,$accesstypes,$othertitle,
           $usertypes,$types,$domhelpdesk) = @_;
       return unless ((ref($accesstypes) eq 'ARRAY') && (ref($domhelpdesk) eq 'HASH'));
       my %lt = &Apache::lonlocal::texthash(
                       'rou'    => 'Role usage',
                       'whi'    => 'Which helpdesk personnel may use this role?',
                       'all'    => 'All with domain helpdesk or helpdesk assistant role',
                       'dh'     => 'All with domain helpdesk role',
                       'da'     => 'All with domain helpdesk assistant role',
                       'none'   => 'None',
                       'status' => 'Determined based on institutional status',
                       'inc'    => 'Include all, but exclude specific personnel',
                       'exc'    => 'Exclude all, but include specific personnel',
                     );
       my %usecheck = (
                        all => ' checked="checked"',
                      );
       my %displaydiv = (
                         status => 'none',
                         inc    => 'none',
                         exc    => 'none',
                         priv   => 'block',
                        );
       my $output;
       if (ref($current) eq 'HASH') {
           if (($current->{'access'} ne '') && ($current->{'access'} ne 'all')) {
               if (grep(/^\Q$current->{access}\E$/,@{$accesstypes})) {
                   $usecheck{$current->{access}} = $usecheck{'all'};
                   delete($usecheck{'all'});
                   if ($current->{access} =~ /^(status|inc|exc)$/) {
                       my $access = $1;
                       $displaydiv{$access} = 'inline';
                   } elsif ($current->{access} eq 'none') {
                       $displaydiv{'priv'} = 'none';
                   }
               }
           }
       }
       $output = '<fieldset id="'.$prefix.$num.'_usage"><legend>'.$lt{'rou'}.'</legend>'.
                 '<p>'.$lt{'whi'}.'</p>';
       foreach my $access (@{$accesstypes}) {
           $output .= '<p><label><input type="radio" name="'.$prefix.$num.'_access" value="'.$access.'" '.$usecheck{$access}.
                      ' onclick="helpdeskAccess('."'$num'".');" />'.
                      $lt{$access}.'</label>';
           if ($access eq 'status') {
               $output .= '<div id="'.$prefix.$num.'_bystatus" style="display:'.$displaydiv{$access}.'">'.
                          &Apache::lonuserutils::adhoc_status_types($dom,$prefix,$num,$current->{$access},
                                                                    $othertitle,$usertypes,$types).
                          '</div>';
           } elsif (($access eq 'inc') && (keys(%{$domhelpdesk}) > 0)) {
               $output .= '<div id="'.$prefix.$num.'_notinc" style="display:'.$displaydiv{$access}.'">'.
                          &Apache::lonuserutils::adhoc_staff($access,$prefix,$num,$current->{$access},$domhelpdesk).
                          '</div>';
           } elsif (($access eq 'exc') && (keys(%{$domhelpdesk}) > 0)) {
               $output .= '<div id="'.$prefix.$num.'_notexc" style="display:'.$displaydiv{$access}.'">'.
                          &Apache::lonuserutils::adhoc_staff($access,$prefix,$num,$current->{$access},$domhelpdesk).
                          '</div>';
           }
           $output .= '</p>';
       }
       $output .= '</fieldset>';
       return $output;
   }
   
 sub radiobutton_prefs {  sub radiobutton_prefs {
     my ($settings,$toggles,$defaultchecked,$choices,$itemcount) = @_;      my ($settings,$toggles,$defaultchecked,$choices,$itemcount,$onclick,
           $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 2380  sub radiobutton_prefs { Line 3652  sub radiobutton_prefs {
             }              }
         }          }
     }      }
       if ($onclick) {
           $onclick = ' onclick="'.$onclick.'"';
       }
     foreach my $item (@{$toggles}) {      foreach my $item (@{$toggles}) {
         $css_class = $itemcount%2?' class="LC_odd_row"':'';          $css_class = $itemcount%2?' class="LC_odd_row"':'';
         $datatable .=          $datatable .=
             '<tr'.$css_class.'><td><span class="LC_nobreak">'.$choices->{$item}.              '<tr'.$css_class.'><td valign="top">'.
             '</span></td>'.              '<span class="LC_nobreak">'.$choices->{$item}.
             '<td class="LC_right_item"><span class="LC_nobreak">'.              '</span></td>';
           if ($align eq 'left') {
               $datatable .= '<td class="LC_left_item">';
           } else {
               $datatable .= '<td class="LC_right_item">';
           }
           $datatable .=
               '<span class="LC_nobreak">'.
             '<label><input type="radio" name="'.              '<label><input type="radio" name="'.
             $item.'" '.$checkedon{$item}.' value="1" />'.&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" />'.&mt('No').'</label>'.              $checkedoff{$item}.' value="0"'.$onclick.' />'.&mt('No').'</label>'.
             '</span></td>'.              '</span>'.$additional.
               '</td>'.
             '</tr>';              '</tr>';
         $itemcount ++;          $itemcount ++;
     }      }
     return ($datatable,$itemcount);      return ($datatable,$itemcount);
 }  }
   
   sub print_ltitools {
       my ($dom,$settings,$rowtotal) = @_;
       my $rownum = 0;
       my $css_class;
       my $itemcount = 1;
       my $maxnum = 0;
       my %ordered;
       if (ref($settings) eq 'HASH') {
           foreach my $item (keys(%{$settings})) {
               if (ref($settings->{$item}) eq 'HASH') {
                   my $num = $settings->{$item}{'order'};
                   $ordered{$num} = $item;
               }
           }
       }
       my $confname = $dom.'-domainconfig';
       my $switchserver = &check_switchserver($dom,$confname);
       my $maxnum = scalar(keys(%ordered));
       my $datatable = &ltitools_javascript($settings);
       my %lt = &ltitools_names();
       my @courseroles = ('cc','in','ta','ep','st');
       my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner);
       my @fields = ('fullname','firstname','lastname','email','user','roles');
       if (keys(%ordered)) {
           my @items = sort { $a <=> $b } keys(%ordered);
           for (my $i=0; $i<@items; $i++) {
               $css_class = $itemcount%2?' class="LC_odd_row"':'';
               my $item = $ordered{$items[$i]};
               my ($title,$key,$secret,$url,$imgsrc,$version);
               if (ref($settings->{$item}) eq 'HASH') {
                   $title = $settings->{$item}->{'title'};
                   $url = $settings->{$item}->{'url'};
                   $key = $settings->{$item}->{'key'};
                   $secret = $settings->{$item}->{'secret'};
                   my $image = $settings->{$item}->{'image'};
                   if ($image ne '') {
                       $imgsrc = '<img src="'.$image.'" alt="'.&mt('Tool Provider icon').'" />';
                   }
               }
               my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_".$item."'".');"';
               $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
                            .'<select name="ltitools_'.$item.'"'.$chgstr.'>';
               for (my $k=0; $k<=$maxnum; $k++) {
                   my $vpos = $k+1;
                   my $selstr;
                   if ($k == $i) {
                       $selstr = ' selected="selected" ';
                   }
                   $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
               }
               $datatable .= '</select>'.('&nbsp;'x2).
                   '<label><input type="checkbox" name="ltitools_del" value="'.$item.'" />'.
                   &mt('Delete?').'</label></span></td>'.
                   '<td colspan="2">'.
                   '<fieldset><legend>'.&mt('Required settings').'</legend>'.
                   '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="30" name="ltitools_title_'.$i.'" value="'.$title.'" /></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'version'}.':<select name="ltitools_version_'.$i.'">'.
                   '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'msgtype'}.':<select name="ltitools_msgtype_'.$i.'">'.
                   '<option value="basic-lti-launch-request" selected="selected">Launch</option></select></span> '.
                   '<br /><br />'.
                   '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="30" name="ltitools_url_'.$i.'"'.
                   ' value="'.$url.'" /></span>'.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'key'}.
                   '<input type="text" size="25" name="ltitools_key_'.$i.'" value="'.$key.'" /></span> '.
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'secret'}.':'.
                   '<input type="password" size="20" name="ltitools_secret_'.$i.'" value="'.$secret.'" />'.
                   '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.ltitools_secret_'.$i.'.type='."'text'".' } else { this.form.ltitools_secret_'.$i.'.type='."'password'".' }" />'.&mt('Visible input').'</label>'.
                   '<input type="hidden" name="ltitools_id_'.$i.'" value="'.$item.'" /></span>'.
                   '</fieldset>'.
                   '<fieldset><legend>'.&mt('Optional settings').'</legend>'.
                   '<span class="LC_nobreak">'.&mt('Display target:');
               my %currdisp;
               if (ref($settings->{$item}->{'display'}) eq 'HASH') {
                   if ($settings->{$item}->{'display'}->{'target'} eq 'window') {
                       $currdisp{'window'} = ' checked="checked"';
                   } elsif ($settings->{$item}->{'display'}->{'target'} eq 'tab') {
                       $currdisp{'tab'} = ' checked="checked"';
                   } else {
                       $currdisp{'iframe'} = ' checked="checked"';
                   }
                   if ($settings->{$item}->{'display'}->{'width'} =~ /^(\d+)$/) {
                       $currdisp{'width'} = $1;
                   }
                   if ($settings->{$item}->{'display'}->{'height'} =~ /^(\d+)$/) {
                        $currdisp{'height'} = $1;
                   }
                   $currdisp{'linktext'} = $settings->{$item}->{'display'}->{'linktext'};
                   $currdisp{'explanation'} = $settings->{$item}->{'display'}->{'explanation'};
               } else {
                   $currdisp{'iframe'} = ' checked="checked"';
               }
               foreach my $disp ('iframe','tab','window') {
                   $datatable .= '<label><input type="radio" name="ltitools_target_'.$i.'" value="'.$disp.'"'.$currdisp{$disp}.' />'.
                                 $lt{$disp}.'</label>'.('&nbsp;'x2);
               }
               $datatable .= ('&nbsp;'x4);
               foreach my $dimen ('width','height') {
                   $datatable .= '<label>'.$lt{$dimen}.'&nbsp;'.
                                 '<input type="text" name="ltitools_'.$dimen.'_'.$i.'" size="5" value="'.$currdisp{$dimen}.'" /></label>'.
                                 ('&nbsp;'x2);
               }
               $datatable .= '<br />'.
                             '<div class="LC_left_float">'.$lt{'linktext'}.'<br />'.
                             '<input type="text" name="ltitools_linktext_'.$i.'" size="25" value="'.$currdisp{'linktext'}.'" /></label></div>'.
                             '<div class="LC_left_float">'.$lt{'explanation'}.'<br />'.
                             '<textarea name="ltitools_explanation_'.$i.'" rows="5" cols="40">'.$currdisp{'explanation'}.
                             '</textarea></div><div style=""></div><br />';
               $datatable .= '<br />';
               foreach my $extra ('passback','roster') {
                   my $checkedon = '';
                   my $checkedoff = ' checked="checked"';
                   if ($settings->{$item}->{$extra}) {
                       $checkedon = $checkedoff;
                       $checkedoff = '';
                   }
                   $datatable .= $lt{$extra}.'&nbsp;'.
                                 '<label><input type="radio" name="ltitools_'.$extra.'_'.$i.'" value="1"'.$checkedon.' />'.
                                 &mt('Yes').'</label>'.('&nbsp;'x2).
                                 '<label><input type="radio" name="ltitools_'.$extra.'_'.$i.'" value="0"'.$checkedoff.' />'.
                                 &mt('No').'</label>'.('&nbsp;'x4);
               }
               $datatable .= '<br /><br /><span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;';
               if ($imgsrc) {
                   $datatable .= $imgsrc.
                                 '<label><input type="checkbox" name="ltitools_image_del"'.
                                 ' value="'.$item.'" />'.&mt('Delete?').'</label></span> '.
                                 '<span class="LC_nobreak">&nbsp;'.&mt('Replace:').'&nbsp;';
               } else {
                   $datatable .= '('.&mt('if larger than 21x21 pixels, image will be scaled').')&nbsp;';
               }
               if ($switchserver) {
                   $datatable .= &mt('Upload to library server: [_1]',$switchserver);
               } else {
                   $datatable .= '<input type="file" name="ltitools_image_'.$i.'" value="" />';
               }
               $datatable .= '</span></fieldset>';
               my (%checkedfields,%rolemaps);
               if (ref($settings->{$item}) eq 'HASH') {
                   if (ref($settings->{$item}->{'fields'}) eq 'HASH') {
                       %checkedfields = %{$settings->{$item}->{'fields'}};
                   }
                   if (ref($settings->{$item}->{'roles'}) eq 'HASH') {
                       %rolemaps = %{$settings->{$item}->{'roles'}};
                       $checkedfields{'roles'} = 1;
                   }
               }
               $datatable .= '<fieldset><legend>'.&mt('User data sent on launch').'</legend>'.
                             '<span class="LC_nobreak">';
               foreach my $field (@fields) {
                   my $checked;
                   if ($checkedfields{$field}) {
                       $checked = ' checked="checked"';
                   }
                   $datatable .= '<label>'.
                                 '<input type="checkbox" name="ltitools_fields_'.$i.'" value="'.$field.'"'.$checked.' />'.
                                 $lt{$field}.'</label>'.('&nbsp;' x2);
               }
               $datatable .= '</span></fieldset>'.
                             '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';
               foreach my $role (@courseroles) {
                   my ($selected,$selectnone);
                   if (!$rolemaps{$role}) {
                       $selectnone = ' selected="selected"';
                   }
                   $datatable .= '<td align="center">'. 
                                 &Apache::lonnet::plaintext($role,'Course').'<br />'.
                                 '<select name="ltitools_roles_'.$role.'_'.$i.'">'.
                                 '<option value=""'.$selectnone.'>'.&mt('Select').'</option>';
                   foreach my $ltirole (@ltiroles) {
                       unless ($selectnone) {
                           if ($rolemaps{$role} eq $ltirole) {
                               $selected = ' selected="selected"';
                           } else {
                               $selected = '';
                           }
                       }
                       $datatable .= '<option value="'.$ltirole.'"'.$selected.'>'.$ltirole.'</option>';
                   }
                   $datatable .= '</select></td>';
               }
               $datatable .= '</tr></table></fieldset>';
               my %courseconfig;
               if (ref($settings->{$item}) eq 'HASH') {
                   if (ref($settings->{$item}->{'crsconf'}) eq 'HASH') {
                       %courseconfig = %{$settings->{$item}->{'crsconf'}};
                   }
               }
               $datatable .= '<fieldset><legend>'.&mt('Configurable in course').'</legend><span class="LC_nobreak">';
               foreach my $item ('label','title','target','linktext','explanation') {
                   my $checked;
                   if ($courseconfig{$item}) {
                       $checked = ' checked="checked"';
                   }
                   $datatable .= '<label>'.
                          '<input type="checkbox" name="ltitools_courseconfig_'.$i.'" value="'.$item.'"'.$checked.' />'.
                          $lt{'crs'.$item}.'</label>'.('&nbsp;' x2)."\n";
               }
               $datatable .= '</span></fieldset>'.
                             '<fieldset><legend>'.&mt('Custom items sent on launch').'</legend>'.
                             '<table><tr><th>'.&mt('Action').'</th><th>'.&mt('Name').'</th><th>'.&mt('Value').'</th></tr>';
               if (ref($settings->{$item}->{'custom'}) eq 'HASH') {
                   my %custom = %{$settings->{$item}->{'custom'}};
                   if (keys(%custom) > 0) {
                       foreach my $key (sort(keys(%custom))) {
                           $datatable .= '<tr><td><span class="LC_nobreak">'.
                                         '<label><input type="checkbox" name="ltitools_customdel_'.$i.'" value="'.
                                         $key.'" />'.&mt('Delete').'</label></span></td><td>'.$key.'</td>'.
                                         '<td><input type="text" name="ltitools_customval_'.$key.'_'.$i.'"'.
                                         ' value="'.$custom{$key}.'" /></td></tr>';
                       }
                   }
               }
               $datatable .= '<tr><td><span class="LC_nobreak">'.
                             '<label><input type="checkbox" name="ltitools_customadd" value="'.$i.'" />'.
                             &mt('Add').'</label></span></td><td><input type="text" name="ltitools_custom_name_'.$i.'" />'.
                             '</td><td><input type="text" name="ltitools_custom_value_'.$i.'" /></td></tr>';
               $datatable .= '</table></fieldset></td></tr>'."\n";
               $itemcount ++;
           }
       }
       $css_class = $itemcount%2?' class="LC_odd_row"':'';
       my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_add_pos'".');"';
       $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
                     '<input type="hidden" name="ltitools_maxnum" value="'.$maxnum.'" />'."\n".
                     '<select name="ltitools_add_pos"'.$chgstr.'>';
       for (my $k=0; $k<$maxnum+1; $k++) {
           my $vpos = $k+1;
           my $selstr;
           if ($k == $maxnum) {
               $selstr = ' selected="selected" ';
           }
           $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
       }
       $datatable .= '</select>&nbsp;'."\n".
                     '<input type="checkbox" name="ltitools_add" value="1" />'.&mt('Add').'</td>'."\n".
                     '<td colspan="2">'.
                     '<fieldset><legend>'.&mt('Required settings').'</legend>'.
                     '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="30" name="ltitools_add_title" value="" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'version'}.':<select name="ltitools_add_version">'.
                     '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'msgtype'}.':<select name="ltitools_add_msgtype">'.
                     '<option value="basic-lti-launch-request" selected="selected">Launch</option></select></span> '.
                     '<br />'.
                     '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="30" name="ltitools_add_url" value="" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'key'}.':<input type="text" size="25" name="ltitools_add_key" value="" /></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'secret'}.':<input type="password" size="20" name="ltitools_add_secret" value="" />'.
                     '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.ltitools_add_secret.type='."'text'".' } else { this.form.ltitools_add_secret.type='."'password'".' }" />'.&mt('Visible input').'</label></span> '."\n".
                     '</fieldset>'.
                     '<fieldset><legend>'.&mt('Optional settings').'</legend>'.
                     '<span class="LC_nobreak">'.&mt('Display target:');
       my %defaultdisp;
       $defaultdisp{'iframe'} = ' checked="checked"';
       foreach my $disp ('iframe','tab','window') {
           $datatable .= '<label><input type="radio" name="ltitools_add_target" value="'.$disp.'"'.$defaultdisp{$disp}.' />'.
                         $lt{$disp}.'</label>'.('&nbsp;'x2);
       }
       $datatable .= ('&nbsp;'x4);
       foreach my $dimen ('width','height') {
           $datatable .= '<label>'.$lt{$dimen}.'&nbsp;'.
                         '<input type="text" name="ltitools_add_'.$dimen.'" size="5" /></label>'.
                         ('&nbsp;'x2);
       }
       $datatable .= '<br />'.
                     '<div class="LC_left_float">'.$lt{'linktext'}.'<br />'.
                     '<input type="text" name="ltitools_add_linktext" size="5" /></label></div>'.
                     '<div class="LC_left_float">'.$lt{'explanation'}.'<br />'.
                     '<textarea name=ltitools_add_explanation" rows="5" cols="40"></textarea>'.
                     '</div><div style=""></div><br />';
       foreach my $extra ('passback','roster') {
           $datatable .= $lt{$extra}.'&nbsp;'.
                         '<label><input type="radio" name="ltitools_add_'.$extra.'" value="1" />'.
                         &mt('Yes').'</label>'.('&nbsp;'x2).
                         '<label><input type="radio" name="ltitools_add_'.$extra.'" value="0" checked="checked" />'.
                         &mt('No').'</label>'.('&nbsp;'x4);
       }
       $datatable .= '<br /><br /><span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;'.
                     '('.&mt('if larger than 21x21 pixels, image will be scaled').')&nbsp;';
       if ($switchserver) {
           $datatable .= &mt('Upload to library server: [_1]',$switchserver);
       } else {
           $datatable .= '<input type="file" name="ltitools_add_image" value="" />';
       }
       $datatable .= '</span></fieldset>'.
                     '<fieldset><legend>'.&mt('User data sent on launch').'</legend>'.
                     '<span class="LC_nobreak">';
       foreach my $field (@fields) {
           $datatable .= '<label>'.
                         '<input type="checkbox" name="ltitools_add_fields" value="'.$field.'" />'.
                         $lt{$field}.'</label>'.('&nbsp;' x2);
       }
       $datatable .= '</span></fieldset>'.
                     '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';
       foreach my $role (@courseroles) {
           my ($checked,$checkednone);
           $datatable .= '<td align="center">'.
                         &Apache::lonnet::plaintext($role,'Course').'<br />'.
                         '<select name="ltitools_add_roles_'.$role.'">'.
                         '<option value="" selected="selected">'.&mt('Select').'</option>';
           foreach my $ltirole (@ltiroles) {
               $datatable .= '<option value="'.$ltirole.'">'.$ltirole.'</option>';
           }
           $datatable .= '</select></td>';
       }
       $datatable .= '</tr></table></fieldset>'.
                     '<fieldset><legend>'.&mt('Configurable in course').'</legend><span class="LC_nobreak">';
       foreach my $item ('label','title','target','linktext','explanation') {
           $datatable .= '<label>'.
                         '<input type="checkbox" name="ltitools_courseconfig" value="'.$item.'" checked="checked" />'.
                         $lt{'crs'.$item}.'</label>'.('&nbsp;' x2)."\n";
       }
       $datatable .= '</span></fieldset>'.
                     '<fieldset><legend>'.&mt('Custom items sent on launch').'</legend>'.
                     '<table><tr><th>'.&mt('Action').'</th><th>'.&mt('Name').'</th><th>'.&mt('Value').'</th></tr>'.
                     '<tr><td><span class="LC_nobreak">'.
                     '<label><input type="checkbox" name="ltitools_add_custom" value="1" />'.
                     &mt('Add').'</label></span></td><td><input type="text" name="ltitools_add_custom_name" />'.
                     '</td><td><input type="text" name="ltitools_add_custom_value" /></td></tr>'.
                     '</table></fieldset></td></tr>'."\n".
                     '</td>'."\n".
                     '</tr>'."\n";
       $itemcount ++;
       return $datatable;
   }
   
   sub ltitools_names {
       my %lt = &Apache::lonlocal::texthash(
                                             'title'          => 'Title',
                                             'version'        => 'Version',
                                             'msgtype'        => 'Message Type',
                                             'url'            => 'URL',
                                             'key'            => 'Key',
                                             'secret'         => 'Secret',
                                             'icon'           => 'Icon',   
                                             'user'           => 'Username:domain',
                                             'fullname'       => 'Full Name',
                                             'firstname'      => 'First Name',
                                             'lastname'       => 'Last Name',
                                             'email'          => 'E-mail',
                                             'roles'          => 'Role',
                                             'window'         => 'Window',
                                             'tab'            => 'Tab',
                                             'iframe'         => 'iFrame',
                                             'height'         => 'Height',
                                             'width'          => 'Width',
                                             'linktext'       => 'Default Link Text',
                                             'explanation'    => 'Default Explanation',
                                             'passback'       => 'Tool can return grades:',
                                             'roster'         => 'Tool can retrieve roster:',
                                             'crstarget'      => 'Display target',
                                             'crslabel'       => 'Course label',
                                             'crstitle'       => 'Course title', 
                                             'crslinktext'    => 'Link Text',
                                             'crsexplanation' => 'Explanation',
                                           );
       return %lt;
   }
   
 sub print_coursedefaults {  sub print_coursedefaults {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable);      my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles);
     my $itemcount = 1;      my $itemcount = 1;
       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)',
           anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',
           coursecredits        => 'Credits can be specified for courses',
           uselcmath            => 'Math preview uses LON-CAPA previewer (javascript) in place of DragMath (Java)',
           usejsme              => 'Molecule editor uses JSME (HTML5) in place of JME (Java)',
           postsubmit           => 'Disable submit button/keypress following student submission',
           canclone             => "People who may clone a course (besides course's owner and coordinators)",
           mysqltables          => 'Lifetime (s) of "Temporary" MySQL tables (student performance data) on homeserver',
       );
       my %staticdefaults = (
                              anonsurvey_threshold => 10,
                              uploadquota          => 500,
                              postsubmit           => 60,
                              mysqltables          => 172800,
                            );
     if ($position eq 'top') {      if ($position eq 'top') {
         my (%checkedon,%checkedoff,%choices,%defaultchecked,@toggles);          %defaultchecked = (
         %choices =                              'canuse_pdfforms' => 'off',
             &Apache::lonlocal::texthash (                              'uselcmath'       => 'on',
                 canuse_pdfforms => 'Course/Community users can create/upload PDF forms',                              'usejsme'         => 'on',
         );                              'canclone'        => 'none',
         %defaultchecked = ('canuse_pdfforms' => 'off');                            );
         @toggles = ('canuse_pdfforms',);          @toggles = ('canuse_pdfforms','uselcmath','usejsme');
         ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,          ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
                                                  \%choices,$itemcount);                                                       \%choices,$itemcount);
         $$rowtotal += $itemcount;          $css_class = $itemcount%2?' class="LC_odd_row"':'';
           $datatable .=
               '<tr'.$css_class.'><td valign="top">'.
               '<span class="LC_nobreak">'.$choices{'canclone'}.
               '</span></td><td class="LC_left_item">';
           my $currcanclone = 'none';
           my $onclick;
           my @cloneoptions = ('none','domain');
           my %clonetitles = (
                                none     => 'No additional course requesters',
                                domain   => "Any course requester in course's domain",
                                instcode => 'Course requests for official courses ...',
                             );
           my (%codedefaults,@code_order,@posscodes);
           if (&Apache::lonnet::auto_instcode_defaults($dom,\%codedefaults,
                                                       \@code_order) eq 'ok') {
               if (@code_order > 0) {
                   push(@cloneoptions,'instcode');
                   $onclick = ' onclick="toggleDisplay(this.form,'."'cloneinstcode'".');"';
               }
           }
           if (ref($settings) eq 'HASH') {
               if ($settings->{'canclone'}) {
                   if (ref($settings->{'canclone'}) eq 'HASH') {
                       if (ref($settings->{'canclone'}{'instcode'}) eq 'ARRAY') {
                           if (@code_order > 0) {
                               $currcanclone = 'instcode';
                               @posscodes = @{$settings->{'canclone'}{'instcode'}};
                           }
                       }
                   } elsif ($settings->{'canclone'} eq 'domain') {
                       $currcanclone = $settings->{'canclone'};
                   }
               }
           }
           foreach my $option (@cloneoptions) {
               my ($checked,$additional);
               if ($currcanclone eq $option) {
                   $checked = ' checked="checked"';
               }
               if ($option eq 'instcode') {
                   if (@code_order) {
                       my $show = 'none';
                       if ($checked) {
                           $show = 'block';
                       }
                       $additional = '<div id="cloneinstcode" style="display:'.$show.'" />'.
                                     &mt('Institutional codes for new and cloned course have identical:').
                                     '<br />';
                       foreach my $item (@code_order) {
                           my $codechk;
                           if ($checked) {
                               if (grep(/^\Q$item\E$/,@posscodes)) {
                                   $codechk = ' checked="checked"';
                               }
                           }
                           $additional .= '<label>'.
                                          '<input type="checkbox" name="clonecode" value="'.$item.'"'.$codechk.' />'.
                                          $item.'</label>';
                       }
                       $additional .= ('&nbsp;'x2).'('.&mt('check as many as needed').')</div>';
                   }
               }
               $datatable .=
                   '<span class="LC_nobreak"><label><input type="radio" name="canclone"'.$checked.
                   ' value="'.$option.'"'.$onclick.' />'.$clonetitles{$option}.
                   '</label>&nbsp;'.$additional.'</span><br />';
           }
           $datatable .= '</td>'.
                         '</tr>';
           $itemcount ++;
     } else {      } else {
         $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';          $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
         my %choices =          my ($currdefresponder,%defcredits,%curruploadquota,%deftimeout,%currmysql);
             &Apache::lonlocal::texthash (          my $currusecredits = 0;
                 anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',          my $postsubmitclient = 1;
         );          my @types = ('official','unofficial','community','textbook','placement');
         my $currdefresponder;  
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             $currdefresponder = $settings->{'anonsurvey_threshold'};              $currdefresponder = $settings->{'anonsurvey_threshold'};
               if (ref($settings->{'uploadquota'}) eq 'HASH') {
                   foreach my $type (keys(%{$settings->{'uploadquota'}})) {
                       $curruploadquota{$type} = $settings->{'uploadquota'}{$type};
                   }
               }
               if (ref($settings->{'coursecredits'}) eq 'HASH') {
                   foreach my $type (@types) {
                       next if ($type eq 'community');
                       $defcredits{$type} = $settings->{'coursecredits'}->{$type};
                       if ($defcredits{$type} ne '') {
                           $currusecredits = 1;
                       }
                   }
               }
               if (ref($settings->{'postsubmit'}) eq 'HASH') {
                   if ($settings->{'postsubmit'}->{'client'} eq 'off') {
                       $postsubmitclient = 0;
                       foreach my $type (@types) {
                           $deftimeout{$type} = $staticdefaults{'postsubmit'};
                       }
                   } else {
                       foreach my $type (@types) {
                           if (ref($settings->{'postsubmit'}->{'timeout'}) eq 'HASH') {
                               if ($settings->{'postsubmit'}->{'timeout'}->{$type} =~ /^\d+$/) {
                                   $deftimeout{$type} = $settings->{'postsubmit'}->{'timeout'}->{$type};
                               } else {
                                   $deftimeout{$type} = $staticdefaults{'postsubmit'};
                               }
                           } else {
                               $deftimeout{$type} = $staticdefaults{'postsubmit'};
                           }
                       }
                   }
               } else {
                   foreach my $type (@types) {
                       $deftimeout{$type} = $staticdefaults{'postsubmit'};
                   }
               }
               if (ref($settings->{'mysqltables'}) eq 'HASH') {
                   foreach my $type (keys(%{$settings->{'mysqltables'}})) {
                       $currmysql{$type} = $settings->{'mysqltables'}{$type};
                   }
               } else {
                   foreach my $type (@types) {
                       $currmysql{$type} = $staticdefaults{'mysqltables'};
                   }
               }
           } else {
               foreach my $type (@types) {
                   $deftimeout{$type} = $staticdefaults{'postsubmit'};
               }
         }          }
         if (!$currdefresponder) {          if (!$currdefresponder) {
             $currdefresponder = 10;              $currdefresponder = $staticdefaults{'anonsurvey_threshold'};
         } elsif ($currdefresponder < 1) {          } elsif ($currdefresponder < 1) {
             $currdefresponder = 1;              $currdefresponder = 1;
         }          }
           foreach my $type (@types) {
               if ($curruploadquota{$type} eq '') {
                   $curruploadquota{$type} = $staticdefaults{'uploadquota'};
               }
           }
         $datatable .=          $datatable .=
                '<tr'.$css_class.'><td><span class="LC_nobreak">'.$choices{'anonsurvey_threshold'}.                  '<tr'.$css_class.'><td><span class="LC_nobreak">'.
                   $choices{'anonsurvey_threshold'}.
                 '</span></td>'.                  '</span></td>'.
                 '<td class="LC_right_item"><span class="LC_nobreak">'.                  '<td class="LC_right_item"><span class="LC_nobreak">'.
                 '<input type="text" name="anonsurvey_threshold"'.                  '<input type="text" name="anonsurvey_threshold"'.
                 ' value="'.$currdefresponder.'" size="5" /></span>'.                  ' value="'.$currdefresponder.'" size="5" /></span>'.
                 '</td></tr>';                  '</td></tr>'."\n";
           $itemcount ++;
           $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
           $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
                         $choices{'uploadquota'}.
                         '</span></td>'.
                         '<td align="right" class="LC_right_item">'.
                         '<table><tr>';
           foreach my $type (@types) {
               $datatable .= '<td align="center">'.&mt($type).'<br />'.
                              '<input type="text" name="uploadquota_'.$type.'"'.
                              ' value="'.$curruploadquota{$type}.'" size="5" /></td>';
           }
           $datatable .= '</tr></table></td></tr>'."\n";
           $itemcount ++;
           my $onclick = "toggleDisplay(this.form,'credits');";
           my $display = 'none';
           if ($currusecredits) {
               $display = 'block';
           }
           my $additional = '<div id="credits" style="display: '.$display.'">'.
                            '<i>'.&mt('Default credits').'</i><br /><table><tr>';
           foreach my $type (@types) {
               next if ($type eq 'community');
               $additional .= '<td align="center">'.&mt($type).'<br />'.
                              '<input type="text" name="'.$type.'_credits"'.
                              ' value="'.$defcredits{$type}.'" size="3" /></td>';
           }
           $additional .= '</tr></table></div>'."\n";
           %defaultchecked = ('coursecredits' => 'off');
           @toggles = ('coursecredits');
           my $current = {
                           'coursecredits' => $currusecredits,
                         };
           (my $table,$itemcount) =
               &radiobutton_prefs($current,\@toggles,\%defaultchecked,
                                  \%choices,$itemcount,$onclick,$additional,'left');
           $datatable .= $table;
           $onclick = "toggleDisplay(this.form,'studentsubmission');";
           my $display = 'none';
           if ($postsubmitclient) {
               $display = 'block';
           }
           $additional = '<div id="studentsubmission" style="display: '.$display.'">'.
                         &mt('Number of seconds submit is disabled').'<br />'.
                         '<i>'.&mt('Enter 0 to remain disabled until page reload.').'</i><br />'.
                         '<table><tr>';
           foreach my $type (@types) {
               $additional .= '<td align="center">'.&mt($type).'<br />'.
                              '<input type="text" name="'.$type.'_timeout" value="'.
                              $deftimeout{$type}.'" size="5" /></td>';
           }
           $additional .= '</tr></table></div>'."\n";
           %defaultchecked = ('postsubmit' => 'on');
           @toggles = ('postsubmit');
           $current = {
                          'postsubmit' => $postsubmitclient,
                      };
           ($table,$itemcount) =
               &radiobutton_prefs($current,\@toggles,\%defaultchecked,
                                  \%choices,$itemcount,$onclick,$additional,'left');
           $datatable .= $table;
           $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
           $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
                         $choices{'mysqltables'}.
                         '</span></td>'.
                         '<td align="right" class="LC_right_item">'.
                         '<table><tr>';
           foreach my $type (@types) {
               $datatable .= '<td align="center">'.&mt($type).'<br />'.
                              '<input type="text" name="mysqltables_'.$type.'"'.
                              ' value="'.$currmysql{$type}.'" size="8" /></td>';
           }
           $datatable .= '</tr></table></td></tr>'."\n";
           $itemcount ++;
   
       }
       $$rowtotal += $itemcount;
       return $datatable;
   }
   
   sub print_selfenrollment {
       my ($position,$dom,$settings,$rowtotal) = @_;
       my ($css_class,$datatable);
       my $itemcount = 1;
       my @types = ('official','unofficial','community','textbook','placement');
       if (($position eq 'top') || ($position eq 'middle')) {
           my ($rowsref,$titlesref) = &Apache::lonuserutils::get_selfenroll_titles();
           my %descs = &Apache::lonuserutils::selfenroll_default_descs();
           my @rows;
           my $key;
           if ($position eq 'top') {
               $key = 'admin'; 
               if (ref($rowsref) eq 'ARRAY') {
                   @rows = @{$rowsref};
               }
           } elsif ($position eq 'middle') {
               $key = 'default';
               @rows = ('types','registered','approval','limit');
           }
           foreach my $row (@rows) {
               if (defined($titlesref->{$row})) {
                   $itemcount ++;
                   $css_class = $itemcount%2?' class="LC_odd_row"':'';
                   $datatable .= '<tr'.$css_class.'>'.
                                 '<td>'.$titlesref->{$row}.'</td>'.
                                 '<td class="LC_left_item">'.
                                 '<table><tr>';
                   my (%current,%currentcap);
                   if (ref($settings) eq 'HASH') {
                       if (ref($settings->{$key}) eq 'HASH') {
                           foreach my $type (@types) {
                               if (ref($settings->{$key}->{$type}) eq 'HASH') {
                                   $current{$type} = $settings->{$key}->{$type}->{$row};
                               }
                               if (($row eq 'limit') && ($key eq 'default')) {
                                   if (ref($settings->{$key}->{$type}) eq 'HASH') {
                                       $currentcap{$type} = $settings->{$key}->{$type}->{'cap'};
                                   }
                               }
                           }
                       }
                   }
                   my %roles = (
                                '0' => &Apache::lonnet::plaintext('dc'),
                               ); 
               
                   foreach my $type (@types) {
                       unless (($row eq 'registered') && ($key eq 'default')) {
                           $datatable .= '<th>'.&mt($type).'</th>';
                       }
                   }
                   unless (($row eq 'registered') && ($key eq 'default')) {
                       $datatable .= '</tr><tr>';
                   }
                   foreach my $type (@types) {
                       if ($type eq 'community') {
                           $roles{'1'} = &mt('Community personnel');
                       } else {
                           $roles{'1'} = &mt('Course personnel');
                       }
                       $datatable .= '<td style="vertical-align: top">';
                       if ($position eq 'top') {
                           my %checked;
                           if ($current{$type} eq '0') {
                               $checked{'0'} = ' checked="checked"';
                           } else {
                               $checked{'1'} = ' checked="checked"';
                           }
                           foreach my $role ('1','0') {
                               $datatable .= '<span class="LC_nobreak"><label>'.
                                             '<input type="radio" name="selfenrolladmin_'.$row.'_'.$type.'" '.
                                             'value="'.$role.'"'.$checked{$role}.' />'.
                                             $roles{$role}.'</label></span> ';
                           }
                       } else {
                           if ($row eq 'types') {
                               my %checked;
                               if ($current{$type} =~ /^(all|dom)$/) {
                                   $checked{$1} = ' checked="checked"';
                               } else {
                                   $checked{''} = ' checked="checked"';
                               }
                               foreach my $val ('','dom','all') {
                                   $datatable .= '<span class="LC_nobreak"><label>'.
                                                 '<input type ="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.
                                                 'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';
                               }
                           } elsif ($row eq 'registered') {
                               my %checked;
                               if ($current{$type} eq '1') {
                                   $checked{'1'} = ' checked="checked"';
                               } else {
                                   $checked{'0'} = ' checked="checked"';
                               }
                               foreach my $val ('0','1') {
                                   $datatable .= '<span class="LC_nobreak"><label>'.
                                                 '<input type ="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.
                                                 'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';
                               }
                           } elsif ($row eq 'approval') {
                               my %checked;
                               if ($current{$type} =~ /^([12])$/) {
                                   $checked{$1} = ' checked="checked"';
                               } else {
                                   $checked{'0'} = ' checked="checked"';
                               }
                               for my $val (0..2) {
                                   $datatable .= '<span class="LC_nobreak"><label>'.
                                                 '<input type="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.
                                                 'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';
                               }
                           } elsif ($row eq 'limit') {
                               my %checked;
                               if ($current{$type} =~ /^(allstudents|selfenrolled)$/) {
                                   $checked{$1} = ' checked="checked"';
                               } else {
                                   $checked{'none'} = ' checked="checked"';
                               }
                               my $cap;
                               if ($currentcap{$type} =~ /^\d+$/) {
                                   $cap = $currentcap{$type};
                               }
                               foreach my $val ('none','allstudents','selfenrolled') {
                                   $datatable .= '<span class="LC_nobreak"><label>'.
                                                 '<input type="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.
                                                 'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';
                               }
                               $datatable .= '<br />'.
                                             '<span class="LC_nobreak">'.&mt('Maximum allowed: ').
                                             '<input type="text" name="selfenrolldefault_cap_'.$type.'" size = "5" value="'.$cap.'" />'.
                                             '</span>'; 
                           }
                       }
                       $datatable .= '</td>';
                   }
                   $datatable .= '</tr>';
               }
               $datatable .= '</table></td></tr>';
           }
       } elsif ($position eq 'bottom') {
           $datatable .= &print_validation_rows('selfenroll',$dom,$settings,\$itemcount);
       }
       $$rowtotal += $itemcount;
       return $datatable;
   }
   
   sub print_validation_rows {
       my ($caller,$dom,$settings,$rowtotal) = @_;
       my ($itemsref,$namesref,$fieldsref);
       if ($caller eq 'selfenroll') { 
           ($itemsref,$namesref,$fieldsref) = &Apache::lonuserutils::selfenroll_validation_types();
       } elsif ($caller eq 'requestcourses') {
           ($itemsref,$namesref,$fieldsref) = &Apache::loncoursequeueadmin::requestcourses_validation_types();
       }
       my %currvalidation;
       if (ref($settings) eq 'HASH') {
           if (ref($settings->{'validation'}) eq 'HASH') {
               %currvalidation = %{$settings->{'validation'}};
           }
       }
       my $datatable;
       my $itemcount = 0;
       foreach my $item (@{$itemsref}) {
           my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
           $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
                         $namesref->{$item}.
                         '</span></td>'.
                         '<td class="LC_left_item">';
           if (($item eq 'url') || ($item eq 'button')) {
               $datatable .= '<span class="LC_nobreak">'.
                             '<input type="text" name="'.$caller.'_validation_'.$item.'"'.
                             ' value="'.$currvalidation{$item}.'" size="50" /></span>';
           } elsif ($item eq 'fields') {
               my @currfields;
               if (ref($currvalidation{$item}) eq 'ARRAY') {
                   @currfields = @{$currvalidation{$item}};
               }
               foreach my $field (@{$fieldsref}) {
                   my $check = '';
                   if (grep(/^\Q$field\E$/,@currfields)) {
                       $check = ' checked="checked"';
                   }
                   $datatable .= '<span class="LC_nobreak"><label>'.
                                 '<input type="checkbox" name="'.$caller.'_validation_fields"'.
                                 ' value="'.$field.'"'.$check.' />'.$field.
                                 '</label></span> ';
               }
           } elsif ($item eq 'markup') {
               $datatable .= '<textarea name="'.$caller.'_validation_markup" cols="50" rows="5" wrap="soft">'.
                              $currvalidation{$item}.
                                 '</textarea>';
           }
           $datatable .= '</td></tr>'."\n";
           if (ref($rowtotal)) {
               $itemcount ++;
           }
       }
       if ($caller eq 'requestcourses') {
           my %currhash;
           if (ref($settings) eq 'HASH') {
               if (ref($settings->{'validation'}) eq 'HASH') {
                   if ($settings->{'validation'}{'dc'} ne '') {
                       $currhash{$settings->{'validation'}{'dc'}} = 1;
                   }
               }
           }
           my $numinrow = 2;
           my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',
                                                          'validationdc',%currhash);
           my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
           $datatable .= '</td></tr><tr'.$css_class.'><td>';
           if ($numdc > 1) {
               $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)');
           } else {
               $datatable .=  &mt('Course creation processed as: ');
           }
           $datatable .= '</td><td class="LC_left_item">'.$dctable.'</td></tr>';
           $itemcount ++;
       }
       if (ref($rowtotal)) {
           $$rowtotal += $itemcount;
     }      }
     return $datatable;      return $datatable;
 }  }
   
 sub print_usersessions {  sub print_usersessions {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable,%checked,%choices);      my ($css_class,$datatable,$itemcount,%checked,%choices);
     my (%by_ip,%by_location,@intdoms);      my (%by_ip,%by_location,@intdoms,@instdoms);
     &build_location_hashes(\@intdoms,\%by_ip,\%by_location);      &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
   
     my @alldoms = &Apache::lonnet::all_domains();      my @alldoms = &Apache::lonnet::all_domains();
     my %serverhomes = %Apache::lonnet::serverhomeIDs;      my %serverhomes = %Apache::lonnet::serverhomeIDs;
     my %servers = &Apache::lonnet::internet_dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
     my %altids = &id_for_thisdom(%servers);      my %altids = &id_for_thisdom(%servers);
     my $itemcount = 1;  
     if ($position eq 'top') {      if ($position eq 'top') {
         if (keys(%serverhomes) > 1) {          if (keys(%serverhomes) > 1) {
             my %spareid = &current_offloads_to($dom,$settings,\%servers);              my %spareid = &current_offloads_to($dom,$settings,\%servers);
             $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$rowtotal);              my $curroffloadnow;
               if (ref($settings) eq 'HASH') {
                   if (ref($settings->{'offloadnow'}) eq 'HASH') {
                       $curroffloadnow = $settings->{'offloadnow'};
                   }
               }
               $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$curroffloadnow,$rowtotal);
         } else {          } else {
             $datatable .= '<tr'.$css_class.'><td colspan="2">'.              $datatable .= '<tr'.$css_class.'><td colspan="2">'.
                           &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.');                            &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.').
                             '</td></tr>';
         }          }
     } else {      } else {
         if (keys(%by_location) == 0) {          my %titles = &usersession_titles();
             $datatable .= '<tr'.$css_class.'><td colspan="2">'.          my ($prefix,@types);
                           &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.');          if ($position eq 'bottom') {
               $prefix = 'remote';
               @types = ('version','excludedomain','includedomain');
         } else {          } else {
             my %lt = &usersession_titles();              $prefix = 'hosted';
             my $numinrow = 5;              @types = ('excludedomain','includedomain');
             my $prefix;          }
             my @types;          ($datatable,$itemcount) = &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
             if ($position eq 'bottom') {      }
                 $prefix = 'remote';      $$rowtotal += $itemcount;
                 @types = ('version','excludedomain','includedomain');      return $datatable;
             } else {  }
                 $prefix = 'hosted';  
                 @types = ('excludedomain','includedomain');  sub rules_by_location {
             }      my ($settings,$prefix,$by_location,$by_ip,$types,$titles) = @_; 
             my (%current,%checkedon,%checkedoff);      my ($datatable,$itemcount,$css_class);
             my @lcversions = &Apache::lonnet::all_loncaparevs();      if (keys(%{$by_location}) == 0) {
             my @locations = sort(keys(%by_location));          $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
             foreach my $type (@types) {          $datatable = '<tr'.$css_class.'><td colspan="2">'.
                 $checkedon{$type} = '';                       &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.').
                 $checkedoff{$type} = ' checked="checked"';                       '</td></tr>';
             }          $itemcount = 1;
             if (ref($settings) eq 'HASH') {      } else {
                 if (ref($settings->{$prefix}) eq 'HASH') {          $itemcount = 0;
                     foreach my $key (keys(%{$settings->{$prefix}})) {          my $numinrow = 5;
                         $current{$key} = $settings->{$prefix}{$key};          my (%current,%checkedon,%checkedoff);
                         if ($key eq 'version') {          my @locations = sort(keys(%{$by_location}));
                             if ($current{$key} ne '') {          foreach my $type (@{$types}) {
                                 $checkedon{$key} = ' checked="checked"';              $checkedon{$type} = '';
                                 $checkedoff{$key} = '';              $checkedoff{$type} = ' checked="checked"';
                             }          }
                         } elsif (ref($current{$key}) eq 'ARRAY') {          if (ref($settings) eq 'HASH') {
               if (ref($settings->{$prefix}) eq 'HASH') {
                   foreach my $key (keys(%{$settings->{$prefix}})) {
                       $current{$key} = $settings->{$prefix}{$key};
                       if ($key eq 'version') {
                           if ($current{$key} ne '') {
                             $checkedon{$key} = ' checked="checked"';                              $checkedon{$key} = ' checked="checked"';
                             $checkedoff{$key} = '';                              $checkedoff{$key} = '';
                         }                          }
                       } elsif (ref($current{$key}) eq 'ARRAY') {
                           $checkedon{$key} = ' checked="checked"';
                           $checkedoff{$key} = '';
                     }                      }
                 }                  }
             }              }
             foreach my $type (@types) {          }
                 next if ($type ne 'version' && !@locations);          foreach my $type (@{$types}) {
                 $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';              next if ($type ne 'version' && !@locations);
                 $datatable .= '<tr'.$css_class.'>              $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
                                <td><span class="LC_nobreak">'.$lt{$type}.'</span><br />              $datatable .= '<tr'.$css_class.'>
                                <span class="LC_nobreak">&nbsp;                             <td><span class="LC_nobreak">'.$titles->{$type}.'</span><br />
                                <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>&nbsp;                             <span class="LC_nobreak">&nbsp;
                                <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';                             <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>&nbsp;
                 if ($type eq 'version') {                             <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';
                     my $selector = '<select name="'.$prefix.'_version">';              if ($type eq 'version') {
                     foreach my $version (@lcversions) {                  my @lcversions = &Apache::lonnet::all_loncaparevs();
                         my $selected = '';                  my $selector = '<select name="'.$prefix.'_version">';
                         if ($current{'version'} eq $version) {                  foreach my $version (@lcversions) {
                             $selected = ' selected="selected"';                      my $selected = '';
                         }                      if ($current{'version'} eq $version) {
                         $selector .= ' <option value="'.$version.'"'.                          $selected = ' selected="selected"';
                                      $selected.'>'.$version.'</option>';  
                     }                      }
                     $selector .= '</select> ';                      $selector .= ' <option value="'.$version.'"'.
                     $datatable .= &mt('remote server must be version: [_1] or later',$selector);                                   $selected.'>'.$version.'</option>';
                 } else {                  }
                     $datatable.= '<div><input type="button" value="'.&mt('check all').'" '.                  $selector .= '</select> ';
                                  'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.                  $datatable .= &mt('remote server must be version: [_1] or later',$selector);
                                  ' />'.('&nbsp;'x2).              } else {
                                  '<input type="button" value="'.&mt('uncheck all').'" '.                  $datatable.= '<div><input type="button" value="'.&mt('check all').'" '.
                                  'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.                               'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.
                                  "\n".                               ' />'.('&nbsp;'x2).
                                  '</div><div><table>';                               '<input type="button" value="'.&mt('uncheck all').'" '.
                     my $rem;                               'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.
                     for (my $i=0; $i<@locations; $i++) {                               "\n".
                         my ($showloc,$value,$checkedtype);                               '</div><div><table>';
                         if (ref($by_location{$locations[$i]}) eq 'ARRAY') {                  my $rem;
                             my $ip = $by_location{$locations[$i]}->[0];                  for (my $i=0; $i<@locations; $i++) {
                             if (ref($by_ip{$ip}) eq 'ARRAY') {                      my ($showloc,$value,$checkedtype);
                                  $value = join(':',@{$by_ip{$ip}});                      if (ref($by_location->{$locations[$i]}) eq 'ARRAY') {
                                 $showloc = join(', ',@{$by_ip{$ip}});                          my $ip = $by_location->{$locations[$i]}->[0];
                                 if (ref($current{$type}) eq 'ARRAY') {                          if (ref($by_ip->{$ip}) eq 'ARRAY') {
                                     foreach my $loc (@{$by_ip{$ip}}) {                                $value = join(':',@{$by_ip->{$ip}});
                                         if (grep(/^\Q$loc\E$/,@{$current{$type}})) {                              $showloc = join(', ',@{$by_ip->{$ip}});
                                             $checkedtype = ' checked="checked"';                              if (ref($current{$type}) eq 'ARRAY') {
                                             last;                                  foreach my $loc (@{$by_ip->{$ip}}) {
                                         }                                      if (grep(/^\Q$loc\E$/,@{$current{$type}})) {
                                           $checkedtype = ' checked="checked"';
                                           last;
                                     }                                      }
                                 }                                  }
                             }                              }
                         }                          }
                         $rem = $i%($numinrow);  
                         if ($rem == 0) {  
                             if ($i > 0) {  
                                 $datatable .= '</tr>';  
                             }  
                             $datatable .= '<tr>';  
                         }  
                         $datatable .= '<td class="LC_left_item">'.  
                                       '<span class="LC_nobreak"><label>'.  
                                       '<input type="checkbox" name="'.$prefix.'_'.$type.  
                                       '" value="'.$value.'"'.$checkedtype.' />'.$showloc.  
                                       '</label></span></td>';  
                     }                      }
                     $rem = @locations%($numinrow);                      $rem = $i%($numinrow);
                     my $colsleft = $numinrow - $rem;                      if ($rem == 0) {
                     if ($colsleft > 1 ) {                          if ($i > 0) {
                         $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.                              $datatable .= '</tr>';
                                       '&nbsp;</td>';                          }
                     } elsif ($colsleft == 1) {                          $datatable .= '<tr>';
                         $datatable .= '<td class="LC_left_item">&nbsp;</td>';                      }
                       $datatable .= '<td class="LC_left_item">'.
                                     '<span class="LC_nobreak"><label>'.
                                     '<input type="checkbox" name="'.$prefix.'_'.$type.
                                     '" value="'.$value.'"'.$checkedtype.' />'.$showloc.
                                     '</label></span></td>';
                   }
                   $rem = @locations%($numinrow);
                   my $colsleft = $numinrow - $rem;
                   if ($colsleft > 1 ) {
                       $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                                     '&nbsp;</td>';
                   } elsif ($colsleft == 1) {
                       $datatable .= '<td class="LC_left_item">&nbsp;</td>';
                   }
                   $datatable .= '</tr></table>';
               }
               $datatable .= '</td></tr>';
               $itemcount ++;
           }
       }
       return ($datatable,$itemcount);
   }
   
   sub print_ssl {
       my ($position,$dom,$settings,$rowtotal) = @_;
       my ($css_class,$datatable);
       my $itemcount = 1;
       if ($position eq 'top') {
           my $primary_id = &Apache::lonnet::domain($dom,'primary');
           my $intdom = &Apache::lonnet::internet_dom($primary_id);
           my $same_institution;
           if ($intdom ne '') {
               my $internet_names = &Apache::lonnet::get_internet_names($Apache::lonnet::perlvar{'lonHostID'});
               if (ref($internet_names) eq 'ARRAY') {
                   if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
                       $same_institution = 1;
                   }
               }
           }
           $css_class = $itemcount%2?' class="LC_odd_row"':'';
           $datatable = '<tr'.$css_class.'><td colspan="2">';
           if ($same_institution) {
               my %domservers = &Apache::lonnet::get_servers($dom);
               $datatable .= &LONCAPA::SSL::print_certstatus(\%domservers,'web','domprefs');
           } else {
               $datatable .= &mt("You need to be logged into one of your own domain's servers to display information about the status of LON-CAPA SSL certificates.");
           }
           $datatable .= '</td></tr>';
           $itemcount ++;
       } else {
           my %titles = &ssl_titles();
           my (%by_ip,%by_location,@intdoms,@instdoms);
           &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
           my @alldoms = &Apache::lonnet::all_domains();
           my %serverhomes = %Apache::lonnet::serverhomeIDs;
           my @domservers = &Apache::lonnet::get_servers($dom);
           my %servers = &Apache::lonnet::internet_dom_servers($dom);
           my %altids = &id_for_thisdom(%servers);
           if (($position eq 'connto') || ($position eq 'connfrom')) {
               my $legacy;
               unless (ref($settings) eq 'HASH') {
                   my $name;
                   if ($position eq 'connto') {
                       $name = 'loncAllowInsecure';
                   } else {
                       $name = 'londAllowInsecure';
                   }
                   my $primarylibserv = &Apache::lonnet::domain($dom,'primary');
                   my @ids=&Apache::lonnet::current_machine_ids();
                   if (($primarylibserv ne '') && (!grep(/^\Q$primarylibserv\E$/,@ids))) {
                       my %what = (
                                      $name => 1,
                                  );
                       my ($result,$returnhash) =
                           &Apache::lonnet::get_remote_globals($primarylibserv,\%what);
                       if ($result eq 'ok') {
                           if (ref($returnhash) eq 'HASH') {
                               $legacy = $returnhash->{$name};
                           }
                       }
                   } else {
                       $legacy = $Apache::lonnet::perlvar{$name};
                   }
               }
               foreach my $type ('dom','intdom','other') {
                   my %checked;
                   $css_class = $itemcount%2?' class="LC_odd_row"':'';
                   $datatable .= '<tr'.$css_class.'><td>'.$titles{$type}.'</td>'.
                                 '<td class="LC_right_item">';
                   my $skip; 
                   if ($type eq 'dom') {
                       unless (keys(%servers) > 1) {
                           $datatable .= &mt('Nothing to set here, as there are no other servers/VMs');    
                           $skip = 1;
                       }
                   }
                   if ($type eq 'intdom') {
                       unless (@instdoms > 1) {
                           $datatable .= &mt('Nothing to set here, as there are no other domains for this institution');
                           $skip = 1;
                       } 
                   } elsif ($type eq 'other') {
                       if (keys(%by_location) == 0) {
                           $datatable .= &mt('Nothing to set here, as there are no other institutions');
                           $skip = 1;
                       }
                   }
                   unless ($skip) {
                       $checked{'yes'} = ' checked="checked"'; 
                       if (ref($settings) eq 'HASH') {
                           if (ref($settings->{$position}) eq 'HASH') {
                               if ($settings->{$position}->{$type} =~ /^(no|req)$/) {
                                   $checked{$1} = $checked{'yes'};
                                   delete($checked{'yes'}); 
                               }
                           }
                       } else {
                           if ($legacy == 0) {
                               $checked{'req'} = $checked{'yes'};
                               delete($checked{'yes'});    
                           }
                       }
                       foreach my $option ('no','yes','req') {
                           $datatable .= '<span class="LC_nobreak"><label>'.
                                         '<input type="radio" name="'.$position.'_'.$type.'" '.
                                         'value="'.$option.'"'.$checked{$option}.' />'.$titles{$option}.
                                         '</label></span>'.('&nbsp;'x2);
                     }                      }
                     $datatable .= '</tr></table>';  
                 }                  }
                 $datatable .= '</td></tr>';                  $datatable .= '</td></tr>';
                   $itemcount ++; 
               }
           } else {
               my $prefix = 'replication';
               my @types = ('certreq','nocertreq');
               if (keys(%by_location) == 0) {
                   $datatable .= '<tr'.$css_class.'><td>'.
                                 &mt('Nothing to set here, as there are no other institutions').
                                 '</td></tr>';
                 $itemcount ++;                  $itemcount ++;
               } else {
                   ($datatable,$itemcount) = 
                       &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
             }              }
         }          }
     }      }
Line 2574  sub print_usersessions { Line 4810  sub print_usersessions {
     return $datatable;      return $datatable;
 }  }
   
   sub ssl_titles {
       return &Apache::lonlocal::texthash (
                  dom           => 'LON-CAPA servers/VMs from same domain',
                  intdom        => 'LON-CAPA servers/VMs from same "internet" domain',
                  other         => 'External LON-CAPA servers/VMs',
                  connto        => 'Connections to other servers',
                  connfrom      => 'Connections from other servers',
                  replication   => 'Replicating content to other institutions',
                  certreq       => 'Client certificate required, but specific domains exempt',
                  nocertreq     => 'No client certificate required, except for specific domains',
                  no            => 'SSL not used',
                  yes           => 'SSL Optional (used if available)',
                  req           => 'SSL Required',
       );
   }
   
   sub print_trust {
       my ($prefix,$dom,$settings,$rowtotal) = @_;
       my ($css_class,$datatable,%checked,%choices);
       my (%by_ip,%by_location,@intdoms,@instdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
       my $itemcount = 1;
       my %titles = &trust_titles();
       my @types = ('exc','inc');
       if ($prefix eq 'top') {
           $prefix = 'content';
       } elsif ($prefix eq 'bottom') {
           $prefix = 'msg';
       }
       ($datatable,$itemcount) = &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
       $$rowtotal += $itemcount;
       return $datatable;
   }
   
   sub trust_titles {
       return &Apache::lonlocal::texthash(
                  content  => "Access to this domain's content by others",
                  shared   => "Access to other domain's content by this domain",
                  enroll   => "Enrollment in this domain's courses by others", 
                  othcoau  => "Co-author roles in this domain for others",
                  coaurem  => "Co-author roles for this domain's users elsewhere", 
                  domroles => "Domain roles in this domain assignable to others",
                  catalog  => "Course Catalog for this domain displayed elsewhere",
                  reqcrs   => "Requests for creation of courses in this domain by others",
                  msg      => "Users in other domains can send messages to this domain",
                  exc      => "Allow all, but exclude specific domains",
                  inc      => "Deny all, but include specific domains",
              );
   } 
   
 sub build_location_hashes {  sub build_location_hashes {
     my ($intdoms,$by_ip,$by_location) = @_;      my ($intdoms,$by_ip,$by_location,$instdoms) = @_;
     return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') &&      return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') &&
                   (ref($by_location) eq 'HASH'));                     (ref($by_location) eq 'HASH') && (ref($instdoms) eq 'ARRAY'));
     my %iphost = &Apache::lonnet::get_iphost();      my %iphost = &Apache::lonnet::get_iphost();
     my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary');      my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary');
     my $primary_ip = &Apache::lonnet::get_host_ip($primary_id);      my $primary_ip = &Apache::lonnet::get_host_ip($primary_id);
Line 2594  sub build_location_hashes { Line 4880  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 2702  sub current_offloads_to { Line 4994  sub current_offloads_to {
 }  }
   
 sub spares_row {  sub spares_row {
     my ($dom,$servers,$spareid,$serverhomes,$altids,$rowtotal) = @_;      my ($dom,$servers,$spareid,$serverhomes,$altids,$curroffloadnow,$rowtotal) = @_;
     my $css_class;      my $css_class;
     my $numinrow = 4;      my $numinrow = 4;
     my $itemcount = 1;      my $itemcount = 1;
Line 2722  sub spares_row { Line 5014  sub spares_row {
                 }                  }
             }              }
             next unless (ref($spareid->{$server}) eq 'HASH');              next unless (ref($spareid->{$server}) eq 'HASH');
               my $checkednow;
               if (ref($curroffloadnow) eq 'HASH') {
                   if ($curroffloadnow->{$server}) {
                       $checkednow = ' checked="checked"';
                   }
               }
             $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';              $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
             $datatable .= '<tr'.$css_class.'>              $datatable .= '<tr'.$css_class.'>
                            <td rowspan="2">                             <td rowspan="2">
                             <span class="LC_nobreak"><b>'.$server.'</b> when busy, offloads to:</span></td>'."\n";                              <span class="LC_nobreak">'.
                             &mt('[_1] when busy, offloads to:'
                                 ,'<b>'.$server.'</b>').'</span><br />'.
                             '<span class="LC_nobreak">'."\n".
                             '<label><input type="checkbox" name="offloadnow" value="'.$server.'"'.$checkednow.' />'.
                             '&nbsp;'.&mt('Switch active users 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 2849  sub print_loadbalancing { Line 5153  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);      my (%currbalancer,%currtargets,%currrules,%existing);
     if (keys(%servers) > 1) {      if (ref($settings) eq 'HASH') {
         if (ref($settings) eq 'HASH') {          %existing = %{$settings};
             $currbalancer = $settings->{'lonhost'};      }
             $currtargets = $settings->{'targets'};      if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
             $currrules = $settings->{'rules'};          &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
         } else {                                    \%currtargets,\%currrules);
             ($currbalancer,$currtargets) =   
                 &Apache::lonnet::get_lonbalancer_config(\%servers);  
         }  
     } else {      } else {
         return;          return;
     }      }
     my ($othertitle,$usertypes,$types) =      my ($othertitle,$usertypes,$types) =
         &Apache::loncommon::sorted_inst_types($dom);          &Apache::loncommon::sorted_inst_types($dom);
     my $rownum = 6;      my $rownum = 8;
     if (ref($types) eq 'ARRAY') {      if (ref($types) eq 'ARRAY') {
         $rownum += scalar(@{$types});          $rownum += scalar(@{$types});
     }      }
     my $css_class = ' class="LC_odd_row"';      my @css_class = ('LC_odd_row','LC_even_row');
     my $targets_div_style = 'display: none';      my $balnum = 0;
     my $disabled_div_style = 'display: block';      my $islast;
     my $homedom_div_style = 'display: none';      my (@toshow,$disabledtext);
     $datatable = '<tr'.$css_class.'>'.      if (keys(%currbalancer) > 0) {
                  '<td rowspan="'.$rownum.'" valign="top">'.          @toshow = sort(keys(%currbalancer));
                  '<p><select name="loadbalancing_lonhost" onchange="toggleTargets();">'."\n".          if (scalar(@toshow) < scalar(keys(%servers)) + 1) {
                  '<option value=""';              push(@toshow,'');
     if (($currbalancer eq '') || (!grep(/^\Q$currbalancer\E$/,keys(%servers)))) {          }
         $datatable .= ' selected="selected"';      } else {
     } else {          @toshow = ('');
         $targets_div_style = 'display: block';          $disabledtext = &mt('No existing load balancer');
         $disabled_div_style = 'display: none';      }
         if ($dom eq &Apache::lonnet::host_domain($currbalancer)) {      foreach my $lonhost (@toshow) {
             $homedom_div_style = 'display: block';           if ($balnum == scalar(@toshow)-1) {
         }              $islast = 1;
     }          } else {
     $datatable .= '>'.&mt('None').'</option>'."\n";              $islast = 0;
     foreach my $lonhost (sort(keys(%servers))) {          }
         my $selected;          my $cssidx = $balnum%2;
         if ($lonhost eq $currbalancer) {          my $targets_div_style = 'display: none';
             $selected .= ' selected="selected"';          my $disabled_div_style = 'display: block';
         }          my $homedom_div_style = 'display: none';
         $datatable .= '<option value="'.$lonhost.'"'.$selected.'>'.$lonhost.'</option>'."\n";          $datatable .= '<tr class="'.$css_class[$cssidx].'">'.
     }                        '<td rowspan="'.$rownum.'" valign="top">'.
     $datatable .= '</select></p></td><td rowspan="'.$rownum.'" valign="top">'.                        '<p>';
                   '<div id="loadbalancing_disabled" style="'.$disabled_div_style.'">'.&mt('No dedicated Load Balancer').'</div>'."\n".          if ($lonhost eq '') {
                   '<div id="loadbalancing_targets" style="'.$targets_div_style.'">'.&mt('Offloads to:').'<br />';              $datatable .= '<span class="LC_nobreak">';
     my ($numspares,@spares) = &count_servers($currbalancer,%servers);              if (keys(%currbalancer) > 0) {
     my @sparestypes = ('primary','default');                  $datatable .= &mt('Add balancer:');
     my %typetitles = &sparestype_titles();              } else {
     foreach my $sparetype (@sparestypes) {                  $datatable .= &mt('Enable balancer:');
         my $targettable;              }
         for (my $i=0; $i<$numspares; $i++) {              $datatable .= '&nbsp;'.
             my $checked;                            '<select name="loadbalancing_lonhost_'.$balnum.'"'.
             if (ref($currtargets) eq 'HASH') {                            ' id="loadbalancing_lonhost_'.$balnum.'"'.
                 if (ref($currtargets->{$sparetype}) eq 'ARRAY') {                            ' onchange="toggleTargets('."'$balnum'".');">'."\n".
                     if (grep(/^\Q$spares[$i]\E$/,@{$currtargets->{$sparetype}})) {                            '<option value="" selected="selected">'.&mt('None').
                         $checked = ' checked="checked"';                            '</option>'."\n";
               foreach my $server (sort(keys(%servers))) {
                   next if ($currbalancer{$server});
                   $datatable .= '<option value="'.$server.'">'.$server.'</option>'."\n";
               }
               $datatable .=
                   '</select>'."\n".
                   '<input type="hidden" name="loadbalancing_prevlonhost_'.$balnum.'" id="loadbalancing_prevlonhost_'.$balnum.'" value="" />&nbsp;</span>'."\n";
           } else {
               $datatable .= '<i>'.$lonhost.'</i><br /><span class="LC_nobreak">'.
                             '<label><input type="checkbox" name="loadbalancing_delete" value="'.$balnum.'" id="loadbalancing_delete_'.$balnum.'" onclick="javascript:balancerDeleteChange('."'$balnum'".');" />&nbsp;'.
                              &mt('Stop balancing').'</label>'.
                              '<input type="hidden" name="loadbalancing_lonhost_'.$balnum.'" value="'.$lonhost.'" id="loadbalancing_lonhost_'.$balnum.'" /></span>';
               $targets_div_style = 'display: block';
               $disabled_div_style = 'display: none';
               if ($dom eq &Apache::lonnet::host_domain($lonhost)) {
                   $homedom_div_style = 'display: block';
               }
           }
           $datatable .= '</p></td><td rowspan="'.$rownum.'" valign="top">'.
                     '<div id="loadbalancing_disabled_'.$balnum.'" style="'.
                     $disabled_div_style.'">'.$disabledtext.'</div>'."\n".
                     '<div id="loadbalancing_targets_'.$balnum.'" style="'.$targets_div_style.'">'.&mt('Offloads to:').'<br />';
           my ($numspares,@spares) = &count_servers($lonhost,%servers);
           my @sparestypes = ('primary','default');
           my %typetitles = &sparestype_titles();
           my %hostherechecked = (
                                     no => ' checked="checked"',
                                 );
           foreach my $sparetype (@sparestypes) {
               my $targettable;
               for (my $i=0; $i<$numspares; $i++) {
                   my $checked;
                   if (ref($currtargets{$lonhost}) eq 'HASH') {
                       if (ref($currtargets{$lonhost}{$sparetype}) eq 'ARRAY') {
                           if (grep(/^\Q$spares[$i]\E$/,@{$currtargets{$lonhost}{$sparetype}})) {
                               $checked = ' checked="checked"';
                           }
                       }
                   }
                   my ($chkboxval,$disabled);
                   if (($lonhost ne '') && (exists($servers{$lonhost}))) {
                       $chkboxval = $spares[$i];
                   }
                   if (exists($currbalancer{$spares[$i]})) {
                       $disabled = ' disabled="disabled"';
                   }
                   $targettable .=
                       '<td><span class="LC_nobreak"><label>'.
                       '<input type="checkbox" name="loadbalancing_target_'.$balnum.'_'.$sparetype.'"'.
                       $checked.$disabled.' value="'.$chkboxval.'" id="loadbalancing_target_'.$balnum.'_'.$sparetype.'_'.$i.'" onclick="checkOffloads('."this,'$balnum','$sparetype'".');" /><span id="loadbalancing_targettxt_'.$balnum.'_'.$sparetype.'_'.$i.'">&nbsp;'.$chkboxval.
                       '</span></label></span></td>';
                   my $rem = $i%($numinrow);
                   if ($rem == 0) {
                       if (($i > 0) && ($i < $numspares-1)) {
                           $targettable .= '</tr>';
                       }
                       if ($i < $numspares-1) {
                           $targettable .= '<tr>';
                     }                      }
                 }                  }
             }              }
             my $chkboxval;              if ($targettable ne '') {
             if (($currbalancer ne '') && (grep((/^\Q$currbalancer\E$/,keys(%servers))))) {                  my $rem = $numspares%($numinrow);
                 $chkboxval = $spares[$i];                  my $colsleft = $numinrow - $rem;
             }                  if ($colsleft > 1 ) {
             $targettable .= '<td><label><input type="checkbox" name="loadbalancing_target_'.$sparetype.'"'.                      $targettable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                       $checked.' value="'.$chkboxval.'" id="loadbalancing_target_'.$sparetype.'_'.$i.'" onclick="checkOffloads('."this,'$sparetype'".');" /><span id="loadbalancing_targettxt_'.$sparetype.'_'.$i.'">&nbsp;'.$chkboxval.                                      '&nbsp;</td>';
                       '</span></label></td>';                  } elsif ($colsleft == 1) {
             my $rem = $i%($numinrow);                      $targettable .= '<td class="LC_left_item">&nbsp;</td>';
             if ($rem == 0) {                  }
                 if ($i > 0) {                  $datatable .=  '<i>'.$typetitles{$sparetype}.'</i><br />'.
                     $targettable .= '</tr>';                                 '<table><tr>'.$targettable.'</tr></table><br />';
               }
               $hostherechecked{$sparetype} = '';
               if (ref($currtargets{$lonhost}) eq 'HASH') {
                   if (ref($currtargets{$lonhost}{$sparetype}) eq 'ARRAY') {
                       if (grep(/^\Q$lonhost\E$/,@{$currtargets{$lonhost}{$sparetype}})) {
                           $hostherechecked{$sparetype} = ' checked="checked"';
                           $hostherechecked{'no'} = '';
                       }
                 }                  }
                 $targettable .= '<tr>';  
             }              }
         }          }
         if ($targettable ne '') {          $datatable .= &mt('Hosting on balancer itself').'<br />'.
             my $rem = $numspares%($numinrow);                        '<label><input type="radio" name="loadbalancing_target_'.$balnum.'_hosthere" value="no"'.
             my $colsleft = $numinrow - $rem;                        $hostherechecked{'no'}.' />'.&mt('No').'</label><br />';
             if ($colsleft > 1 ) {          foreach my $sparetype (@sparestypes) {
                 $targettable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.              $datatable .= '<label><input type="radio" name="loadbalancing_target_'.$balnum.'_hosthere" '.
                                 '&nbsp;</td>';                            'value="'.$sparetype.'"'.$hostherechecked{$sparetype}.' /><i>'.$typetitles{$sparetype}.
             } elsif ($colsleft == 1) {                            '</i></label><br />';
                 $targettable .= '<td class="LC_left_item">&nbsp;</td>';          }
           $datatable .= '</div></td></tr>'.
                         &loadbalancing_rules($dom,$intdom,$currrules{$lonhost},
                                              $othertitle,$usertypes,$types,\%servers,
                                              \%currbalancer,$lonhost,
                                              $targets_div_style,$homedom_div_style,
                                              $css_class[$cssidx],$balnum,$islast);
           $$rowtotal += $rownum;
           $balnum ++;
       }
       $datatable .= '<input type="hidden" name="loadbalancing_total" id="loadbalancing_total" value="'.$balnum.'" />';
       return $datatable;
   }
   
   sub get_loadbalancers_config {
       my ($servers,$existing,$currbalancer,$currtargets,$currrules) = @_;
       return unless ((ref($servers) eq 'HASH') &&
                      (ref($existing) eq 'HASH') && (ref($currbalancer) eq 'HASH') &&
                      (ref($currtargets) eq 'HASH') && (ref($currrules) eq 'HASH'));
       if (keys(%{$existing}) > 0) {
           my $oldlonhost;
           foreach my $key (sort(keys(%{$existing}))) {
               if ($key eq 'lonhost') {
                   $oldlonhost = $existing->{'lonhost'};
                   $currbalancer->{$oldlonhost} = 1;
               } elsif ($key eq 'targets') {
                   if ($oldlonhost) {
                       $currtargets->{$oldlonhost} = $existing->{'targets'};
                   }
               } elsif ($key eq 'rules') {
                   if ($oldlonhost) {
                       $currrules->{$oldlonhost} = $existing->{'rules'};
                   }
               } elsif (ref($existing->{$key}) eq 'HASH') {
                   $currbalancer->{$key} = 1;
                   $currtargets->{$key} = $existing->{$key}{'targets'};
                   $currrules->{$key} = $existing->{$key}{'rules'};
               }
           }
       } else {
           my ($balancerref,$targetsref) =
                   &Apache::lonnet::get_lonbalancer_config($servers);
           if ((ref($balancerref) eq 'HASH') && (ref($targetsref) eq 'HASH')) {
               foreach my $server (sort(keys(%{$balancerref}))) {
                   $currbalancer->{$server} = 1;
                   $currtargets->{$server} = $targetsref->{$server};
             }              }
             $datatable .=  '<i>'.$typetitles{$sparetype}.'</i><br />'.  
                            '<table><tr>'.$targettable.'</table><br />';  
         }          }
     }      }
     $datatable .= '</div></td></tr>'.      return;
                   &loadbalancing_rules($dom,$intdom,$currrules,$othertitle,  
                                        $usertypes,$types,\%servers,$currbalancer,  
                                        $targets_div_style,$homedom_div_style,$css_class);  
     $$rowtotal += $rownum;  
     return $datatable;  
 }  }
   
 sub loadbalancing_rules {  sub loadbalancing_rules {
     my ($dom,$intdom,$currrules,$othertitle,$usertypes,$types,$servers,      my ($dom,$intdom,$currrules,$othertitle,$usertypes,$types,$servers,
         $currbalancer,$targets_div_style,$homedom_div_style,$css_class) = @_;          $currbalancer,$lonhost,$targets_div_style,$homedom_div_style,
           $css_class,$balnum,$islast) = @_;
     my $output;      my $output;
     my ($alltypes,$othertypes,$titles) =       my $num = 0;
       my ($alltypes,$othertypes,$titles) =
         &loadbalancing_titles($dom,$intdom,$usertypes,$types);          &loadbalancing_titles($dom,$intdom,$usertypes,$types);
     if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH'))  {      if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH'))  {
         foreach my $type (@{$alltypes}) {          foreach my $type (@{$alltypes}) {
               $num ++;
             my $current;              my $current;
             if (ref($currrules) eq 'HASH') {              if (ref($currrules) eq 'HASH') {
                 $current = $currrules->{$type};                  $current = $currrules->{$type};
             }              }
             if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {              if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {
                 if ($dom ne &Apache::lonnet::host_domain($currbalancer)) {                  if ($dom ne &Apache::lonnet::host_domain($lonhost)) {
                     $current = '';                      $current = '';
                 }                  }
             }              }
             $output .= &loadbalance_rule_row($type,$titles->{$type},$current,              $output .= &loadbalance_rule_row($type,$titles->{$type},$current,
                                              $servers,$currbalancer,$dom,                                               $servers,$currbalancer,$lonhost,$dom,
                                              $targets_div_style,$homedom_div_style,$css_class);                                               $targets_div_style,$homedom_div_style,
                                                $css_class,$balnum,$num,$islast);
         }          }
     }      }
     return $output;      return $output;
Line 2978  sub loadbalancing_titles { Line 5386  sub loadbalancing_titles {
            '_LC_author'      => &mt('Users from [_1] with author role',$dom),             '_LC_author'      => &mt('Users from [_1] with author role',$dom),
            '_LC_internetdom' => &mt('Users not from [_1], but from [_2]',$dom,$intdom),             '_LC_internetdom' => &mt('Users not from [_1], but from [_2]',$dom,$intdom),
            '_LC_external'    => &mt('Users not from [_1]',$intdom),             '_LC_external'    => &mt('Users not from [_1]',$intdom),
              '_LC_ipchangesso' => &mt('SSO users from [_1], with IP mismatch',$dom),
              '_LC_ipchange'    => &mt('Non-SSO users with IP mismatch'),
                      );                       );
     my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external');      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') {
         unshift(@alltypes,@{$types},'default');          @available = @{$types};
       }
       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 3002  sub loadbalancing_titles { Line 5417  sub loadbalancing_titles {
 }  }
   
 sub loadbalance_rule_row {  sub loadbalance_rule_row {
     my ($type,$title,$current,$servers,$currbalancer,$dom,$targets_div_style,      my ($type,$title,$current,$servers,$currbalancer,$lonhost,$dom,
         $homedom_div_style,$css_class) = @_;          $targets_div_style,$homedom_div_style,$css_class,$balnum,$num,$islast) = @_;
     my @rulenames = ('default','homeserver');      my @rulenames;
     my %ruletitles = &offloadtype_text();      my %ruletitles = &offloadtype_text();
     if ($type eq '_LC_external') {      if (($type eq '_LC_ipchangesso') || ($type eq '_LC_ipchange')) {
         push(@rulenames,'externalbalancer');          @rulenames = ('balancer','offloadedto','specific');
     } else {      } else {
         push(@rulenames,'specific');          @rulenames = ('default','homeserver');
           if ($type eq '_LC_external') {
               push(@rulenames,'externalbalancer');
           } else {
               push(@rulenames,'specific');
           }
           push(@rulenames,'none');
     }      }
     push(@rulenames,'none');  
     my $style = $targets_div_style;      my $style = $targets_div_style;
     if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {      if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {
         $style = $homedom_div_style;          $style = $homedom_div_style;
     }      }
     my $output =       my $space;
         '<tr'.$css_class.'><td valign="top"><div id="balanceruletitle_'.$type.'" style="'.$style.'">'.$title.'</div></td>'."\n".      if ($islast && $num == 1) {
         '<td><div id="balancerule_'.$type.'" style="'.$style.'">'."\n";          $space = '<div display="inline-block">&nbsp;</div>';
       }
       my $output =
           '<tr class="'.$css_class.'" id="balanceruletr_'.$balnum.'_'.$num.'"><td valign="top">'.$space.
           '<div id="balanceruletitle_'.$balnum.'_'.$type.'" style="'.$style.'">'.$title.'</div></td>'."\n".
           '<td valaign="top">'.$space.
           '<div id="balancerule_'.$balnum.'_'.$type.'" style="'.$style.'">'."\n";
     for (my $i=0; $i<@rulenames; $i++) {      for (my $i=0; $i<@rulenames; $i++) {
         my $rule = $rulenames[$i];          my $rule = $rulenames[$i];
         my ($checked,$extra);          my ($checked,$extra);
Line 3034  sub loadbalance_rule_row { Line 5460  sub loadbalance_rule_row {
                 unless ($checked) {                  unless ($checked) {
                     $default = ' selected="selected"';                      $default = ' selected="selected"';
                 }                  }
                 $extra = ':&nbsp;<select name="loadbalancing_singleserver_'.$type.                  $extra =
                          '" id="loadbalancing_singleserver_'.$type.                      ':&nbsp;<select name="loadbalancing_singleserver_'.$balnum.'_'.$type.
                          '" onchange="singleServerToggle('."'$type'".')">'."\n".                      '" id="loadbalancing_singleserver_'.$balnum.'_'.$type.
                          '<option value=""'.$default.'></option>'."\n";                      '" onchange="singleServerToggle('."'$balnum','$type'".')">'."\n".
                 foreach my $lonhost (sort(keys(%{$servers}))) {                      '<option value=""'.$default.'></option>'."\n";
                     next if ($lonhost eq $currbalancer);                  foreach my $server (sort(keys(%{$servers}))) {
                       if (ref($currbalancer) eq 'HASH') {
                           next if (exists($currbalancer->{$server}));
                       }
                     my $selected;                      my $selected;
                     if ($lonhost eq $current) {                      if ($server eq $current) {
                         $selected = ' selected="selected"';                          $selected = ' selected="selected"';
                     }                      }
                     $extra .= '<option value="'.$lonhost.'"'.$selected.'>'.$lonhost.'</option>';                      $extra .= '<option value="'.$server.'"'.$selected.'>'.$server.'</option>';
                 }                  }
                 $extra .= '</select>';                  $extra .= '</select>';
             }              }
Line 3052  sub loadbalance_rule_row { Line 5481  sub loadbalance_rule_row {
             $checked = ' checked="checked"';              $checked = ' checked="checked"';
         }          }
         $output .= '<span class="LC_nobreak"><label>'.          $output .= '<span class="LC_nobreak"><label>'.
                    '<input type="radio" name="loadbalancing_rules_'.$type.                     '<input type="radio" name="loadbalancing_rules_'.$balnum.'_'.$type.
                    '" id="loadbalancing_rules_'.$type.'_'.$i.'" value="'.                     '" id="loadbalancing_rules_'.$balnum.'_'.$type.'_'.$i.'" value="'.
                    $rule.'" onclick="balanceruleChange('."this.form,'$type'".                     $rule.'" onclick="balanceruleChange('."this.form,'$balnum','$type'".
                    ')"'.$checked.' />&nbsp;'.$ruletitles{$rulenames[$i]}.                     ')"'.$checked.' />&nbsp;';
                    '</label>'.$extra.'</span><br />'."\n";          if (($rulenames[$i] eq 'specific') && ($type =~ /^_LC_ipchange/)) {
               $output .= $ruletitles{'particular'};
           } else {
               $output .= $ruletitles{$rulenames[$i]};
           }
           $output .= '</label>'.$extra.'</span><br />'."\n";
     }      }
     $output .= '</div></td></tr>'."\n";      $output .= '</div></td></tr>'."\n";
     return $output;      return $output;
Line 3069  sub offloadtype_text { Line 5503  sub offloadtype_text {
            'externalbalancer' => "Offloads to Load Balancer in user's domain",             'externalbalancer' => "Offloads to Load Balancer in user's domain",
            'specific'         => 'Offloads to specific server',             'specific'         => 'Offloads to specific server',
            'none'             => 'No offload',             'none'             => 'No offload',
              'balancer'         => 'Session hosted on Load Balancer, after re-authentication',
              'offloadedto'      => 'Session hosted on offload server, after re-authentication',
              'particular'       => 'Session hosted (after re-auth) on server:',
     );      );
     return %ruletitles;      return %ruletitles;
 }  }
Line 3083  sub sparestype_titles { Line 5520  sub sparestype_titles {
   
 sub contact_titles {  sub contact_titles {
     my %titles = &Apache::lonlocal::texthash (      my %titles = &Apache::lonlocal::texthash (
                    'supportemail' => 'Support E-mail address',                     'supportemail'    => 'Support E-mail address',
                    'adminemail'   => 'Default Server Admin E-mail address',                     'adminemail'      => 'Default Server Admin E-mail address',
                    'errormail'    => 'Error reports to be e-mailed to',                     'errormail'       => 'Error reports to be e-mailed to',
                    'packagesmail' => 'Package update alerts to be e-mailed to',                     'packagesmail'    => 'Package update alerts to be e-mailed to',
                    'helpdeskmail' => 'Helpdesk requests to be e-mailed to',                     'helpdeskmail'    => "Helpdesk requests for this domain's users",
                    'lonstatusmail' => 'E-mail from nightly status check (warnings/errors)',                     'otherdomsmail'   => 'Helpdesk requests for other (unconfigured) domains',
                    'requestsmail' => 'E-mail from course requests requiring approval',                     'lonstatusmail'   => 'E-mail from nightly status check (warnings/errors)',
                      'requestsmail'    => 'E-mail from course requests requiring approval',
                      'updatesmail'     => 'E-mail from nightly check of LON-CAPA module integrity/updates',
                      'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID',
                  );                   );
     my %short_titles = &Apache::lonlocal::texthash (      my %short_titles = &Apache::lonlocal::texthash (
                            adminemail   => 'Admin E-mail address',                             adminemail   => 'Admin E-mail address',
Line 3098  sub contact_titles { Line 5538  sub contact_titles {
     return (\%titles,\%short_titles);      return (\%titles,\%short_titles);
 }  }
   
   sub helpform_fields {
       my %titles =  &Apache::lonlocal::texthash (
                          'username'   => 'Name',
                          'user'       => 'Username/domain',
                          'phone'      => 'Phone',
                          'cc'         => 'Cc e-mail',
                          'course'     => 'Course Details',
                          'section'    => 'Sections',
                          'screenshot' => 'File upload',
       );
       my @fields = ('username','phone','user','course','section','cc','screenshot');
       my %possoptions = (
                           username     => ['yes','no','req'],
                           phone        => ['yes','no','req'],
                           user         => ['yes','no'],
                           cc           => ['yes','no'],
                           course       => ['yes','no'],
                           section      => ['yes','no'],
                           screenshot   => ['yes','no'],
                         );
       my %fieldoptions = &Apache::lonlocal::texthash (
                            'yes'  => 'Optional',
                            'req'  => 'Required',
                            'no'   => "Not shown",
       );
       return (\@fields,\%titles,\%fieldoptions,\%possoptions);
   }
   
 sub tool_titles {  sub tool_titles {
     my %titles = &Apache::lonlocal::texthash (      my %titles = &Apache::lonlocal::texthash (
                      aboutme    => 'Personal web page',                       aboutme    => 'Personal web page',
Line 3107  sub tool_titles { Line 5575  sub tool_titles {
                      official   => 'Official courses (with institutional codes)',                       official   => 'Official courses (with institutional codes)',
                      unofficial => 'Unofficial courses',                       unofficial => 'Unofficial courses',
                      community  => 'Communities',                       community  => 'Communities',
                        textbook   => 'Textbook courses',
                        placement  => 'Placement tests',
                  );                   );
     return %titles;      return %titles;
 }  }
Line 3116  sub courserequest_titles { Line 5586  sub courserequest_titles {
                                    official   => 'Official',                                     official   => 'Official',
                                    unofficial => 'Unofficial',                                     unofficial => 'Unofficial',
                                    community  => 'Communities',                                     community  => 'Communities',
                                      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 3137  sub authorrequest_titles { Line 5609  sub authorrequest_titles {
 sub courserequest_conditions {  sub courserequest_conditions {
     my %conditions = &Apache::lonlocal::texthash (      my %conditions = &Apache::lonlocal::texthash (
        approval    => '(Processing of request subject to approval by Domain Coordinator).',         approval    => '(Processing of request subject to approval by Domain Coordinator).',
        validate   => '(Processing of request subject to instittutional validation).',         validate   => '(Processing of request subject to institutional validation).',
                  );                   );
     return %conditions;      return %conditions;
 }  }
Line 3168  sub print_usercreation { Line 5640  sub print_usercreation {
                 $rowcount ++;                  $rowcount ++;
             }              }
         }          }
         my ($emailrules,$emailruleorder) =   
             &Apache::lonnet::inst_userrules($dom,'email');  
         if (ref($emailrules) eq 'HASH') {  
             if (keys(%{$emailrules}) > 0) {  
                 $datatable .= &user_formats_row('email',$settings,$emailrules,  
                                                 $emailruleorder,$numinrow,$rowcount);  
                 $$rowtotal ++;  
                 $rowcount ++;  
             }  
         }  
         if ($rowcount == 0) {          if ($rowcount == 0) {
             $datatable .= '<tr><td colspan="2">'.&mt('No format rules have been defined for usernames or IDs in this domain.').'</td></tr>';                $datatable .= '<tr><td colspan="2">'.&mt('No format rules have been defined for usernames or IDs in this domain.').'</td></tr>';  
             $$rowtotal ++;              $$rowtotal ++;
             $rowcount ++;              $rowcount ++;
         }          }
     } elsif ($position eq 'middle') {      } elsif ($position eq 'middle') {
         my @creators = ('author','course','requestcrs','selfcreate');          my @creators = ('author','course','requestcrs');
         my ($rules,$ruleorder) =          my ($rules,$ruleorder) =
             &Apache::lonnet::inst_userrules($dom,'username');              &Apache::lonnet::inst_userrules($dom,'username');
         my %lt = &usercreation_types();          my %lt = &usercreation_types();
         my %checked;          my %checked;
         my @selfcreate;   
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if (ref($settings->{'cancreate'}) eq 'HASH') {              if (ref($settings->{'cancreate'}) eq 'HASH') {
                 foreach my $item (@creators) {                  foreach my $item (@creators) {
                     $checked{$item} = $settings->{'cancreate'}{$item};                      $checked{$item} = $settings->{'cancreate'}{$item};
                 }                  }
                 if (ref($settings->{'cancreate'}{'selfcreate'}) eq 'ARRAY') {  
                     @selfcreate = @{$settings->{'cancreate'}{'selfcreate'}};  
                 } elsif ($settings->{'cancreate'}{'selfcreate'} ne '') {  
                     if ($settings->{'cancreate'}{'selfcreate'} eq 'any') {  
                         @selfcreate = ('email','login','sso');  
                     } elsif ($settings->{'cancreate'}{'selfcreate'} ne 'none') {  
                         @selfcreate = ($settings->{'cancreate'}{'selfcreate'});  
                     }  
                 }  
             } elsif (ref($settings->{'cancreate'}) eq 'ARRAY') {              } elsif (ref($settings->{'cancreate'}) eq 'ARRAY') {
                 foreach my $item (@creators) {                  foreach my $item (@creators) {
                     if (grep(/^\Q$item\E$/,@{$settings->{'cancreate'}})) {                      if (grep(/^\Q$item\E$/,@{$settings->{'cancreate'}})) {
Line 3215  sub print_usercreation { Line 5667  sub print_usercreation {
         my $rownum = 0;          my $rownum = 0;
         foreach my $item (@creators) {          foreach my $item (@creators) {
             $rownum ++;              $rownum ++;
             if ($item ne 'selfcreate') {                if ($checked{$item} eq '') {
                 if ($checked{$item} eq '') {                  $checked{$item} = 'any';
                     $checked{$item} = 'any';  
                 }  
             }              }
             my $css_class;              my $css_class;
             if ($rownum%2) {              if ($rownum%2) {
Line 3229  sub print_usercreation { Line 5679  sub print_usercreation {
             $datatable .= '<tr'.$css_class.'>'.              $datatable .= '<tr'.$css_class.'>'.
                          '<td><span class="LC_nobreak">'.$lt{$item}.                           '<td><span class="LC_nobreak">'.$lt{$item}.
                          '</span></td><td align="right">';                           '</span></td><td align="right">';
             my @options;              my @options = ('any');
             if ($item eq 'selfcreate') {              if (ref($rules) eq 'HASH') {
                 push(@options,('email','login','sso'));                  if (keys(%{$rules}) > 0) {
             } else {                      push(@options,('official','unofficial'));
                 @options = ('any');  
                 if (ref($rules) eq 'HASH') {  
                     if (keys(%{$rules}) > 0) {  
                         push(@options,('official','unofficial'));  
                     }  
                 }                  }
                 push(@options,'none');  
             }              }
               push(@options,'none');
             foreach my $option (@options) {              foreach my $option (@options) {
                 my $type = 'radio';                  my $type = 'radio';
                 my $check = ' ';                  my $check = ' ';
                 if ($item eq 'selfcreate') {                  if ($checked{$item} eq $option) {
                     $type = 'checkbox';                      $check = ' checked="checked" ';
                     if (grep(/^\Q$option\E$/,@selfcreate)) {  
                         $check = ' checked="checked" ';  
                     }  
                 } else {  
                     if ($checked{$item} eq $option) {  
                         $check = ' checked="checked" ';  
                     }  
                 }                   } 
                 $datatable .= '<span class="LC_nobreak"><label>'.                  $datatable .= '<span class="LC_nobreak"><label>'.
                               '<input type="'.$type.'" name="can_createuser_'.                                '<input type="'.$type.'" name="can_createuser_'.
Line 3261  sub print_usercreation { Line 5699  sub print_usercreation {
             }              }
             $datatable .= '</td></tr>';              $datatable .= '</td></tr>';
         }          }
         my ($othertitle,$usertypes,$types) =  
             &Apache::loncommon::sorted_inst_types($dom);  
         my $createsettings;  
         if (ref($settings) eq 'HASH') {  
             $createsettings = $settings->{cancreate};  
         }  
         if (ref($usertypes) eq 'HASH') {  
             if (keys(%{$usertypes}) > 0) {  
                 $datatable .= &insttypes_row($createsettings,$types,$usertypes,  
                                              $dom,$numinrow,$othertitle,  
                                              'statustocreate');  
                 $$rowtotal ++;  
                 $rownum ++;  
             }  
         }  
         $datatable .= &captcha_choice('cancreate',$createsettings,$rownum);  
     } else {      } else {
         my @contexts = ('author','course','domain');          my @contexts = ('author','course','domain');
         my @authtypes = ('int','krb4','krb5','loc');          my @authtypes = ('int','krb4','krb5','loc');
Line 3328  sub print_usercreation { Line 5750  sub print_usercreation {
     return $datatable;      return $datatable;
 }  }
   
   sub print_selfcreation {
       my ($position,$dom,$settings,$rowtotal) = @_;
       my (@selfcreate,$createsettings,$processing,$emailverified,$emaildomain,$datatable);
       if (ref($settings) eq 'HASH') {
           if (ref($settings->{'cancreate'}) eq 'HASH') {
               $createsettings = $settings->{'cancreate'};
               if (ref($createsettings) eq 'HASH') {
                   if (ref($createsettings->{'selfcreate'}) eq 'ARRAY') {
                       @selfcreate = @{$createsettings->{'selfcreate'}};
                   } elsif ($createsettings->{'selfcreate'} ne '') {
                       if ($settings->{'cancreate'}{'selfcreate'} eq 'any') {
                           @selfcreate = ('email','login','sso');
                       } elsif ($createsettings->{'selfcreate'} ne 'none') {
                           @selfcreate = ($createsettings->{'selfcreate'});
                       }
                   }
                   if (ref($createsettings->{'selfcreateprocessing'}) eq 'HASH') {
                       $processing = $createsettings->{'selfcreateprocessing'};
                   }
                   if (ref($createsettings->{'emailverified'}) eq 'HASH') {
                       $emailverified = $createsettings->{'emailverified'};
                   }
                   if (ref($createsettings->{'emaildomain'}) eq 'HASH') {
                       $emaildomain = $createsettings->{'emaildomain'};
                   }
               }
           }
       }
       my %radiohash;
       my $numinrow = 4;
       map { $radiohash{'cancreate_'.$_} = 1; } @selfcreate;
       my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
       if ($position eq 'top') {
           my %choices = &Apache::lonlocal::texthash (
                                                         cancreate_login      => 'Institutional Login',
                                                         cancreate_sso        => 'Institutional Single Sign On',
                                                     );
           my @toggles = sort(keys(%choices));
           my %defaultchecked = (
                                  'cancreate_login' => 'off',
                                  'cancreate_sso'   => 'off',
                                );
           my ($onclick,$itemcount);
           ($datatable,$itemcount) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,
                                                        \%choices,$itemcount,$onclick);
           $$rowtotal += $itemcount;
           
           if (ref($usertypes) eq 'HASH') {
               if (keys(%{$usertypes}) > 0) {
                   $datatable .= &insttypes_row($createsettings,$types,$usertypes,
                                                $dom,$numinrow,$othertitle,
                                                'statustocreate',$$rowtotal);
                   $$rowtotal ++;
               }
           }
           my @fields = ('lastname','firstname','middlename','permanentemail','id','inststatus');
           my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
           $fieldtitles{'inststatus'} = &mt('Institutional status');
           my $rem;
           my $numperrow = 2;
           my $css_class = $$rowtotal%2?' class="LC_odd_row"':'';
           $datatable .= '<tr'.$css_class.'>'.
                        '<td class="LC_left_item">'.&mt('Mapping of Shibboleth environment variable names to user data fields (SSO auth)').'</td>'.
                        '<td class="LC_left_item">'."\n".
                        '<table><tr><td>'."\n";
           for (my $i=0; $i<@fields; $i++) {
               $rem = $i%($numperrow);
               if ($rem == 0) {
                   if ($i > 0) {
                       $datatable .= '</tr>';
                   }
                   $datatable .= '<tr>';
               }
               my $currval;
               if (ref($createsettings) eq 'HASH') {
                   if (ref($createsettings->{'shibenv'}) eq 'HASH') {
                       $currval = $createsettings->{'shibenv'}{$fields[$i]};
                   }
               }
               $datatable .= '<td class="LC_left_item">'.
                             '<span class="LC_nobreak">'.
                             '<input type="text" name="shibenv_'.$fields[$i].'" '.
                             'value="'.$currval.'" size="10" />&nbsp;'.
                             $fieldtitles{$fields[$i]}.'</span></td>';
           }
           my $colsleft = $numperrow - $rem;
           if ($colsleft > 1 ) {
               $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                            '&nbsp;</td>';
           } elsif ($colsleft == 1) {
               $datatable .= '<td class="LC_left_item">&nbsp;</td>';
           }
           $datatable .= '</tr></table></td></tr>';
           $$rowtotal ++;
       } elsif ($position eq 'middle') {
           my %domconf = &Apache::lonnet::get_dom('configuration',['usermodification'],$dom);
           my @posstypes;
           if (ref($types) eq 'ARRAY') {
               @posstypes = @{$types};
           }
           unless (grep(/^default$/,@posstypes)) {
               push(@posstypes,'default');
           }
           my %usertypeshash;
           if (ref($usertypes) eq 'HASH') {
               %usertypeshash = %{$usertypes};
           }
           $usertypeshash{'default'} = $othertitle;
           foreach my $status (@posstypes) {
               $datatable .= &modifiable_userdata_row('selfcreate',$status,$domconf{'usermodification'},
                                                      $numinrow,$$rowtotal,\%usertypeshash);
               $$rowtotal ++;
           }
       } else {
           my %choices = &Apache::lonlocal::texthash (
                                                         cancreate_email => 'Non-institutional username (e-mail verification)',
                                                     );
           my @toggles = sort(keys(%choices));
           my %defaultchecked = (
                                  'cancreate_email' => 'off',
                                );
           my $itemcount = 0;
           my $display = 'none';
           if (grep(/^\Qemail\E$/,@selfcreate)) {
               $display = 'block';
           }
           my $onclick = "toggleDisplay(this.form,'emailoptions');";
           my $additional = '<div id="emailoptions" style="display: '.$display.'">';
           my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
           my $order;
           if (ref($domdefaults{'inststatusguest'}) eq 'ARRAY') {
               $order = $domdefaults{'inststatusguest'};
           }
           my (@ordered,%usertypeshash);
           if (ref($order) eq 'ARRAY') {
               @ordered = @{$order};
           }
           if (@ordered) {
               unless (grep(/^default$/,@ordered)) {
                   push(@ordered,'default');
               }
               if (ref($usertypes) eq 'HASH') {
                   %usertypeshash = %{$usertypes};
               }
               $usertypeshash{'default'} = $othertitle;
               $additional .= '<table><tr>';
               foreach my $status (@ordered) {
                   $additional .= '<th align="center">'.$usertypeshash{$status}.'</th>';
               }
               $additional .= '</tr><tr>';
               foreach my $status (@ordered) {
                   $additional .= '<td align="left" valign="top">'.&validate_by_email($rowtotal,$processing,$status).'</td>';
               }
               $additional .= '</tr></table><br />'.
                              '<table><tr>';
               foreach my $status (@ordered) {
                   $additional .= '<th align="center">'.$usertypeshash{$status}.'</th>';
               }
               $additional .= '</tr><tr>';
               foreach my $status (@ordered) {
                   $additional .= '<td align="left" valign="top">'.&email_as_username($rowtotal,$emailverified,$emaildomain,$status).'</td>';
               }
               $additional .= '</tr></table>';
     
           } else {
               $usertypeshash{'default'} = $othertitle;
               $additional .= &mt('Approval:').' '.&validate_by_email($rowtotal,$processing).'<br />'.
                              &mt('Username:').' '.&email_as_username($rowtotal,$emailverified,$emaildomain);
           }
           $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();
           $numinrow = 1;
           foreach my $status (@ordered) {
               $datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,
                                                      $numinrow,$$rowtotal,\%usertypeshash,$infofields,$infotitles);
               $$rowtotal ++;
           }
           my ($emailrules,$emailruleorder) =
               &Apache::lonnet::inst_userrules($dom,'email');
           if (ref($emailrules) eq 'HASH') {
               if (keys(%{$emailrules}) > 0) {
                   $datatable .= &user_formats_row('email',$settings,$emailrules,
                                                   $emailruleorder,$numinrow,$$rowtotal);
                   $$rowtotal ++;
               }
           }
           $datatable .= &captcha_choice('cancreate',$createsettings,$$rowtotal);
       }
       return $datatable;
   }
   
   sub validate_by_email {
       my ($rowtotal,$processing,$type) = @_;
       my %choices =
           &Apache::lonlocal::texthash (
                                         automatic => 'Automatic approval',
                                         approval  => 'Queued for approval',
                                         notinuse  => 'Unavailable',
                                       );
       my $output;
       my @options = ('automatic','approval');
       unless ($type eq '') {
           push(@options,'notinuse');
       }
       foreach my $option (@options) {
           my $checked;
           if (ref($processing) eq 'HASH') {
               if ($type eq '') {   
                   if (!exists($processing->{'default'})) {
                       if ($option eq 'automatic') {
                           $checked = ' checked="checked"';
                       }
                   } else {
                       if ($processing->{'default'} eq $option) {
                           $checked = ' checked="checked"';
                       }
                   }
               } else {
                   if (!exists($processing->{$type})) {
                       if ($option eq 'automatic') {
                           $checked = ' checked="checked"';
                       }
                   } else {
                       if ($processing->{$type} eq $option) {
                           $checked = ' checked="checked"';
                       }
                   }
               }
           } 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 />';
           }
       }
       $$rowtotal ++;
       return $output;
   }
   
   sub email_as_username {
       my ($rowtotal,$emailverified,$emaildomain,$type) = @_;
       my %choices =
           &Apache::lonlocal::texthash (
                                         email => 'Username is e-mail',
                                         other => 'Username is chosen',
                                       );
       my $name = 'cancreate_emailverified';
       my $condition = 'cancreate_emaildomain';
       if (($type ne '') && ($type ne 'default')) {
           $name .= '_'.$type;
           $condition .= '_'.$type;
       }
       my $display = 'none';
       my $onclick = "toggleDisplay(this.form,'$name');";
   
       my $output;
       foreach my $option ('email','other') {
           my ($checked,$domain);
           if (ref($emailverified) eq 'HASH') {
               if ($type eq '') {
                   if (!exists($emailverified->{'default'})) {
                       if ($option eq 'email') {
                           $checked = ' checked="checked"';
                       }
                   } else {
                       if ($emailverified->{'default'} eq $option) {
                           $checked = ' checked="checked"';
                       }
                   }
               } else {
                   if (!exists($emailverified->{$type})) {
                       if ($option eq 'email') {
                           $checked = ' checked="checked"';
                       }
                   } else {
                       if ($emailverified->{$type} eq $option) {
                           $checked = ' checked="checked"';
                           if ($option eq 'other') {
                               $display = 'inline';
                           }
                       }
                   }
               }
           } elsif ($option eq 'email') {
               $checked = ' checked="checked"';
           }
           $output .= '<span class="LC_nobreak"><label>'.
                      '<input type="radio" name="'.$name.'"'.
                      $checked.' value="'.$option.'" onclick="'.$onclick.'" />'.
                      $choices{$option}.'</label></span>';
           if ($type eq '') {
               $output .= '&nbsp;';
           } else {
               $output .= '<br />';
           }
       }
       my $domain;
       if (ref($emaildomain) eq 'HASH') {
           if ($type eq '') {
               if (exists($emaildomain->{'default'})) {
                   $domain = $emaildomain->{'default'};
               }
           } else {
               if (exists($emaildomain->{$type})) {
                   $domain = $emaildomain->{$type};
               }
           }
       }
       $output .= '<div id="'.$name.'" style="display: '.$display.';">'.
                  '<span class="LC_domprefs_email">'.&mt('E-mail domain').'</span> '.
                  '<input type="text" name="'.$condition.'" value="'.$domain.'" size="10" />'.
                  '</div>';
       $$rowtotal ++;
       return $output;
   }
   
 sub captcha_choice {  sub captcha_choice {
     my ($context,$settings,$itemcount) = @_;      my ($context,$settings,$itemcount) = @_;
     my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext);      my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext,
           $vertext,$currver);
     my %lt = &captcha_phrases();      my %lt = &captcha_phrases();
     $keyentry = 'hidden';      $keyentry = 'hidden';
     if ($context eq 'cancreate') {      if ($context eq 'cancreate') {
         $rowname = &mt('CAPTCHA validation (e-mail as username)');          $rowname = &mt('CAPTCHA validation');
     } elsif ($context eq 'login') {      } elsif ($context eq 'login') {
         $rowname =  &mt('"Contact helpdesk" CAPTCHA validation');          $rowname =  &mt('"Contact helpdesk" CAPTCHA validation');
     }      }
Line 3348  sub captcha_choice { Line 6103  sub captcha_choice {
             $pubtext = $lt{'pub'};              $pubtext = $lt{'pub'};
             $privtext = $lt{'priv'};              $privtext = $lt{'priv'};
             $keyentry = 'text';              $keyentry = 'text';
               $vertext = $lt{'ver'};
               $currver = $settings->{'recaptchaversion'};
               if ($currver ne '2') {
                   $currver = 1;
               }
         }          }
         if (ref($settings->{'recaptchakeys'}) eq 'HASH') {          if (ref($settings->{'recaptchakeys'}) eq 'HASH') {
             $currpub = $settings->{'recaptchakeys'}{'public'};              $currpub = $settings->{'recaptchakeys'}{'public'};
Line 3381  sub captcha_choice { Line 6141  sub captcha_choice {
                $currpub.'" size="40" /></span><br />'."\n".                 $currpub.'" size="40" /></span><br />'."\n".
                '<span class="LC_nobreak"><span id="'.$context.'_recaptchaprivtxt">'.$privtext.'</span>&nbsp;'."\n".                 '<span class="LC_nobreak"><span id="'.$context.'_recaptchaprivtxt">'.$privtext.'</span>&nbsp;'."\n".
                '<input type="'.$keyentry.'" id="'.$context.'_recaptchapriv" name="'.$context.'_recaptchapriv" value="'.                 '<input type="'.$keyentry.'" id="'.$context.'_recaptchapriv" name="'.$context.'_recaptchapriv" value="'.
                $currpriv.'" size="40" /></span></td></tr></table>'."\n".                 $currpriv.'" size="40" /></span><br />'.
                  '<span class="LC_nobreak"><span id="'.$context.'_recaptchavertxt">'.$vertext.'</span>&nbsp;'."\n".
                  '<input type="'.$keyentry.'" id="'.$context.'_recaptchaversion" name="'.$context.'_recaptchaversion" value="'.
                  $currver.'" size="3" /></span><br />'.
                  '</td></tr></table>'."\n".
                '</td></tr>';                 '</td></tr>';
     return $output;      return $output;
 }  }
Line 3448  sub usercreation_types { Line 6212  sub usercreation_types {
                     author     => 'When adding a co-author',                      author     => 'When adding a co-author',
                     course     => 'When adding a user to a course',                      course     => 'When adding a user to a course',
                     requestcrs => 'When requesting a course',                      requestcrs => 'When requesting a course',
                     selfcreate => 'User creates own account',   
                     any        => 'Any',                      any        => 'Any',
                     official   => 'Institutional only ',                      official   => 'Institutional only ',
                     unofficial => 'Non-institutional only',                      unofficial => 'Non-institutional only',
                     email      => 'E-mail address',  
                     login      => 'Institutional Login',  
                     sso        => 'SSO',   
                     none       => 'None',                      none       => 'None',
     );      );
     return %lt;      return %lt;
 }  }
   
   sub selfcreation_types {
       my %lt = &Apache::lonlocal::texthash (
                       selfcreate => 'User creates own account',
                       any        => 'Any',
                       official   => 'Institutional only ',
                       unofficial => 'Non-institutional only',
                       email      => 'E-mail address',
                       login      => 'Institutional Login',
                       sso        => 'SSO',
                );
   }
   
 sub authtype_names {  sub authtype_names {
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
                       int    => 'Internal',                        int    => 'Internal',
Line 3492  sub print_usermodification { Line 6264  sub print_usermodification {
             $$rowtotal ++;              $$rowtotal ++;
             $rowcount ++;              $rowcount ++;
         }          }
     } elsif ($position eq 'middle') {      } elsif ($position eq 'bottom') {
         $context = 'course';          $context = 'course';
         $rowcount = 0;          $rowcount = 0;
         foreach my $role ('st','ep','ta','in','cr') {          foreach my $role ('st','ep','ta','in','cr') {
Line 3501  sub print_usermodification { Line 6273  sub print_usermodification {
             $$rowtotal ++;              $$rowtotal ++;
             $rowcount ++;              $rowcount ++;
         }          }
     } elsif ($position eq 'bottom') {  
         $context = 'selfcreate';  
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
         $usertypes->{'default'} = $othertitle;  
         if (ref($types) eq 'ARRAY') {  
             push(@{$types},'default');  
             $usertypes->{'default'} = $othertitle;  
             foreach my $status (@{$types}) {  
                 $datatable .= &modifiable_userdata_row($context,$status,$settings,  
                                                        $numinrow,$rowcount,$usertypes);  
                 $$rowtotal ++;  
                 $rowcount ++;  
             }  
         }  
     }      }
     return $datatable;      return $datatable;
 }  }
   
 sub print_defaults {  sub print_defaults {
     my ($dom,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my @items = ('auth_def','auth_arg_def','lang_def','timezone_def',  
                  'datelocale_def','portal_def');  
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);  
     my $titles = &defaults_titles($dom);  
     my $rownum = 0;      my $rownum = 0;
     my ($datatable,$css_class);      my ($datatable,$css_class,$titles);
     foreach my $item (@items) {      unless ($position eq 'bottom') {
         if ($rownum%2) {          $titles = &defaults_titles($dom);
             $css_class = '';      }
       if ($position eq 'top') {
           my @items = ('auth_def','auth_arg_def','lang_def','timezone_def',
                        'datelocale_def','portal_def');
           my %defaults;
           if (ref($settings) eq 'HASH') {
               %defaults = %{$settings};
         } else {          } else {
             $css_class = ' class="LC_odd_row" ';              my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
               foreach my $item (@items) {
                   $defaults{$item} = $domdefaults{$item};
               }
         }          }
         $datatable .= '<tr'.$css_class.'>'.          foreach my $item (@items) {
                   '<td><span class="LC_nobreak">'.$titles->{$item}.              if ($rownum%2) {
                   '</span></td><td class="LC_right_item">';                  $css_class = '';
         if ($item eq 'auth_def') {              } else {
             my @authtypes = ('internal','krb4','krb5','localauth');                  $css_class = ' class="LC_odd_row" ';
             my %shortauth = (  
                              internal => 'int',  
                              krb4 => 'krb4',  
                              krb5 => 'krb5',  
                              localauth  => 'loc'  
                            );  
             my %authnames = &authtype_names();  
             foreach my $auth (@authtypes) {  
                 my $checked = ' ';  
                 if ($domdefaults{$item} eq $auth) {  
                     $checked = ' checked="checked" ';  
                 }  
                 $datatable .= '<label><input type="radio" name="'.$item.  
                               '" value="'.$auth.'"'.$checked.'/>'.  
                               $authnames{$shortauth{$auth}}.'</label>&nbsp;&nbsp;';  
             }              }
         } elsif ($item eq 'timezone_def') {              $datatable .= '<tr'.$css_class.'>'.
             my $includeempty = 1;                            '<td><span class="LC_nobreak">'.$titles->{$item}.
             $datatable .= &Apache::loncommon::select_timezone($item,$domdefaults{$item},undef,$includeempty);                            '</span></td><td class="LC_right_item" colspan="3">';
         } elsif ($item eq 'datelocale_def') {              if ($item eq 'auth_def') {
             my $includeempty = 1;                  my @authtypes = ('internal','krb4','krb5','localauth');
             $datatable .= &Apache::loncommon::select_datelocale($item,$domdefaults{$item},undef,$includeempty);                  my %shortauth = (
         } elsif ($item eq 'lang_def') {                                   internal => 'int',
             my %langchoices = &get_languages_hash();                                   krb4 => 'krb4',
             $langchoices{''} = 'No language preference';                                   krb5 => 'krb5',
             %langchoices = &Apache::lonlocal::texthash(%langchoices);                                   localauth  => 'loc'
             $datatable .= &Apache::loncommon::select_form($domdefaults{$item},$item,                                  );
                                                           \%langchoices);                  my %authnames = &authtype_names();
         } else {                  foreach my $auth (@authtypes) {
             my $size;                      my $checked = ' ';
             if ($item eq 'portal_def') {                      if ($defaults{$item} eq $auth) {
                 $size = ' size="25"';                          $checked = ' checked="checked" ';
                       }
                       $datatable .= '<label><input type="radio" name="'.$item.
                                     '" value="'.$auth.'"'.$checked.'/>'.
                                     $authnames{$shortauth{$auth}}.'</label>&nbsp;&nbsp;';
                   }
               } elsif ($item eq 'timezone_def') {
                   my $includeempty = 1;
                   $datatable .= &Apache::loncommon::select_timezone($item,$defaults{$item},undef,$includeempty);
               } elsif ($item eq 'datelocale_def') {
                   my $includeempty = 1;
                   $datatable .= &Apache::loncommon::select_datelocale($item,$defaults{$item},undef,$includeempty);
               } elsif ($item eq 'lang_def') {
                   my $includeempty = 1;
                   $datatable .= &Apache::loncommon::select_language($item,$defaults{$item},$includeempty);
               } else {
                   my $size;
                   if ($item eq 'portal_def') {
                       $size = ' size="25"';
                   }
                   $datatable .= '<input type="text" name="'.$item.'" value="'.
                                 $defaults{$item}.'"'.$size.' />';
               }
               $datatable .= '</td></tr>';
               $rownum ++;
           }
       } elsif ($position eq 'middle') {
           my @items = ('intauth_cost','intauth_check','intauth_switch');
           my %defaults;
           if (ref($settings) eq 'HASH') {
               %defaults = %{$settings};
               if ($defaults{'intauth_cost'} !~ /^\d+$/) {
                   $defaults{'intauth_cost'} = 10;
               }
               if ($defaults{'intauth_check'} !~ /^(0|1|2)$/) {
                   $defaults{'intauth_check'} = 0;
               }
               if ($defaults{'intauth_switch'} !~ /^(0|1|2)$/) {
                   $defaults{'intauth_switch'} = 0;
               }
           } else {
               %defaults = (
                             'intauth_cost'   => 10,
                             'intauth_check'  => 0,
                             'intauth_switch' => 0,
                           );
           }
           foreach my $item (@items) {
               if ($rownum%2) {
                   $css_class = '';
               } else {
                   $css_class = ' class="LC_odd_row" ';
               }
               $datatable .= '<tr'.$css_class.'>'.
                             '<td><span class="LC_nobreak">'.$titles->{$item}.
                             '</span></td><td class="LC_left_item" colspan="3">';
               if ($item eq 'intauth_switch') {
                   my @options = (0,1,2);
                   my %optiondesc = &Apache::lonlocal::texthash (
                                      0 => 'No',
                                      1 => 'Yes',
                                      2 => 'Yes, and copy existing passwd file to passwd.bak file',
                                    );
                   $datatable .= '<table width="100%">';
                   foreach my $option (@options) {
                       my $checked = ' ';
                       if ($defaults{$item} eq $option) {
                           $checked = ' checked="checked"';
                       }
                       $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.
                                     '<label><input type="radio" name="'.$item.
                                     '" value="'.$option.'"'.$checked.' />'.
                                     $optiondesc{$option}.'</label></span></td></tr>';
                   }
                   $datatable .= '</table>';
               } elsif ($item eq 'intauth_check') {
                   my @options = (0,1,2);
                   my %optiondesc = &Apache::lonlocal::texthash (
                                      0 => 'No',
                                      1 => 'Yes, allow login then update passwd file using default cost (if higher)',
                                      2 => 'Yes, disallow login if stored cost is less than domain default',
                                    );
                   $datatable .= '<table wisth="100%">';
                   foreach my $option (@options) {
                       my $checked = ' ';
                       my $onclick;
                       if ($defaults{$item} eq $option) {
                           $checked = ' checked="checked"';
                       }
                       if ($option == 2) {
                           $onclick = ' onclick="javascript:warnIntAuth(this);"';
                       }
                       $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.
                                     '<label><input type="radio" name="'.$item.
                                     '" value="'.$option.'"'.$checked.$onclick.' />'.
                                     $optiondesc{$option}.'</label></span></td></tr>';
                   }
                   $datatable .= '</table>';
               } else {
                   $datatable .= '<input type="text" name="'.$item.'" value="'.
                                 $defaults{$item}.'" size="3" onblur="javascript:warnIntAuth(this);" />'; 
               }
               $datatable .= '</td></tr>';
               $rownum ++;
           }
       } else {
           my %defaults;
           if (ref($settings) eq 'HASH') {
               if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH') &&
                   (ref($settings->{'inststatusguest'}) eq 'ARRAY')) {
                   my $maxnum = @{$settings->{'inststatusorder'}};
                   for (my $i=0; $i<$maxnum; $i++) {
                       $css_class = $rownum%2?' class="LC_odd_row"':'';
                       my $item = $settings->{'inststatusorder'}->[$i];
                       my $title = $settings->{'inststatustypes'}->{$item};
                       my $guestok;
                       if (grep(/^\Q$item\E$/,@{$settings->{'inststatusguest'}})) {
                           $guestok = 1;
                       }
                       my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'$item'".');"';
                       $datatable .= '<tr'.$css_class.'>'.
                                     '<td><span class="LC_nobreak">'.
                                     '<select name="inststatus_pos_'.$item.'"'.$chgstr.'>';
                       for (my $k=0; $k<=$maxnum; $k++) {
                           my $vpos = $k+1;
                           my $selstr;
                           if ($k == $i) {
                               $selstr = ' selected="selected" ';
                           }
                           $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                       }
                       my ($checkedon,$checkedoff);
                       $checkedoff = ' checked="checked"';
                       if ($guestok) {
                           $checkedon = $checkedoff;
                           $checkedoff = ''; 
                       }
                       $datatable .= '</select>&nbsp;'.&mt('Internal ID:').'&nbsp;<b>'.$item.'</b>&nbsp;'.
                                     '<input type="checkbox" name="inststatus_delete" value="'.$item.'" />'.
                                     &mt('delete').'</span></td>'.
                                     '<td class="LC_left_item"><span class="LC_nobreak">'.&mt('Name displayed:').
                                     '<input type="text" size="20" name="inststatus_title_'.$item.'" value="'.$title.'" />'.
                                     '</span></td>'.
                                     '<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"':'';
                   my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'addinststatus_pos'".');"';
                   $datatable .= '<tr '.$css_class.'>'.
                                 '<td><span class="LC_nobreak"><select name="addinststatus_pos"'.$chgstr.'>';
                   for (my $k=0; $k<=$maxnum; $k++) {
                       my $vpos = $k+1;
                       my $selstr;
                       if ($k == $maxnum) {
                           $selstr = ' selected="selected" ';
                       }
                       $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                   }
                   $datatable .= '</select>&nbsp;'.&mt('Internal ID:').
                                 '<input type="text" size="10" name="addinststatus" value="" />'.
                                 '&nbsp;'.&mt('(new)').
                                 '</span></td><td class="LC_left_item"><span class="LC_nobreak">'.
                                 &mt('Name displayed:').
                                 '<input type="text" size="20" name="addinststatus_title" value="" /></span></td>'.
                                 '<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";
                   $rownum ++;
             }              }
             $datatable .= '<input type="text" name="'.$item.'" value="'.  
                           $domdefaults{$item}.'"'.$size.' />';  
         }          }
         $datatable .= '</td></tr>';  
         $rownum ++;  
     }      }
     $$rowtotal += $rownum;      $$rowtotal += $rownum;
     return $datatable;      return $datatable;
Line 3601  sub defaults_titles { Line 6518  sub defaults_titles {
                    'timezone_def'  => 'Default timezone',                     'timezone_def'  => 'Default timezone',
                    'datelocale_def' => 'Default locale for dates',                     'datelocale_def' => 'Default locale for dates',
                    'portal_def'     => 'Portal/Default URL',                     'portal_def'     => 'Portal/Default URL',
                      'intauth_cost'   => 'Encryption cost for bcrypt (positive integer)',
                      'intauth_check'  => 'Check bcrypt cost if authenticated',
                      'intauth_switch' => 'Existing crypt-based switched to bcrypt on authentication',
                  );                   );
     if ($dom) {      if ($dom) {
         my $uprimary_id = &Apache::lonnet::domain($dom,'primary');          my $uprimary_id = &Apache::lonnet::domain($dom,'primary');
Line 3724  sub print_scantronformat { Line 6644  sub print_scantronformat {
         $datatable .= '<td>'.&mt('Default in use:').'<br />'.          $datatable .= '<td>'.&mt('Default in use:').'<br />'.
                       '<span class="LC_nobreak">';                        '<span class="LC_nobreak">';
         if ($scantronurl) {          if ($scantronurl) {
             $datatable .= '<a href="'.$scantronurl.'" target="_blank">'.              $datatable .= &Apache::loncommon::modal_link($scantronurl,&mt('Default bubblesheet format file'),600,500,
                           &mt('Default bubblesheet format file').'</a>';                                                           undef,undef,undef,undef,'background-color:#ffffff');
         } else {          } else {
             $datatable = &mt('File unavailable for display');              $datatable = &mt('File unavailable for display');
         }          }
Line 3750  sub print_scantronformat { Line 6670  sub print_scantronformat {
             }               } 
             $datatable .= '<td>'.$errorstr.'</td><td>&nbsp;';              $datatable .= '<td>'.$errorstr.'</td><td>&nbsp;';
         } elsif ($scantronurl) {          } elsif ($scantronurl) {
               my $link =  &Apache::loncommon::modal_link($scantronurl,&mt('Custom bubblesheet format file'),600,500,
                                                          undef,undef,undef,undef,'background-color:#ffffff');
             $datatable .= '<td><span class="LC_nobreak">'.              $datatable .= '<td><span class="LC_nobreak">'.
                           '<a href="'.$scantronurl.'" target="_blank">'.                            $link.
                           &mt('Custom bubblesheet format file').'</a><label>'.                            '<label><input type="checkbox" name="scantronformat_del"'.
                           '<input type="checkbox" name="scantronformat_del"'.                            ' value="1" />'.&mt('Delete?').'</label></span></td>'.
                           '" value="1" />'.&mt('Delete?').'</label></span></td>'.  
                           '<td><span class="LC_nobreak">&nbsp;'.                            '<td><span class="LC_nobreak">&nbsp;'.
                           &mt('Replace:').'</span><br />';                            &mt('Replace:').'</span><br />';
         }          }
Line 3791  sub print_coursecategories { Line 6712  sub print_coursecategories {
     my ($position,$dom,$hdritem,$settings,$rowtotal) = @_;      my ($position,$dom,$hdritem,$settings,$rowtotal) = @_;
     my $datatable;      my $datatable;
     if ($position eq 'top') {      if ($position eq 'top') {
           my (%checked);
           my @catitems = ('unauth','auth');
           my @cattypes = ('std','domonly','codesrch','none');
           $checked{'unauth'} = 'std';
           $checked{'auth'} = 'std';
           if (ref($settings) eq 'HASH') {
               foreach my $type (@cattypes) {
                   if ($type eq $settings->{'unauth'}) {
                       $checked{'unauth'} = $type;
                   }
                   if ($type eq $settings->{'auth'}) {
                       $checked{'auth'} = $type;
                   }
               }
           }
           my %lt = &Apache::lonlocal::texthash (
                                                  unauth   => 'Catalog type for unauthenticated users',
                                                  auth     => 'Catalog type for authenticated users',
                                                  none     => 'No catalog',
                                                  std      => 'Standard catalog',
                                                  domonly  => 'Domain-only catalog',
                                                  codesrch => "Code search form",
                                                );
          my $itemcount = 0;
          foreach my $item (@catitems) {
              my $css_class = $itemcount%2? ' class="LC_odd_row"':'';
              $datatable .= '<tr '.$css_class.'>'.
                            '<td>'.$lt{$item}.'</td>'.
                            '<td class="LC_right_item"><span class="LC_nobreak">';
              foreach my $type (@cattypes) {
                  my $ischecked;
                  if ($checked{$item} eq $type) {
                      $ischecked=' checked="checked"';
                  }
                  $datatable .= '<label>'.
                                '<input type="radio" name="coursecat_'.$item.'" value="'.$type.'"'.$ischecked.
                                ' />'.$lt{$type}.'</label>&nbsp;';
              }
              $datatable .= '</td></tr>';
              $itemcount ++;
           }
           $$rowtotal += $itemcount;
       } elsif ($position eq 'middle') {
         my $toggle_cats_crs = ' ';          my $toggle_cats_crs = ' ';
         my $toggle_cats_dom = ' checked="checked" ';          my $toggle_cats_dom = ' checked="checked" ';
         my $can_cat_crs = ' ';          my $can_cat_crs = ' ';
Line 3799  sub print_coursecategories { Line 6763  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 3817  sub print_coursecategories { Line 6785  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 3857  sub print_coursecategories { Line 6836  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 3883  sub print_coursecategories { Line 6876  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 3908  sub print_coursecategories { Line 6904  sub print_coursecategories {
                             }                              }
                             $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';                              $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                         }                          }
                         $datatable .= '</select></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 3932  sub print_coursecategories { Line 6928  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>';
                         } else {                          } else {
                             $datatable .= $parent                              $datatable .= $parent
                                           .'&nbsp;<label><input type="checkbox" name="deletecategory" '                                            .'&nbsp;<span class="LC_nobreak"><label>'
                                             .'<input type="checkbox" name="deletecategory" '
                                           .'value="'.$item.'" />'.&mt('Delete').'</label></span></td>';                                            .'value="'.$item.'" />'.&mt('Delete').'</label></span></td>';
                         }                          }
                         my $depth = 1;                          my $depth = 1;
Line 3963  sub print_coursecategories { Line 6960  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 3996  sub print_coursecategories { Line 6993  sub print_coursecategories {
                 $datatable .= &initialize_categories($itemcount);                  $datatable .= &initialize_categories($itemcount);
             }              }
         } else {          } else {
             $datatable .= '<td class="LC_right_item">'.$hdritem->{'header'}->[0]->{'col2'}.'</td>'              $datatable .= '<td class="LC_right_item">'.$hdritem->{'header'}->[1]->{'col2'}.'</td>'
                           .&initialize_categories($itemcount);                            .&initialize_categories($itemcount);
         }          }
         $$rowtotal += $itemcount;          $$rowtotal += $itemcount;
Line 4052  sub print_serverstatuses { Line 7049  sub print_serverstatuses {
   
 sub serverstatus_pages {  sub serverstatus_pages {
     return ('userstatus','lonstatus','loncron','server-status','codeversions',      return ('userstatus','lonstatus','loncron','server-status','codeversions',
             'clusterstatus','metadata_keywords','metadata_harvest',              'checksums','clusterstatus','certstatus','metadata_keywords',
             'takeoffline','takeonline','showenv','toggledebug','ping','domconf');              'metadata_harvest','takeoffline','takeonline','showenv','toggledebug',
               'ping','domconf','uniquecodes','diskusage','coursecatalog');
   }
   
   sub defaults_javascript {
       my ($settings) = @_;
       my $intauthcheck = &mt('Warning: disallowing login for an authenticated user if the stored cost is less than the default will require a password reset by/for the user.');
       my $intauthcost = &mt('Warning: bcrypt encryption cost for internal authentication must be an integer.');
       &js_escape(\$intauthcheck);
       &js_escape(\$intauthcost);
       my $intauthjs = <<"ENDSCRIPT";
   
   function warnIntAuth(field) {
       if (field.name == 'intauth_check') {
           if (field.value == '2') {
               alert('$intauthcheck');
           }
       }
       if (field.name == 'intauth_cost') {
           field.value.replace(/\s/g,'');
           if (field.value != '') {
               var regexdigit=/^\\d+\$/;
               if (!regexdigit.test(field.value)) {
                   alert('$intauthcost');
               }
           }
       }
       return;
   }
   
   ENDSCRIPT
   
       if (ref($settings) ne 'HASH') {
           return &Apache::lonhtmlcommon::scripttag($intauthjs);
       }
       if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {
           my $maxnum = scalar(@{$settings->{'inststatusorder'}});
           if ($maxnum eq '') {
               $maxnum = 0;
           }
           $maxnum ++;
           my $jstext = '    var inststatuses = Array('."'".join("','",@{$settings->{'inststatusorder'}})."'".');';  
           return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   function reorderTypes(form,caller) {
       var changedVal;
   $jstext 
       var newpos = 'addinststatus_pos';
       var current = new Array;
       var maxh = $maxnum;
       var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
       var oldVal;
       if (caller == newpos) {
           changedVal = newitemVal;
       } else {
           var curritem = 'inststatus_pos_'+caller;
           changedVal = form.elements[curritem].options[form.elements[curritem].selectedIndex].value;
           current[newitemVal] = newpos;
       }
       for (var i=0; i<inststatuses.length; i++) {
           if (inststatuses[i] != caller) {
               var elementName = 'inststatus_pos_'+inststatuses[i];
               if (form.elements[elementName]) {
                   var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
                   current[currVal] = elementName;
               }
           }
       }
       for (var j=0; j<maxh; j++) {
           if (current[j] == undefined) {
               oldVal = j;
           }
       }
       if (oldVal < changedVal) {
           for (var k=oldVal+1; k<=changedVal ; k++) {
              var elementName = current[k];
              form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
           }
       } else {
           for (var k=changedVal; k<oldVal; k++) {
               var elementName = current[k];
               form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
           }
       }
       return;
   }
   
   $intauthjs
   
   // ]]>
   </script>
   
   ENDSCRIPT
       } else {
           return &Apache::lonhtmlcommon::scripttag($intauthjs);
       }
 }  }
   
 sub coursecategories_javascript {  sub coursecategories_javascript {
Line 4078  sub coursecategories_javascript { Line 7171  sub coursecategories_javascript {
         $jstext  = '    var categories = Array(1);'."\n".          $jstext  = '    var categories = Array(1);'."\n".
                    '    categories[0] = Array("instcode_pos");'."\n";                      '    categories[0] = Array("instcode_pos");'."\n"; 
     }      }
     my $instcode_reserved = &mt('The name: "instcode" is a reserved category');      my $instcode_reserved = &mt('The name: [_1] is a reserved category.','"instcode"');
     my $communities_reserved = &mt('The name: "communities" is a reserved category');      my $communities_reserved = &mt('The name: [_1] is a reserved category.','"communities"');
     my $choose_again = '\\n'.&mt('Please use a different name for the new top level category');       my $placement_reserved = &mt('The name: [_1] is a reserved category.','"placement"');
       my $choose_again = "\n".&mt('Please use a different name for the new top level category.'); 
       &js_escape(\$instcode_reserved);
       &js_escape(\$communities_reserved);
       &js_escape(\$placement_reserved);
       &js_escape(\$choose_again);
     $output = <<"ENDSCRIPT";      $output = <<"ENDSCRIPT";
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
Line 4088  function reorderCats(form,parent,item,id Line 7186  function reorderCats(form,parent,item,id
     var changedVal;      var changedVal;
 $jstext  $jstext
     var newpos = 'addcategory_pos';      var newpos = 'addcategory_pos';
     var current = new Array;  
     if (parent == '') {      if (parent == '') {
         var has_instcode = 0;          var has_instcode = 0;
         var maxtop = categories[idx].length;          var maxtop = categories[idx].length;
Line 4150  function categoryCheck(form) { Line 7247  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 4166  sub initialize_categories { Line 7267  sub initialize_categories {
     my %default_names = (      my %default_names = (
                       instcode    => 'Official courses (with institutional codes)',                        instcode    => 'Official courses (with institutional codes)',
                       communities => 'Communities',                        communities => 'Communities',
                         placement   => 'Placement Tests',
                         );                          );
     my $select0 = ' selected="selected"';      my $select0 = ' selected="selected"';
     my $select1 = '';      my $select1 = '';
     foreach my $default ('instcode','communities') {      foreach my $default ('instcode','communities','placement') {
         $css_class = $itemcount%2?' class="LC_odd_row"':'';          $css_class = $itemcount%2?' class="LC_odd_row"':'';
         $chgstr = ' onchange="javascript:reorderCats(this.form,'."'',$default"."_pos','0'".');"';          $chgstr = ' onchange="javascript:reorderCats(this.form,'."'',$default"."_pos','0'".');"';
         if ($default eq 'communities') {          if (($default eq 'communities') || ($default eq 'placement')) {
             $select1 = $select0;              $select1 = $select0;
             $select0 = '';              $select0 = '';
         }          }
Line 4210  sub build_category_rows { Line 7312  sub build_category_rows {
             if (ref($cats->[$depth]{$parent}) eq 'ARRAY') {              if (ref($cats->[$depth]{$parent}) eq 'ARRAY') {
                 my $numchildren = @{$cats->[$depth]{$parent}};                  my $numchildren = @{$cats->[$depth]{$parent}};
                 my $css_class = $itemcount%2?' class="LC_odd_row"':'';                  my $css_class = $itemcount%2?' class="LC_odd_row"':'';
                 $text .= '<td><table class="LC_datatable">';                  $text .= '<td><table class="LC_data_table">';
                 my ($idxnum,$parent_name,$parent_item);                  my ($idxnum,$parent_name,$parent_item);
                 my $higher = $depth - 1;                  my $higher = $depth - 1;
                 if ($higher == 0) {                  if ($higher == 0) {
Line 4284  sub build_category_rows { Line 7386  sub build_category_rows {
 }  }
   
 sub modifiable_userdata_row {  sub modifiable_userdata_row {
     my ($context,$role,$settings,$numinrow,$rowcount,$usertypes) = @_;      my ($context,$item,$settings,$numinrow,$rowcount,$usertypes,$fieldsref,$titlesref) = @_;
     my $rolename;      my ($role,$rolename,$statustype);
     if ($context eq 'selfcreate') {      $role = $item;
       if ($context eq 'cancreate') {
           if ($item =~ /^emailusername_(.+)$/) {
               $statustype = $1;
               $role = 'emailusername';
               if (ref($usertypes) eq 'HASH') {
                   if ($usertypes->{$statustype}) {
                       $rolename = &mt('Data provided by [_1]',$usertypes->{$statustype});
                   } else {
                       $rolename = &mt('Data provided by user');
                   }
               }
           }
       } elsif ($context eq 'selfcreate') {
         if (ref($usertypes) eq 'HASH') {          if (ref($usertypes) eq 'HASH') {
             $rolename = $usertypes->{$role};              $rolename = $usertypes->{$role};
         } else {          } else {
Line 4299  sub modifiable_userdata_row { Line 7414  sub modifiable_userdata_row {
             $rolename = &Apache::lonnet::plaintext($role);              $rolename = &Apache::lonnet::plaintext($role);
         }          }
     }      }
     my @fields = ('lastname','firstname','middlename','generation',      my (@fields,%fieldtitles);
                   'permanentemail','id');      if (ref($fieldsref) eq 'ARRAY') {
     my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();          @fields = @{$fieldsref};
       } else {
           @fields = ('lastname','firstname','middlename','generation',
                      'permanentemail','id');
       }
       if ((ref($titlesref) eq 'HASH')) {
           %fieldtitles = %{$titlesref};
       } else {
           %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
       }
     my $output;      my $output;
     my $css_class = $rowcount%2?' class="LC_odd_row"':'';      my $css_class = $rowcount%2?' class="LC_odd_row"':'';
     $output = '<tr '.$css_class.'>'.      $output = '<tr '.$css_class.'>'.
Line 4312  sub modifiable_userdata_row { Line 7436  sub modifiable_userdata_row {
     if (ref($settings) eq 'HASH') {      if (ref($settings) eq 'HASH') {
         if (ref($settings->{$context}) eq 'HASH') {          if (ref($settings->{$context}) eq 'HASH') {
             if (ref($settings->{$context}->{$role}) eq 'HASH') {              if (ref($settings->{$context}->{$role}) eq 'HASH') {
                 foreach my $field (@fields) {                  my $hashref = $settings->{$context}->{$role};
                     if ($settings->{$context}->{$role}->{$field}) {                  if ($role eq 'emailusername') {
                         $checks{$field} = ' checked="checked" ';                      if ($statustype) {
                           if (ref($settings->{$context}->{$role}->{$statustype}) eq 'HASH') {
                               $hashref = $settings->{$context}->{$role}->{$statustype};
                               if (ref($hashref) eq 'HASH') { 
                                   foreach my $field (@fields) {
                                       if ($hashref->{$field}) {
                                           $checks{$field} = $hashref->{$field};
                                       }
                                   }
                               }
                           }
                       }
                   } else {
                       if (ref($hashref) eq 'HASH') {
                           foreach my $field (@fields) {
                               if ($hashref->{$field}) {
                                   $checks{$field} = ' checked="checked" ';
                               }
                           }
                     }                      }
                 }                  }
             }              }
         }          }
     }      }
        
     for (my $i=0; $i<@fields; $i++) {      for (my $i=0; $i<@fields; $i++) {
         my $rem = $i%($numinrow);          my $rem = $i%($numinrow);
         if ($rem == 0) {          if ($rem == 0) {
Line 4329  sub modifiable_userdata_row { Line 7472  sub modifiable_userdata_row {
             $output .= '<tr>';              $output .= '<tr>';
         }          }
         my $check = ' ';          my $check = ' ';
         if (exists($checks{$fields[$i]})) {          unless ($role eq 'emailusername') {
             $check = $checks{$fields[$i]}              if (exists($checks{$fields[$i]})) {
         } else {                  $check = $checks{$fields[$i]}
             if ($role eq 'st') {              } else {
                 if (ref($settings) ne 'HASH') {                  if ($role eq 'st') {
                     $check = ' checked="checked" ';                       if (ref($settings) ne 'HASH') {
                           $check = ' checked="checked" '; 
                       }
                 }                  }
             }              }
         }          }
         $output .= '<td class="LC_left_item">'.          $output .= '<td class="LC_left_item">'.
                    '<span class="LC_nobreak"><label>'.                     '<span class="LC_nobreak">';
                    '<input type="checkbox" name="canmodify_'.$role.'" '.          if ($role eq 'emailusername') {
                    'value="'.$fields[$i].'"'.$check.'/>'.$fieldtitles{$fields[$i]}.              unless ($checks{$fields[$i]} =~ /^(required|optional)$/) {
                    '</label></span></td>';                  $checks{$fields[$i]} = 'omit';
               }
               foreach my $option ('required','optional','omit') {
                   my $checked='';
                   if ($checks{$fields[$i]} eq $option) {
                       $checked='checked="checked" ';
                   }
                   $output .= '<label>'.
                              '<input type="radio" name="canmodify_'.$item.'_'.$fields[$i].'" value="'.$option.'" '.$checked.'/>'.
                              &mt($option).'</label>'.('&nbsp;' x2);
               }
               $output .= '<i>'.$fieldtitles{$fields[$i]}.'</i>';
           } else {
               $output .= '<label>'.
                          '<input type="checkbox" name="canmodify_'.$role.'" '.
                          'value="'.$fields[$i].'"'.$check.'/>'.$fieldtitles{$fields[$i]}.
                          '</label>';
           }
           $output .= '</span></td>';
         $rem = @fields%($numinrow);          $rem = @fields%($numinrow);
     }      }
     my $colsleft = $numinrow - $rem;      my $colsleft = $numinrow - $rem;
Line 4357  sub modifiable_userdata_row { Line 7520  sub modifiable_userdata_row {
 }  }
   
 sub insttypes_row {  sub insttypes_row {
     my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context) = @_;      my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context,$rownum) = @_;
     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)',
Line 4371  sub insttypes_row { Line 7534  sub insttypes_row {
     if ($context eq 'statustocreate') {      if ($context eq 'statustocreate') {
         $class = 'LC_right_item';          $class = 'LC_right_item';
     }      }
     my $output =  '<tr class="LC_odd_row">'.      my $css_class = ' class="LC_odd_row"';
                   '<td>'.$lt{$context}.$showdom.      if ($rownum ne '') { 
                   '</td><td class="'.$class.'" colspan="2"><table>';          $css_class = ($rownum%2? ' class="LC_odd_row"':'');
       }
       my $output = '<tr'.$css_class.'>'.
                    '<td>'.$lt{$context}.$showdom.
                    '</td><td class="'.$class.'" colspan="2"><table>';
     my $rem;      my $rem;
     if (ref($types) eq 'ARRAY') {      if (ref($types) eq 'ARRAY') {
         for (my $i=0; $i<@{$types}; $i++) {          for (my $i=0; $i<@{$types}; $i++) {
Line 4502  sub usertype_update_row { Line 7669  sub usertype_update_row {
 }  }
   
 sub modify_login {  sub modify_login {
     my ($r,$dom,$confname,%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);
     %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',
                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');
     @offon = ('off','on');      @offon = ('off','on');
Line 4519  sub modify_login { Line 7687  sub modify_login {
     }      }
     ($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'],      ($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'],
                                            \%domconfig,\%loginhash);                                             \%domconfig,\%loginhash);
     my @toggles = ('coursecatalog','adminmail','newuser');      my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');
     foreach my $item (@toggles) {      foreach my $item (@toggles) {
         $loginhash{login}{$item} = $env{'form.'.$item};          $loginhash{login}{$item} = $env{'form.'.$item};
     }      }
Line 4530  sub modify_login { Line 7698  sub modify_login {
     }      }
   
     my %servers = &Apache::lonnet::internet_dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my %domservers = &Apache::lonnet::get_servers($dom);
     my @loginvia_attribs = ('serverpath','custompath','exempt');      my @loginvia_attribs = ('serverpath','custompath','exempt');
     if (keys(%servers) > 1) {      if (keys(%servers) > 1) {
         foreach my $lonhost (keys(%servers)) {          foreach my $lonhost (keys(%servers)) {
Line 4572  sub modify_login { Line 7741  sub modify_login {
                             $changes{'loginvia'}{$lonhost} = 1;                              $changes{'loginvia'}{$lonhost} = 1;
                         }                          }
                         if ($item eq 'exempt') {                          if ($item eq 'exempt') {
                             $new =~ s/^\s+//;                              $new = &check_exempt_addresses($new);
                             $new =~ s/\s+$//;  
                             my @poss_ips = split(/\s*[,:]\s*/,$new);  
                             my @okips;  
                             foreach my $ip (@poss_ips) {  
                                 if ($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {  
                                     if (($1 <= 255) && ($2 <= 255) && ($3 <= 255) && ($4 <= 255)) {  
                                         push(@okips,$ip);   
                                     }  
                                 }  
                             }  
                             if (@okips > 0) {  
                                 $new = join(',',@okips);   
                             } else {  
                                 $new = '';   
                             }  
                         }                          }
                         $loginhash{login}{loginvia}{$lonhost}{$item} = $new;                          $loginhash{login}{loginvia}{$lonhost}{$item} = $new;
                     }                      }
Line 4683  sub modify_login { Line 7837  sub modify_login {
                         $errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';                          $errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';
                         if ((grep(/^\Q$lang\E$/,@currlangs)) &&                          if ((grep(/^\Q$lang\E$/,@currlangs)) &&
                             (!grep(/^\Q$lang\E$/,@delurls))) {                              (!grep(/^\Q$lang\E$/,@delurls))) {
   
                             $loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang};                              $loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang};
                         }                          }
                     }                      }
Line 4699  sub modify_login { Line 7852  sub modify_login {
             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';              $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
         }          }
     }      }
   
       my (%currheadtagurls,%currexempt,@newhosts,%newheadtagurls,%possexempt);
       if (ref($domconfig{'login'}) eq 'HASH') {
           if (ref($domconfig{'login'}{'headtag'}) eq 'HASH') {
               foreach my $lonhost (keys(%{$domconfig{'login'}{'headtag'}})) {
                   if ($domservers{$lonhost}) {
                       if (ref($domconfig{'login'}{'headtag'}{$lonhost}) eq 'HASH') {
                           $currheadtagurls{$lonhost} = $domconfig{'login'}{'headtag'}{$lonhost}{'url'};
                           $currexempt{$lonhost} = $domconfig{'login'}{'headtag'}{$lonhost}{'exempt'};
                       }
                   }
               }
           }
       }
       my @delheadtagurls = &Apache::loncommon::get_env_multiple('form.loginheadtag_del');
       foreach my $lonhost (sort(keys(%domservers))) {
           if (grep(/^\Q$lonhost\E$/,@delheadtagurls)) {
               $changes{'headtag'}{$lonhost} = 1;
           } else {
               if ($env{'form.loginheadtagexempt_'.$lonhost}) {
                   $possexempt{$lonhost} = &check_exempt_addresses($env{'form.loginheadtagexempt_'.$lonhost});
               }
               if ($env{'form.loginheadtag_'.$lonhost.'.filename'}) {
                   push(@newhosts,$lonhost);
               } elsif ($currheadtagurls{$lonhost}) {
                   $loginhash{'login'}{'headtag'}{$lonhost}{'url'} = $currheadtagurls{$lonhost};
                   if ($currexempt{$lonhost}) {
                       if ((!exists($possexempt{$lonhost})) || ($possexempt{$lonhost} ne $currexempt{$lonhost})) {
                           $changes{'headtag'}{$lonhost} = 1;
                       }
                   } elsif ($possexempt{$lonhost}) {
                       $changes{'headtag'}{$lonhost} = 1;
                   }
                   if ($possexempt{$lonhost}) {
                       $loginhash{'login'}{'headtag'}{$lonhost}{'exempt'} = $possexempt{$lonhost};
                   }
               }
           }
       }
       if (@newhosts) {
           my $error;
           my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
           if ($configuserok eq 'ok') {
               if ($switchserver) {
                   $error = &mt("Upload of custom markup is not permitted to this server: [_1]",$switchserver);
               } elsif ($author_ok eq 'ok') {
                   foreach my $lonhost (@newhosts) {
                       my $formelem = 'loginheadtag_'.$lonhost;
                       (my $result,$newheadtagurls{$lonhost}) = &publishlogo($r,'upload',$formelem,$dom,$confname,
                                                                             "login/headtag/$lonhost",'','',
                                                                             $env{'form.loginheadtag_'.$lonhost.'.filename'});
                       if ($result eq 'ok') {
                           $loginhash{'login'}{'headtag'}{$lonhost}{'url'} = $newheadtagurls{$lonhost};
                           $changes{'headtag'}{$lonhost} = 1;
                           if ($possexempt{$lonhost}) {
                               $loginhash{'login'}{'headtag'}{$lonhost}{'exempt'} = $possexempt{$lonhost};
                           }
                       } else {
                           my $puberror = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",
                                              $newheadtagurls{$lonhost},$result);
                           $errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';
                           if ((grep(/^\Q$lonhost\E$/,keys(%currheadtagurls))) &&
                               (!grep(/^\Q$lonhost\E$/,@delheadtagurls))) {
                               $loginhash{'login'}{'headtag'}{$lonhost} = $currheadtagurls{$lonhost};
                           }
                       }
                   }
               } else {
                   $error = &mt("Upload of custom markup file(s) failed because an author role could not be assigned to a Domain Configuration user ([_1]) in domain: [_2].  Error was: [_3].",$confname,$dom,$author_ok);
               }
           } else {
               $error = &mt("Upload of custom markup file(s) failed because a Domain Configuration user ([_1]) could not be created in domain: [_2].  Error was: [_3].",$confname,$dom,$configuserok);
           }
           if ($error) {
               &Apache::lonnet::logthis($error);
               $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
           }
       }
     &process_captcha('login',\%changes,$loginhash{'login'},$domconfig{'login'});      &process_captcha('login',\%changes,$loginhash{'login'},$domconfig{'login'});
   
     my $defaulthelpfile = '/adm/loginproblems.html';      my $defaulthelpfile = '/adm/loginproblems.html';
Line 4707  sub modify_login { Line 7938  sub modify_login {
     my $putresult = &Apache::lonnet::put_dom('configuration',\%loginhash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%loginhash,
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         my @toggles = ('coursecatalog','adminmail','newuser');          my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');
         my %defaultchecked = (          my %defaultchecked = (
                     'coursecatalog' => 'on',                      'coursecatalog' => 'on',
                       'helpdesk'      => 'on',
                     'adminmail'     => 'off',                      'adminmail'     => 'off',
                     'newuser'       => 'off',                      'newuser'       => 'off',
         );          );
Line 4738  sub modify_login { Line 7970  sub modify_login {
         }          }
         if (keys(%changes) > 0 || $colchgtext) {          if (keys(%changes) > 0 || $colchgtext) {
             &Apache::loncommon::devalidate_domconfig_cache($dom);              &Apache::loncommon::devalidate_domconfig_cache($dom);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domainconfig'} = 1;
               }
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
                 if ($item eq 'loginvia') {                  if ($item eq 'loginvia') {
Line 4795  sub modify_login { Line 8030  sub modify_login {
                             }                              }
                         }                          }
                     }                      }
                   } elsif ($item eq 'headtag') {
                       if (ref($changes{$item}) eq 'HASH') {
                           foreach my $lonhost (sort(keys(%{$changes{$item}}))) {
                               if (grep(/^\Q$lonhost\E$/,@delheadtagurls)) {
                                   $resulttext .= '<li>'.&mt('custom markup file removed for [_1]',$domservers{$lonhost}).'</li>';
                               } elsif (ref($loginhash{'login'}{'headtag'}{$lonhost}) eq 'HASH') {
                                   $resulttext .= '<li><a href="'.
                                                  "javascript:void(open('$loginhash{'login'}{'headtag'}{$lonhost}{'url'}?inhibitmenu=yes','Custom_HeadTag',
                                                  'menubar=0,toolbar=1,scrollbars=1,width=600,height=500,resizable=yes'))".
                                                  '">'.&mt('custom markup').'</a> '.&mt('(for [_1])',$servers{$lonhost}).' ';
                                   if ($possexempt{$lonhost}) {
                                       $resulttext .= &mt('not included for client IP(s): [_1]',$possexempt{$lonhost});
                                   } else {
                                       $resulttext .= &mt('included for any client IP');
                                   }
                                   $resulttext .= '</li>';
                               }
                           }
                       }
                 } elsif ($item eq 'captcha') {                  } elsif ($item eq 'captcha') {
                     if (ref($loginhash{'login'}) eq 'HASH') {                      if (ref($loginhash{'login'}) eq 'HASH') {
                         my $chgtxt;                          my $chgtxt;
Line 4826  sub modify_login { Line 8080  sub modify_login {
                         if (!$privkey) {                          if (!$privkey) {
                             $chgtxt .= '<li>'.&mt('Private key deleted').'</li>';                              $chgtxt .= '<li>'.&mt('Private key deleted').'</li>';
                         } else {                          } else {
                             $chgtxt .= '<li>'.&mt('Private key set to [_1]',$pubkey).'</li>';                              $chgtxt .= '<li>'.&mt('Private key set to [_1]',$privkey).'</li>';
                         }                          }
                         $chgtxt .= '</ul>';                          $chgtxt .= '</ul>';
                         $resulttext .= '<li>'.$chgtxt.'</li>';                          $resulttext .= '<li>'.$chgtxt.'</li>';
                     }                      }
                   } elsif ($item eq 'recaptchaversion') {
                       if (ref($loginhash{'login'}) eq 'HASH') {
                           if ($loginhash{'login'}{'captcha'} eq 'recaptcha') {
                               $resulttext .= '<li>'.&mt('ReCAPTCHA for helpdesk form set to version [_1]',$loginhash{'login'}{'recaptchaversion'}).
                                              '</li>';
                           }
                       }
                 } else {                  } else {
                     $resulttext .= '<li>'.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'</li>';                      $resulttext .= '<li>'.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'</li>';
                 }                  }
Line 4850  sub modify_login { Line 8111  sub modify_login {
     return $resulttext;      return $resulttext;
 }  }
   
   sub check_exempt_addresses {
       my ($iplist) = @_;
       $iplist =~ s/^\s+//;
       $iplist =~ s/\s+$//;
       my @poss_ips = split(/\s*[,:]\s*/,$iplist);
       my (@okips,$new);
       foreach my $ip (@poss_ips) {
           if ($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
               if (($1 <= 255) && ($2 <= 255) && ($3 <= 255) && ($4 <= 255)) {
                   push(@okips,$ip);
               }
           }
       }
       if (@okips > 0) {
           $new = join(',',@okips);
       } else {
           $new = '';
       }
       return $new;
   }
   
 sub color_font_choices {  sub color_font_choices {
     my %choices =      my %choices =
         &Apache::lonlocal::texthash (          &Apache::lonlocal::texthash (
Line 4858  sub color_font_choices { Line 8140  sub color_font_choices {
             links => "Link colors",              links => "Link colors",
             images => "Images",              images => "Images",
             font => "Font color",              font => "Font color",
             fontmenu => "Font Menu",              fontmenu => "Font menu",
             pgbg => "Page",              pgbg => "Page",
             tabbg => "Header",              tabbg => "Header",
             sidebg => "Border",              sidebg => "Border",
Line 4870  sub color_font_choices { Line 8152  sub color_font_choices {
 }  }
   
 sub modify_rolecolors {  sub modify_rolecolors {
     my ($r,$dom,$confname,$roles,%domconfig) = @_;      my ($r,$dom,$confname,$roles,$lastactref,%domconfig) = @_;
     my ($resulttext,%rolehash);      my ($resulttext,%rolehash);
     $rolehash{'rolecolors'} = {};      $rolehash{'rolecolors'} = {};
     if (ref($domconfig{'rolecolors'}) ne 'HASH') {      if (ref($domconfig{'rolecolors'}) ne 'HASH') {
Line 4885  sub modify_rolecolors { Line 8167  sub modify_rolecolors {
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             &Apache::loncommon::devalidate_domconfig_cache($dom);              &Apache::loncommon::devalidate_domconfig_cache($dom);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domainconfig'} = 1;
               }
             $resulttext = &display_colorchgs($dom,\%changes,$roles,              $resulttext = &display_colorchgs($dom,\%changes,$roles,
                                              $rolehash{'rolecolors'});                                               $rolehash{'rolecolors'});
         } else {          } else {
Line 4910  sub modify_colors { Line 8195  sub modify_colors {
     my @images;      my @images;
     my $servadm = $r->dir_config('lonAdmEMail');      my $servadm = $r->dir_config('lonAdmEMail');
     my $errors;      my $errors;
       my %defaults;
     foreach my $role (@{$roles}) {      foreach my $role (@{$roles}) {
         if ($role eq 'login') {          if ($role eq 'login') {
             %choices = &login_choices();              %choices = &login_choices();
             @logintext = ('textcol','bgcol');              @logintext = ('textcol','bgcol');
         } else {          } else {
             %choices = &color_font_choices();              %choices = &color_font_choices();
             $confhash->{$role}{'fontmenu'} = $env{'form.'.$role.'_fontmenu'};  
         }          }
         if ($role eq 'login') {          if ($role eq 'login') {
             @images = ('img','logo','domlogo','login');              @images = ('img','logo','domlogo','login');
             @bgs = ('pgbg','mainbg','sidebg');              @bgs = ('pgbg','mainbg','sidebg');
         } else {          } else {
             @images = ('img');              @images = ('img');
             @bgs = ('pgbg','tabbg','sidebg');               @bgs = ('pgbg','tabbg','sidebg');
         }          }
         $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'};          my %defaults = &role_defaults($role,\@bgs,\@links,\@images,\@logintext);
         foreach my $item (@bgs,@links,@logintext) {          unless ($env{'form.'.$role.'_font'} eq $defaults{'font'}) {
             $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};              $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'};
           }
           if ($role eq 'login') {
               foreach my $item (@logintext) {
                   $env{'form.'.$role.'_'.$item} = lc($env{'form.'.$role.'_'.$item});
                   if ($env{'form.'.$role.'_'.$item} =~ /^\w+/) {
                       $env{'form.'.$role.'_'.$item} = '#'.$env{'form.'.$role.'_'.$item};
                   }
                   unless ($env{'form.'.$role.'_'.$item} eq lc($defaults{'logintext'}{$item})) {
                       $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
                   }
               }
           } else {
               $env{'form.'.$role.'_fontmenu'} = lc($env{'form.'.$role.'_fontmenu'});
               if ($env{'form.'.$role.'_fontmenu'} =~ /^\w+/) {
                   $env{'form.'.$role.'_fontmenu'} = '#'.$env{'form.'.$role.'_fontmenu'};
               }
               unless($env{'form.'.$role.'_fontmenu'} eq lc($defaults{'fontmenu'})) {
                   $confhash->{$role}{'fontmenu'} = $env{'form.'.$role.'_fontmenu'};
               }
           }
           foreach my $item (@bgs) {
               $env{'form.'.$role.'_'.$item} = lc($env{'form.'.$role.'_'.$item});
               if ($env{'form.'.$role.'_'.$item} =~ /^\w+/) {
                   $env{'form.'.$role.'_'.$item} = '#'.$env{'form.'.$role.'_'.$item};
               }
               unless ($env{'form.'.$role.'_'.$item} eq lc($defaults{'bgs'}{$item})) {
                   $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
               }
           }
           foreach my $item (@links) {
               $env{'form.'.$role.'_'.$item} = lc($env{'form.'.$role.'_'.$item});
               if ($env{'form.'.$role.'_'.$item} =~ /^\w+/) {
                   $env{'form.'.$role.'_'.$item} = '#'.$env{'form.'.$role.'_'.$item};
               }
               unless ($env{'form.'.$role.'_'.$item} eq lc($defaults{'links'}{$item})) {
                   $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
               }
         }          }
         my ($configuserok,$author_ok,$switchserver) =           my ($configuserok,$author_ok,$switchserver) = 
             &config_check($dom,$confname,$servadm);              &config_check($dom,$confname,$servadm);
Line 5261  sub check_authorstatus { Line 8583  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 5283  sub publishlogo { Line 8605  sub publishlogo {
     if ($fname=~m|/|) {      if ($fname=~m|/|) {
         ($fnamepath,$file) = ($fname =~ m|^(.*)/([^/]+)$|);          ($fnamepath,$file) = ($fname =~ m|^(.*)/([^/]+)$|);
     }      }
     my @parts=split(/\//,"$filepath/$relpath/$fnamepath");        my @parts=split(/\//,"$filepath/$relpath/$fnamepath");
     my $count;      my $count;
     for ($count=5;$count<=$#parts;$count++) {      for ($count=5;$count<=$#parts;$count++) {
         $filepath.="/$parts[$count]";          $filepath.="/$parts[$count]";
Line 5295  sub publishlogo { Line 8617  sub publishlogo {
     if ($file=~/\.(\w+)$/ &&      if ($file=~/\.(\w+)$/ &&
         (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {          (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {
         $output =           $output = 
             &mt('Invalid file extension ([_1]) - reserved for LONCAPA use.',$1);               &mt('Invalid file extension ([_1]) - reserved for internal use.',$1); 
     } elsif ($file=~/\.(\w+)$/ &&      } elsif ($file=~/\.(\w+)$/ &&
         !defined(&Apache::loncommon::fileembstyle($1))) {          !defined(&Apache::loncommon::fileembstyle($1))) {
         $output = &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1);          $output = &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1);
     } elsif ($file=~/\.(\d+)\.(\w+)$/) {      } elsif ($file=~/\.(\d+)\.(\w+)$/) {
         $output = &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2);          $output = &mt('Filename not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2);
     } elsif (-d "$filepath/$file") {      } elsif (-d "$filepath/$file") {
         $output = &mt('File name is a directory name - rename the file and re-upload');          $output = &mt('Filename is a directory name - rename the file and re-upload');
     } else {      } else {
         my $source = $filepath.'/'.$file;          my $source = $filepath.'/'.$file;
         my $logfile;          my $logfile;
         if (!open($logfile,">>$source".'.log')) {          if (!open($logfile,">>$source".'.log')) {
             return (&mt('No write permission to Construction Space'));              return (&mt('No write permission to Authoring Space'));
         }          }
         print $logfile          print $logfile
 "\n================= Publish ".localtime()." ================\n".  "\n================= Publish ".localtime()." ================\n".
Line 5389  $env{'user.name'}.':'.$env{'user.domain' Line 8711  $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 5401  $env{'user.name'}.':'.$env{'user.domain' Line 8724  $env{'user.name'}.':'.$env{'user.domain'
             $output = $versionresult;              $output = $versionresult;
         }          }
     }      }
     return ($output,$logourl);      return ($output,$logourl,$madethumb);
 }  }
   
 sub logo_versioning {  sub logo_versioning {
Line 5454  sub write_metadata { Line 8777  sub write_metadata {
         print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file;          print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file;
         my $mfh;          my $mfh;
         if (open($mfh,'>'.$targetdir.'/'.$file.'.meta')) {          if (open($mfh,'>'.$targetdir.'/'.$file.'.meta')) {
             foreach (sort keys %metadatafields) {              foreach (sort(keys(%metadatafields))) {
                 unless ($_=~/\./) {                  unless ($_=~/\./) {
                     my $unikey=$_;                      my $unikey=$_;
                     $unikey=~/^([A-Za-z]+)/;                      $unikey=~/^([A-Za-z]+)/;
Line 5538  sub check_switchserver { Line 8861  sub check_switchserver {
     my @ids=&Apache::lonnet::current_machine_ids();      my @ids=&Apache::lonnet::current_machine_ids();
     foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }      foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
     if (!$allowed) {      if (!$allowed) {
  $switchserver='<a href="/adm/switchserver?otherserver='.$home.'&role=dc./'.$dom.'/">'.&mt('Switch Server').'</a>';   $switchserver='<a href="/adm/switchserver?otherserver='.$home.'&amp;role=dc./'.$dom.'/&amp;destinationurl=/adm/domainprefs">'.&mt('Switch Server').'</a>';
     }      }
     return $switchserver;      return $switchserver;
 }  }
   
 sub modify_quotas {  sub modify_quotas {
     my ($dom,$action,%domconfig) = @_;      my ($r,$dom,$action,$lastactref,%domconfig) = @_;
     my ($context,@usertools,@options,%validations,%titles,%confhash,%toolshash,      my ($context,@usertools,@options,%validations,%titles,%confhash,%toolshash,
         %limithash,$toolregexp,%conditions,$resulttext,%changes);          %limithash,$toolregexp,%conditions,$resulttext,%changes,$confname,$configuserok,
           $author_ok,$switchserver,$errors,$validationitemsref,$validationnamesref,
           $validationfieldsref);
     if ($action eq 'quotas') {      if ($action eq 'quotas') {
         $context = 'tools';           $context = 'tools'; 
     } else {       } else {
         $context = $action;          $context = $action;
     }      }
     if ($context eq 'requestcourses') {      if ($context eq 'requestcourses') {
         @usertools = ('official','unofficial','community');          @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();
         $toolregexp = join('|',@usertools);          $toolregexp = join('|',@usertools);
         %conditions = &courserequest_conditions();          %conditions = &courserequest_conditions();
           $confname = $dom.'-domainconfig';
           my $servadm = $r->dir_config('lonAdmEMail');
           ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
           ($validationitemsref,$validationnamesref,$validationfieldsref) = 
               &Apache::loncoursequeueadmin::requestcourses_validation_types();
     } elsif ($context eq 'requestauthor') {      } elsif ($context eq 'requestauthor') {
         @usertools = ('author');          @usertools = ('author');
         %titles = &authorrequest_titles();          %titles = &authorrequest_titles();
Line 5566  sub modify_quotas { Line 8896  sub modify_quotas {
         @usertools = ('aboutme','blog','webdav','portfolio');          @usertools = ('aboutme','blog','webdav','portfolio');
         %titles = &tool_titles();          %titles = &tool_titles();
     }      }
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);      my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
     foreach my $key (keys(%env)) {      foreach my $key (keys(%env)) {
         if ($context eq 'requestcourses') {          if ($context eq 'requestcourses') {
Line 5586  sub modify_quotas { Line 8916  sub modify_quotas {
         } else {          } else {
             if ($key =~ /^form\.quota_(.+)$/) {              if ($key =~ /^form\.quota_(.+)$/) {
                 $confhash{'defaultquota'}{$1} = $env{$key};                  $confhash{'defaultquota'}{$1} = $env{$key};
             }              } elsif ($key =~ /^form\.authorquota_(.+)$/) {
             if ($key =~ /^form\.\Q$context\E_(.+)$/) {                  $confhash{'authorquota'}{$1} = $env{$key};
               } elsif ($key =~ /^form\.\Q$context\E_(.+)$/) {
                 @{$toolshash{$1}} = &Apache::loncommon::get_env_multiple($key);                  @{$toolshash{$1}} = &Apache::loncommon::get_env_multiple($key);
             }              }
         }          }
     }      }
     if (($context eq 'requestcourses') || ($context eq 'requestauthor')) {      if (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
         my @approvalnotify = &Apache::loncommon::get_env_multiple('form.reqapprovalnotify');          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','placement');
           my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');
           foreach my $type (@hasuniquecode) {
               if (grep(/^\Q$type\E$/,@crstypes)) {
                   $confhash{'uniquecode'}{$type} = 1;
               }
           }
           my (%newbook,%allpos);
           if ($context eq 'requestcourses') {
               foreach my $type ('textbooks','templates') {
                   @{$allpos{$type}} = (); 
                   my $invalid;
                   if ($type eq 'textbooks') {
                       $invalid = &mt('Invalid LON-CAPA course for textbook');
                   } else {
                       $invalid = &mt('Invalid LON-CAPA course for template');
                   }
                   if ($env{'form.'.$type.'_addbook'}) {
                       if (($env{'form.'.$type.'_addbook_cnum'} =~ /^$match_courseid$/) &&
                           ($env{'form.'.$type.'_addbook_cdom'} =~ /^$match_domain$/)) {
                           if (&Apache::lonnet::homeserver($env{'form.'.$type.'_addbook_cnum'},
                                                           $env{'form.'.$type.'_addbook_cdom'}) eq 'no_host') {
                               $errors .= '<li><span class="LC_error">'.$invalid.'</span></li>';
                           } else {
                               $newbook{$type} = $env{'form.'.$type.'_addbook_cdom'}.'_'.$env{'form.'.$type.'_addbook_cnum'};
                               my $position = $env{'form.'.$type.'_addbook_pos'};
                               $position =~ s/\D+//g;
                               if ($position ne '') {
                                   $allpos{$type}[$position] = $newbook{$type};
                               }
                           }
                       } else {
                           $errors .= '<li><span class="LC_error">'.$invalid.'</span></li>';
                       }
                   }
               } 
           }
         if (ref($domconfig{$action}) eq 'HASH') {          if (ref($domconfig{$action}) eq 'HASH') {
             if (ref($domconfig{$action}{'notify'}) eq 'HASH') {              if (ref($domconfig{$action}{'notify'}) eq 'HASH') {
                 if ($domconfig{$action}{'notify'}{'approval'} ne $confhash{'notify'}{'approval'}) {                  if ($domconfig{$action}{'notify'}{'approval'} ne $confhash{'notify'}{'approval'}) {
Line 5606  sub modify_quotas { Line 8974  sub modify_quotas {
                     $changes{'notify'}{'approval'} = 1;                      $changes{'notify'}{'approval'} = 1;
                 }                  }
             }              }
               if (ref($domconfig{$action}{'uniquecode'}) eq 'HASH') {
                   if (ref($confhash{'uniquecode'}) eq 'HASH') {
                       foreach my $crstype (keys(%{$domconfig{$action}{'uniquecode'}})) {
                           unless ($confhash{'uniquecode'}{$crstype}) {
                               $changes{'uniquecode'} = 1;
                           }
                       }
                       unless ($changes{'uniquecode'}) {
                           foreach my $crstype (keys(%{$confhash{'uniquecode'}})) {
                               unless ($domconfig{$action}{'uniquecode'}{$crstype}) {
                                   $changes{'uniquecode'} = 1;
                               }
                           }
                       }
                  } else {
                      $changes{'uniquecode'} = 1;
                  }
               } elsif (ref($confhash{'uniquecode'}) eq 'HASH') {
                   $changes{'uniquecode'} = 1;
               }
               if ($context eq 'requestcourses') {
                   foreach my $type ('textbooks','templates') {
                       if (ref($domconfig{$action}{$type}) eq 'HASH') {
                           my %deletions;
                           my @todelete = &Apache::loncommon::get_env_multiple('form.'.$type.'_del');
                           if (@todelete) {
                               map { $deletions{$_} = 1; } @todelete;
                           }
                           my %imgdeletions;
                           my @todeleteimages = &Apache::loncommon::get_env_multiple('form.'.$type.'_image_del');
                           if (@todeleteimages) {
                               map { $imgdeletions{$_} = 1; } @todeleteimages;
                           }
                           my $maxnum = $env{'form.'.$type.'_maxnum'};
                           for (my $i=0; $i<=$maxnum; $i++) {
                               my $itemid = $env{'form.'.$type.'_id_'.$i};
                               my ($key) = ($itemid =~ /^\Q$type\E_(\w+)$/); 
                               if (ref($domconfig{$action}{$type}{$key}) eq 'HASH') {
                                   if ($deletions{$key}) {
                                       if ($domconfig{$action}{$type}{$key}{'image'}) {
                                           #FIXME need to obsolete item in RES space
                                       }
                                       next;
                                   } else {
                                       my $newpos = $env{'form.'.$itemid};
                                       $newpos =~ s/\D+//g;
                                       foreach my $item ('subject','title','publisher','author') {
                                           next if ((($item eq 'author') || ($item eq 'publisher')) &&
                                                    ($type eq 'templates'));
                                           $confhash{$type}{$key}{$item} = $env{'form.'.$type.'_'.$item.'_'.$i};
                                           if ($domconfig{$action}{$type}{$key}{$item} ne $confhash{$type}{$key}{$item}) {
                                               $changes{$type}{$key} = 1;
                                           }
                                       }
                                       $allpos{$type}[$newpos] = $key;
                                   }
                                   if ($imgdeletions{$key}) {
                                       $changes{$type}{$key} = 1;
                                       #FIXME need to obsolete item in RES space
                                   } elsif ($env{'form.'.$type.'_image_'.$i.'.filename'}) {
                                       my ($cdom,$cnum) = split(/_/,$key);
                                       my ($imgurl,$error) = &process_textbook_image($r,$dom,$confname,$type.'_image_'.$i,
                                                                                     $cdom,$cnum,$type,$configuserok,
                                                                                     $switchserver,$author_ok);
                                       if ($imgurl) {
                                           $confhash{$type}{$key}{'image'} = $imgurl;
                                           $changes{$type}{$key} = 1; 
                                       }
                                       if ($error) {
                                           &Apache::lonnet::logthis($error);
                                           $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                                       } 
                                   } elsif ($domconfig{$action}{$type}{$key}{'image'}) {
                                       $confhash{$type}{$key}{'image'} = 
                                           $domconfig{$action}{$type}{$key}{'image'};
                                   }
                               }
                           }
                       }
                   }
               }
         } else {          } else {
             if ($confhash{'notify'}{'approval'}) {              if ($confhash{'notify'}{'approval'}) {
                 $changes{'notify'}{'approval'} = 1;                  $changes{'notify'}{'approval'} = 1;
             }              }
               if (ref($confhash{'uniquecode'} eq 'HASH')) {
                   $changes{'uniquecode'} = 1;
               }
           }
           if ($context eq 'requestcourses') {
               foreach my $type ('textbooks','templates') {
                   if ($newbook{$type}) {
                       $changes{$type}{$newbook{$type}} = 1;
                       foreach my $item ('subject','title','publisher','author') {
                           next if ((($item eq 'author') || ($item eq 'publisher')) &&
                                    ($type eq 'template'));
                           $env{'form.'.$type.'_addbook_'.$item} =~ s/(`)/'/g;
                           if ($env{'form.'.$type.'_addbook_'.$item}) {
                               $confhash{$type}{$newbook{$type}}{$item} = $env{'form.'.$type.'_addbook_'.$item};
                           }
                       }
                       if ($type eq 'textbooks') {
                           if ($env{'form.'.$type.'_addbook_image.filename'} ne '') {
                               my ($cdom,$cnum) = split(/_/,$newbook{$type});
                               my ($imageurl,$error) =
                                   &process_textbook_image($r,$dom,$confname,$type.'_addbook_image',$cdom,$cnum,$type,
                                                           $configuserok,$switchserver,$author_ok);
                               if ($imageurl) {
                                   $confhash{$type}{$newbook{$type}}{'image'} = $imageurl;
                               }
                               if ($error) {
                                   &Apache::lonnet::logthis($error);
                                   $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                               }
                           }
                       }
                   }
                   if (@{$allpos{$type}} > 0) {
                       my $idx = 0;
                       foreach my $item (@{$allpos{$type}}) {
                           if ($item ne '') {
                               $confhash{$type}{$item}{'order'} = $idx;
                               if (ref($domconfig{$action}) eq 'HASH') {
                                   if (ref($domconfig{$action}{$type}) eq 'HASH') {
                                       if (ref($domconfig{$action}{$type}{$item}) eq 'HASH') {
                                           if ($domconfig{$action}{$type}{$item}{'order'} ne $idx) {
                                               $changes{$type}{$item} = 1;
                                           }
                                       }
                                   }
                               }
                               $idx ++;
                           }
                       }
                   }
               }
               if (ref($validationitemsref) eq 'ARRAY') {
                   foreach my $item (@{$validationitemsref}) {
                       if ($item eq 'fields') {
                           my @changed;
                           @{$confhash{'validation'}{$item}} = &Apache::loncommon::get_env_multiple('form.requestcourses_validation_'.$item);
                           if (@{$confhash{'validation'}{$item}} > 0) {
                               @{$confhash{'validation'}{$item}} = sort(@{$confhash{'validation'}{$item}});
                           }
                           if (ref($domconfig{'requestcourses'}) eq 'HASH') {
                               if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
                                   if (ref($domconfig{'requestcourses'}{'validation'}{$item}) eq 'ARRAY') {
                                       @changed = &Apache::loncommon::compare_arrays($confhash{'validation'}{$item},
                                                                                     $domconfig{'requestcourses'}{'validation'}{$item});
                                   } else {
                                       @changed = @{$confhash{'validation'}{$item}};
                                   }
                               } else {
                                   @changed = @{$confhash{'validation'}{$item}};
                               }
                           } else {
                               @changed = @{$confhash{'validation'}{$item}};
                           }
                           if (@changed) {
                               if ($confhash{'validation'}{$item}) {
                                   $changes{'validation'}{$item} = join(', ',@{$confhash{'validation'}{$item}});
                               } else {
                                   $changes{'validation'}{$item} = &mt('None');
                               }
                           }
                       } else {
                           $confhash{'validation'}{$item} = $env{'form.requestcourses_validation_'.$item};
                           if ($item eq 'markup') {
                               if ($env{'form.requestcourses_validation_'.$item}) {
                                   $env{'form.requestcourses_validation_'.$item} =~ s/[\n\r\f]+/\s/gs;
                               }
                           }
                           if (ref($domconfig{'requestcourses'}) eq 'HASH') {
                               if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
                                   if ($domconfig{'requestcourses'}{'validation'}{$item} ne $confhash{'validation'}{$item}) {
                                       $changes{'validation'}{$item} = $confhash{'validation'}{$item};
                                   }
                               } else {
                                   if ($confhash{'validation'}{$item} ne '') {
                                       $changes{'validation'}{$item} = $confhash{'validation'}{$item};
                                   }
                               }
                           } else {
                               if ($confhash{'validation'}{$item} ne '') {
                                   $changes{'validation'}{$item} = $confhash{'validation'}{$item};
                               }
                           }
                       }
                   }
               }
               if ($env{'form.validationdc'}) {
                   my $newval = $env{'form.validationdc'};
                   my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);
                   if (exists($domcoords{$newval})) {
                       $confhash{'validation'}{'dc'} = $newval;
                   }
               }
               if (ref($confhash{'validation'}) eq 'HASH') {
                   if (ref($domconfig{'requestcourses'}) eq 'HASH') {
                       if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
                           if ($domconfig{'requestcourses'}{'validation'}{'dc'}) {
                               unless ($confhash{'validation'}{'dc'} eq $domconfig{'requestcourses'}{'validation'}{'dc'}) {
                                   if ($confhash{'validation'}{'dc'} eq '') {
                                       $changes{'validation'}{'dc'} = &mt('None');
                                   } else {
                                       $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
                                   }
                               }
                           } elsif ($confhash{'validation'}{'dc'} ne '') {
                               $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
                           }
                       } elsif ($confhash{'validation'}{'dc'} ne '') {
                           $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
                       }
                   } elsif ($confhash{'validation'}{'dc'} ne '') {
                       $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
                   }
               } else {
                   if (ref($domconfig{'requestcourses'}) eq 'HASH') {
                       if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
                           if ($domconfig{'requestcourses'}{'validation'}{'dc'}) {
                               $changes{'validation'}{'dc'} = &mt('None');
                           }
                       }
                   }
               }
         }          }
     } else {      } else {
         $confhash{'defaultquota'}{'default'} = $env{'form.defaultquota'};          $confhash{'defaultquota'}{'default'} = $env{'form.defaultquota'};
           $confhash{'authorquota'}{'default'} = $env{'form.authorquota'};
     }      }
     foreach my $item (@usertools) {      foreach my $item (@usertools) {
         foreach my $type (@{$types},'default','_LC_adv') {          foreach my $type (@{$types},'default','_LC_adv') {
Line 5700  sub modify_quotas { Line 9291  sub modify_quotas {
                     }                      }
                 }                  }
             }              }
               if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') {
                   foreach my $key (keys(%{$domconfig{'quotas'}{'authorquota'}})) {
                       if (exists($confhash{'authorquota'}{$key})) {
                           if ($confhash{'authorquota'}{$key} ne $domconfig{'quotas'}{'authorquota'}{$key}) {
                               $changes{'authorquota'}{$key} = 1;
                           }
                       } else {
                           $confhash{'authorquota'}{$key} = $domconfig{'quotas'}{'authorquota'}{$key};
                       }
                   }
               }
         }          }
         if (ref($confhash{'defaultquota'}) eq 'HASH') {          if (ref($confhash{'defaultquota'}) eq 'HASH') {
             foreach my $key (keys(%{$confhash{'defaultquota'}})) {              foreach my $key (keys(%{$confhash{'defaultquota'}})) {
Line 5718  sub modify_quotas { Line 9320  sub modify_quotas {
                 }                  }
             }              }
         }          }
           if (ref($confhash{'authorquota'}) eq 'HASH') {
               foreach my $key (keys(%{$confhash{'authorquota'}})) {
                   if (ref($domconfig{'quotas'}) eq 'HASH') {
                       if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') {
                           if (!exists($domconfig{'quotas'}{'authorquota'}{$key})) {
                               $changes{'authorquota'}{$key} = 1;
                           }
                       } else {
                           $changes{'authorquota'}{$key} = 1;
                       }
                   } else {
                       $changes{'authorquota'}{$key} = 1;
                   }
               }
           }
     }      }
   
     if ($context eq 'requestauthor') {      if ($context eq 'requestauthor') {
         $domdefaults{'requestauthor'} = \%confhash;          $domdefaults{'requestauthor'} = \%confhash;
     } else {      } else {
         foreach my $key (keys(%confhash)) {          foreach my $key (keys(%confhash)) {
             $domdefaults{$key} = $confhash{$key};              unless (($context eq 'requestcourses') && (($key eq 'textbooks') || ($key eq 'templates'))) {
                   $domdefaults{$key} = $confhash{$key};
               }
         }          }
     }      }
   
Line 5737  sub modify_quotas { Line 9356  sub modify_quotas {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             my $cachetime = 24*60*60;              my $cachetime = 24*60*60;
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);              &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
               }
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             unless (($context eq 'requestcourses') ||              unless (($context eq 'requestcourses') ||
                     ($context eq 'requestauthor')) {                      ($context eq 'requestauthor')) {
Line 5749  sub modify_quotas { Line 9370  sub modify_quotas {
                             if ($type eq 'default') {                              if ($type eq 'default') {
                                 $typetitle = $othertitle;                                  $typetitle = $othertitle;
                             }                              }
                             $resulttext .= '<li>'.&mt('[_1] set to [_2] Mb',$typetitle,$confhash{'defaultquota'}{$type}).'</li>';                              $resulttext .= '<li>'.&mt('[_1] set to [_2] MB',$typetitle,$confhash{'defaultquota'}{$type}).'</li>';
                           }
                       }
                       $resulttext .= '</ul></li>';
                   }
                   if (ref($changes{'authorquota'}) eq 'HASH') {
                       $resulttext .= '<li>'.&mt('Authoring Space default quotas').'<ul>';
                       foreach my $type (@{$types},'default') {
                           if (defined($changes{'authorquota'}{$type})) {
                               my $typetitle = $usertypes->{$type};
                               if ($type eq 'default') {
                                   $typetitle = $othertitle;
                               }
                               $resulttext .= '<li>'.&mt('[_1] set to [_2] MB',$typetitle,$confhash{'authorquota'}{$type}).'</li>';
                         }                          }
                     }                      }
                     $resulttext .= '</ul></li>';                      $resulttext .= '</ul></li>';
Line 5808  sub modify_quotas { Line 9442  sub modify_quotas {
                                         $cond = $conditions{$inconf{$type}};                                          $cond = $conditions{$inconf{$type}};
                                     }                                      }
                                     $resulttext .= '<li>'.&mt('Set to be available to [_1].',$typetitle).' '.$cond.'</li>';                                      $resulttext .= '<li>'.&mt('Set to be available to [_1].',$typetitle).' '.$cond.'</li>';
                                   } elsif ($context eq 'requestauthor') {
                                       $resulttext .= '<li>'.&mt('Set to "[_1]" for "[_2]".',
                                                                $titles{$inconf{$type}},$typetitle);
   
                                 } else {                                  } else {
                                     $resulttext .= '<li>'.&mt('Set to be available to [_1]',$typetitle).'</li>';                                      $resulttext .= '<li>'.&mt('Set to be available to [_1]',$typetitle).'</li>';
                                 }                                  }
Line 5842  sub modify_quotas { Line 9480  sub modify_quotas {
                     }                      }
                 }                  }
             }              }
               if ($action eq 'requestcourses') {
                   my @offon = ('off','on');
                   if ($changes{'uniquecode'}) {
                       if (ref($confhash{'uniquecode'}) eq 'HASH') {
                           my $codestr = join(' ',map{ &mt($_); } sort(keys(%{$confhash{'uniquecode'}})));
                           $resulttext .= '<li>'.
                                          &mt('Generation of six character code as course identifier for distribution to students set to on for: [_1].','<b>'.$codestr.'</b>').
                                          '</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('Generation of six character code as course identifier for distribution to students set to off.').
                                          '</li>';
                       }
                   }
                   foreach my $type ('textbooks','templates') {
                       if (ref($changes{$type}) eq 'HASH') {
                           $resulttext .= '<li>'.&mt("Available $type updated").'<ul>';
                           foreach my $key (sort(keys(%{$changes{$type}}))) {
                               my %coursehash = &Apache::lonnet::coursedescription($key);
                               my $coursetitle = $coursehash{'description'};
                               my $position = $confhash{$type}{$key}{'order'} + 1;
                               $resulttext .= '<li>';
                               foreach my $item ('subject','title','publisher','author') {
                                   next if ((($item eq 'author') || ($item eq 'publisher')) &&
                                            ($type eq 'templates'));
                                   my $name = $item.':';
                                   $name =~ s/^(\w)/\U$1/;
                                   $resulttext .= &mt($name).' '.$confhash{$type}{$key}{$item}.'<br />';
                               }
                               $resulttext .= ' '.&mt('Order: [_1]',$position).'<br />';
                               if ($type eq 'textbooks') {
                                   if ($confhash{$type}{$key}{'image'}) {
                                       $resulttext .= ' '.&mt('Image: [_1]',
                                                      '<img src="'.$confhash{$type}{$key}{'image'}.'"'.
                                                      ' alt="Textbook cover" />').'<br />';
                                   }
                               }
                               $resulttext .= ' '.&mt('LON-CAPA Course: [_1]',$coursetitle).'</li>';
                           }
                           $resulttext .= '</ul></li>';
                       }
                   }
                   if (ref($changes{'validation'}) eq 'HASH') {
                       if ((ref($validationitemsref) eq 'ARRAY') && (ref($validationnamesref) eq 'HASH')) {
                           $resulttext .= '<li>'.&mt('Validation of courses/communities updated').'<ul>';
                           foreach my $item (@{$validationitemsref}) {
                               if (exists($changes{'validation'}{$item})) {
                                   if ($item eq 'markup') {
                                       $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$validationnamesref->{$item},
                                                                 '<br /><pre>'.$changes{'validation'}{$item}.'</pre>').'</li>';
                                   } else {
                                       $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$validationnamesref->{$item},
                                                                 '<b>'.$changes{'validation'}{$item}.'</b>').'</li>';
                                   }
                               }
                           }
                           if (exists($changes{'validation'}{'dc'})) {
                               $resulttext .= '<li>'.&mt('Validated course requests identified as processed by: [_1]',
                                                        '<b>'.$changes{'validation'}{'dc'}.'</b>').'</li>';
                           }
                       }
                   }
               }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
             if (keys(%newenv)) {              if (keys(%newenv)) {
                 &Apache::lonnet::appenv(\%newenv);                  &Apache::lonnet::appenv(\%newenv);
Line 5859  sub modify_quotas { Line 9559  sub modify_quotas {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
     &mt('An error occurred: [_1]',$putresult).'</span>';      &mt('An error occurred: [_1]',$putresult).'</span>';
     }      }
       if ($errors) {
           $resulttext .= '<p>'.&mt('The following errors occurred when modifying Textbook settings.').
                          '<ul>'.$errors.'</ul></p>';
       }
     return $resulttext;      return $resulttext;
 }  }
   
   sub process_textbook_image {
       my ($r,$dom,$confname,$caller,$cdom,$cnum,$type,$configuserok,$switchserver,$author_ok) = @_;
       my $filename = $env{'form.'.$caller.'.filename'};
       my ($error,$url);
       my ($width,$height) = (50,50);
       if ($configuserok eq 'ok') {
           if ($switchserver) {
               $error = &mt('Upload of textbook image is not permitted to this server: [_1]',
                            $switchserver);
           } elsif ($author_ok eq 'ok') {
               my ($result,$imageurl) =
                   &publishlogo($r,'upload',$caller,$dom,$confname,
                                "$type/$dom/$cnum/cover",$width,$height);
               if ($result eq 'ok') {
                   $url = $imageurl;
               } else {
                   $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$result);
               }
           } else {
               $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3].  Error was: [_4].",$filename,$confname,$dom,$author_ok);
           }
       } else {
           $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3].  Error was: [_4].",$filename,$confname,$dom,$configuserok);
       }
       return ($url,$error);
   }
   
   sub modify_ltitools {
       my ($r,$dom,$action,$lastactref,%domconfig) = @_;
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
       my ($newid,@allpos,%changes,%confhash,%encconfig,$errors,$resulttext);
       my $confname = $dom.'-domainconfig';
       my $servadm = $r->dir_config('lonAdmEMail');
       my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
       my (%posslti,%possfield);
       my @courseroles = ('cc','in','ta','ep','st');
       my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner);
       map { $posslti{$_} = 1; } @ltiroles;
       my @allfields = ('fullname','firstname','lastname','email','user','roles');
       map { $possfield{$_} = 1; } @allfields;
       my %lt = &ltitools_names(); 
       if ($env{'form.ltitools_add'}) {
           my $title = $env{'form.ltitools_add_title'};
           $title =~ s/(`)/'/g;
           ($newid,my $error) = &get_ltitools_id($dom,$title);
           if ($newid) {
               my $position = $env{'form.ltitools_add_pos'};
               $position =~ s/\D+//g;
               if ($position ne '') {
                   $allpos[$position] = $newid;
               }
               $changes{$newid} = 1;
               foreach my $item ('title','url','key','secret') {
                   $env{'form.ltitools_add_'.$item} =~ s/(`)/'/g;
                   if ($env{'form.ltitools_add_'.$item}) {
                       if (($item eq 'key') || ($item eq 'secret')) {
                           $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') {
                   $confhash{$newid}{'version'} = $env{'form.ltitools_add_version'};
               }
               if ($env{'form.ltitools_add_msgtype'} eq 'basic-lti-launch-request') {
                   $confhash{$newid}{'msgtype'} = $env{'form.ltitools_add_msgtype'};
               }
               foreach my $item ('width','height','linktext','explanation') {
                   $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+$/) {
                           $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') {
                   $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 {
                   $confhash{$newid}{'display'}{'target'} = 'iframe';
               }
               foreach my $item ('passback','roster') {
                   if ($env{'form.ltitools_add_'.$item}) {
                       $confhash{$newid}{$item} = 1;
                   }
               }
               if ($env{'form.ltitools_add_image.filename'} ne '') {
                   my ($imageurl,$error) =
                       &process_ltitools_image($r,$dom,$confname,'ltitools_add_image',$dom,
                                               $configuserok,$switchserver,$author_ok);
                   if ($imageurl) {
                       $confhash{$newid}{'image'} = $imageurl;
                   }
                   if ($error) {
                       &Apache::lonnet::logthis($error);
                       $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                   }
               }
               my @fields = &Apache::loncommon::get_env_multiple('form.ltitools_add_fields');
               foreach my $field (@fields) {
                   if ($possfield{$field}) {
                       if ($field eq 'roles') {
                           foreach my $role (@courseroles) {
                               my $choice = $env{'form.ltitools_add_roles_'.$role};
                               if (($choice ne '') && ($posslti{$choice})) {
                                   $confhash{$newid}{'roles'}{$role} = $choice;
                                   if ($role eq 'cc') {
                                       $confhash{$newid}{'roles'}{'co'} = $choice; 
                                   }
                               }
                           }
                       } else {
                           $confhash{$newid}{'fields'}{$field} = 1;
                       }
                   }
               }
               my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig');
               foreach my $item (@courseconfig) {
                   $confhash{$newid}{'crsconf'}{$item} = 1;
               }
               if ($env{'form.ltitools_add_custom'}) {
                   my $name = $env{'form.ltitools_add_custom_name'};
                   my $value = $env{'form.ltitools_add_custom_value'};
                   $value =~ s/(`)/'/g;
                   $name =~ s/(`)/'/g;
                   $confhash{$newid}{'custom'}{$name} = $value;
               }
           } else {
               my $error = &mt('Failed to acquire unique ID for new external tool');   
               $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
           }
       }
       if (ref($domconfig{$action}) eq 'HASH') {
           my %deletions;
           my @todelete = &Apache::loncommon::get_env_multiple('form.ltitools_del');
           if (@todelete) {
               map { $deletions{$_} = 1; } @todelete;
           }
           my %customadds;
           my @newcustom = &Apache::loncommon::get_env_multiple('form.ltitools_customadd');
           if (@newcustom) {
               map { $customadds{$_} = 1; } @newcustom;
           } 
           my %imgdeletions;
           my @todeleteimages = &Apache::loncommon::get_env_multiple('form.ltitools_image_del');
           if (@todeleteimages) {
               map { $imgdeletions{$_} = 1; } @todeleteimages;
           }
           my $maxnum = $env{'form.ltitools_maxnum'};
           for (my $i=0; $i<=$maxnum; $i++) {
               my $itemid = $env{'form.ltitools_id_'.$i};
               if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
                   if ($deletions{$itemid}) {
                       if ($domconfig{$action}{$itemid}{'image'}) {
                           #FIXME need to obsolete item in RES space
                       }
                       $changes{$itemid} = $domconfig{$action}{$itemid}{'title'};
                       next;
                   } else {
                       my $newpos = $env{'form.ltitools_'.$itemid};
                       $newpos =~ s/\D+//g;
                       foreach my $item ('title','url') {
                           $confhash{$itemid}{$item} = $env{'form.ltitools_'.$item.'_'.$i};
                           if ($domconfig{$action}{$itemid}{$item} ne $confhash{$itemid}{$item}) {
                               $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') {
                           $confhash{$itemid}{'version'} = $env{'form.ltitools_version_'.$i};
                       }
                       if ($env{'form.ltitools_msgtype_'.$i} eq 'basic-lti-launch-request') {
                           $confhash{$itemid}{'msgtype'} = $env{'form.ltitools_msgtype_'.$i};
                       }
                       foreach my $size ('width','height') {
                           $env{'form.ltitools_'.$size.'_'.$i} =~ s/^\s+//;
                           $env{'form.ltitools_'.$size.'_'.$i} =~ s/\s+$//;
                           if ($env{'form.ltitools_'.$size.'_'.$i} =~ /^\d+$/) {
                               $confhash{$itemid}{'display'}{$size} = $env{'form.ltitools_'.$size.'_'.$i};
                               if (ref($domconfig{$action}{$itemid}{'display'}) eq 'HASH') {
                                   if ($domconfig{$action}{$itemid}{'display'}{$size} ne $confhash{$itemid}{'display'}{$size}) {
                                       $changes{$itemid} = 1;
                                   }
                               } else {
                                   $changes{$itemid} = 1;
                               }
                           } 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') {
                           $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 {
                           $confhash{$itemid}{'display'}{'target'} = 'iframe';
                       }
                       if (ref($domconfig{$action}{$itemid}{'display'}) eq 'HASH') {
                           if ($domconfig{$action}{$itemid}{'display'}{'target'} ne $confhash{$itemid}{'display'}{'target'}) {
                               $changes{$itemid} = 1;
                           }
                       } else {
                           $changes{$itemid} = 1;
                       }
                       foreach my $extra ('passback','roster') {
                           if ($env{'form.ltitools_'.$extra.'_'.$i}) {
                               $confhash{$itemid}{$extra} = 1;
                           }
                           if ($domconfig{$action}{$itemid}{$extra} ne $confhash{$itemid}{$extra}) {
                               $changes{$itemid} = 1;
                           }
                       }
                       my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig_'.$i);
                       foreach my $item ('label','title','target','linktext','explanation') {
                           if (grep(/^\Q$item\E$/,@courseconfig)) {
                               $confhash{$itemid}{'crsconf'}{$item} = 1;
                               if (ref($domconfig{$action}{$itemid}{'crsconf'}) eq 'HASH') {
                                   if ($domconfig{$action}{$itemid}{'crsconf'}{$item} ne $confhash{$itemid}{'crsconf'}{$item}) {
                                       $changes{$itemid} = 1;
                                   }
                               } else {
                                   $changes{$itemid} = 1;
                               }
                           }
                       }
                       my @fields = &Apache::loncommon::get_env_multiple('form.ltitools_fields_'.$i);
                       foreach my $field (@fields) {
                           if ($possfield{$field}) {
                               if ($field eq 'roles') {
                                   foreach my $role (@courseroles) {
                                       my $choice = $env{'form.ltitools_roles_'.$role.'_'.$i};
                                       if (($choice ne '') && ($posslti{$choice})) {
                                           $confhash{$itemid}{'roles'}{$role} = $choice;
                                           if ($role eq 'cc') {
                                               $confhash{$itemid}{'roles'}{'co'} = $choice;
                                           }
                                       }
                                       if (ref($domconfig{$action}{$itemid}{'roles'}) eq 'HASH') {
                                           if ($domconfig{$action}{$itemid}{'roles'}{$role} ne $confhash{$itemid}{'roles'}{$role}) {
                                               $changes{$itemid} = 1;
                                           }
                                       } elsif ($confhash{$itemid}{'roles'}{$role}) {
                                           $changes{$itemid} = 1;
                                       }
                                   }
                               } else {
                                   $confhash{$itemid}{'fields'}{$field} = 1;
                                   if (ref($domconfig{$action}{$itemid}{'fields'}) eq 'HASH') {
                                       if ($domconfig{$action}{$itemid}{'fields'}{$field} ne $confhash{$itemid}{'fields'}{$field}) {
                                           $changes{$itemid} = 1;
                                       }
                                   } else {
                                       $changes{$itemid} = 1;
                                   }
                               }
                           }
                       }
                       $allpos[$newpos] = $itemid;
                   }
                   if ($imgdeletions{$itemid}) {
                       $changes{$itemid} = 1;
                       #FIXME need to obsolete item in RES space
                   } elsif ($env{'form.ltitools_image_'.$i.'.filename'}) {
                       my ($imgurl,$error) = &process_ltitools_image($r,$dom,$confname,'ltitools_image_'.$i,
                                                                    $itemid,$configuserok,$switchserver,
                                                                    $author_ok);
                       if ($imgurl) {
                           $confhash{$itemid}{'image'} = $imgurl;
                           $changes{$itemid} = 1;
                       }
                       if ($error) {
                           &Apache::lonnet::logthis($error);
                           $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
                       }
                   } elsif ($domconfig{$action}{$itemid}{'image'}) {
                       $confhash{$itemid}{'image'} =
                          $domconfig{$action}{$itemid}{'image'};
                   }
                   if ($customadds{$i}) {
                       my $name = $env{'form.ltitools_custom_name_'.$i};
                       $name =~ s/(`)/'/g;
                       $name =~ s/^\s+//;
                       $name =~ s/\s+$//;
                       my $value = $env{'form.ltitools_custom_value_'.$i};
                       $value =~ s/(`)/'/g;
                       $value =~ s/^\s+//;
                       $value =~ s/\s+$//;
                       if ($name ne '') {
                           $confhash{$itemid}{'custom'}{$name} = $value;
                           $changes{$itemid} = 1;
                       }
                   }
                   my %customdels;
                   my @customdeletions = &Apache::loncommon::get_env_multiple('form.ltitools_customdel_'.$i); 
                   if (@customdeletions) {
                       $changes{$itemid} = 1;
                   }
                   map { $customdels{$_} = 1; } @customdeletions;
                   if (ref($domconfig{$action}{$itemid}{'custom'}) eq 'HASH') {
                       foreach my $key (keys(%{$domconfig{$action}{$itemid}{'custom'}})) {
                           unless ($customdels{$key}) {
                               if ($env{'form.ltitools_customval_'.$key.'_'.$i} ne '') {
                                   $confhash{$itemid}{'custom'}{$key} = $env{'form.ltitools_customval_'.$key.'_'.$i}; 
                               }
                               if ($domconfig{$action}{$itemid}{'custom'}{$key} ne $env{'form.ltitools_customval_'.$key.'_'.$i}) {
                                   $changes{$itemid} = 1;
                               }
                           }
                       }
                   }
                   unless ($changes{$itemid}) {
                       foreach my $key (keys(%{$domconfig{$action}{$itemid}})) {
                           if (ref($domconfig{$action}{$itemid}{$key}) eq 'HASH') {
                               if (ref($confhash{$itemid}{$key}) eq 'HASH') {
                                   foreach my $innerkey (keys(%{$domconfig{$action}{$itemid}{$key}})) {
                                       unless (exists($confhash{$itemid}{$key}{$innerkey})) {
                                           $changes{$itemid} = 1;
                                           last;
                                       }
                                   }
                               } elsif (keys(%{$domconfig{$action}{$itemid}{$key}}) > 0) {
                                   $changes{$itemid} = 1;
                               }
                           }
                           last if ($changes{$itemid});
                       }
                   }
               }
           }
       }
       if (@allpos > 0) {
           my $idx = 0;
           foreach my $itemid (@allpos) {
               if ($itemid ne '') {
                   $confhash{$itemid}{'order'} = $idx;
                   if (ref($domconfig{$action}) eq 'HASH') {
                       if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
                           if ($domconfig{$action}{$itemid}{'order'} ne $idx) {
                               $changes{$itemid} = 1;
                           }
                       }
                   }
                   $idx ++;
               }
           }
       }
       my %ltitoolshash = (
                             $action => { %confhash }
                          );
       my $putresult = &Apache::lonnet::put_dom('configuration',\%ltitoolshash,
                                                $dom);
       if ($putresult eq 'ok') {
           my %ltienchash = (
                                $action => { %encconfig }
                            );
           &Apache::lonnet::put_dom('encconfig',\%ltienchash,$dom);
           if (keys(%changes) > 0) {
               my $cachetime = 24*60*60;
               my %ltiall = %confhash;
               foreach my $id (keys(%ltiall)) {
                   if (ref($encconfig{$id}) eq 'HASH') {
                       foreach my $item ('key','secret') {
                           $ltiall{$id}{$item} = $encconfig{$id}{$item};
                       }
                   }
               }
               &Apache::lonnet::do_cache_new('ltitools',$dom,\%ltiall,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'ltitools'} = 1;
               }
               $resulttext = &mt('Changes made:').'<ul>';
               my %bynum;
               foreach my $itemid (sort(keys(%changes))) {
                   my $position = $confhash{$itemid}{'order'};
                   $bynum{$position} = $itemid;
               }
               foreach my $pos (sort { $a <=> $b } keys(%bynum)) {
                   my $itemid = $bynum{$pos}; 
                   if (ref($confhash{$itemid}) ne 'HASH') {
                       $resulttext .= '<li>'.&mt('Deleted: [_1]',$changes{$itemid}).'</li>';
                   } else {
                       $resulttext .= '<li><b>'.$confhash{$itemid}{'title'}.'</b>';
                       if ($confhash{$itemid}{'image'}) {
                           $resulttext .= '&nbsp;'.
                                          '<img src="'.$confhash{$itemid}{'image'}.'"'.
                                          ' alt="'.&mt('Tool Provider icon').'" />';
                       }
                       $resulttext .= '</li><ul>';
                       my $position = $pos + 1;
                       $resulttext .= '<li>'.&mt('Order: [_1]',$position).'</li>';
                       foreach my $item ('version','msgtype','url') {
                           if ($confhash{$itemid}{$item} ne '') {
                               $resulttext .= '<li>'.$lt{$item}.':&nbsp;'.$confhash{$itemid}{$item}.'</li>';
                           }
                       }
                       if ($encconfig{$itemid}{'key'} ne '') {
                           $resulttext .= '<li>'.$lt{'key'}.':&nbsp;'.$encconfig{$itemid}{'key'}.'</li>';
                       }
                       if ($encconfig{$itemid}{'secret'} ne '') {
                           $resulttext .= '<li>'.$lt{'secret'}.':&nbsp;';
                           my $num = length($encconfig{$itemid}{'secret'});
                           $resulttext .= ('*'x$num).'</li>';
                       }
                       $resulttext .= '<li>'.&mt('Configurable in course:');
                       my @possconfig = ('label','title','target','linktext','explanation');
                       my $numconfig = 0; 
                       if (ref($confhash{$itemid}{'crsconf'}) eq 'HASH') { 
                           foreach my $item (@possconfig) {
                               if ($confhash{$itemid}{'crsconf'}{$item}) {
                                   $numconfig ++;
                                   $resulttext .= ' "'.$lt{'crs'.$item}.'"';
                               }
                           }
                       }
                       if (!$numconfig) {
                           $resulttext .= &mt('None');
                       }
                       $resulttext .= '</li>';
                       foreach my $item ('passback','roster') {
                           $resulttext .= '<li>'.$lt{$item}.'&nbsp;';
                           if ($confhash{$itemid}{$item}) {
                               $resulttext .= &mt('Yes');
                           } else {
                               $resulttext .= &mt('No');
                           }
                           $resulttext .= '</li>';
                       }
                       if (ref($confhash{$itemid}{'display'}) eq 'HASH') {
                           my $displaylist;
                           if ($confhash{$itemid}{'display'}{'target'}) {
                               $displaylist = &mt('Display target').':&nbsp;'.
                                              $confhash{$itemid}{'display'}{'target'}.',';
                           }
                           foreach my $size ('width','height') { 
                               if ($confhash{$itemid}{'display'}{$size}) {
                                   $displaylist .= ('&nbsp;'x2).$lt{$size}.':&nbsp;'.
                                                   $confhash{$itemid}{'display'}{$size}.',';
                               }
                           }
                           if ($displaylist) {
                               $displaylist =~ s/,$//;
                               $resulttext .= '<li>'.$displaylist.'</li>';
                           }
                           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') {
                           my $fieldlist;
                           foreach my $field (@allfields) {
                               if ($confhash{$itemid}{'fields'}{$field}) {
                                   $fieldlist .= ('&nbsp;'x2).$lt{$field}.',';
                               }
                           }
                           if ($fieldlist) {
                               $fieldlist =~ s/,$//;
                               $resulttext .= '<li>'.&mt('Data sent').':'.$fieldlist.'</li>';
                           }
                       }
                       if (ref($confhash{$itemid}{'roles'}) eq 'HASH') {
                           my $rolemaps;
                           foreach my $role (@courseroles) {
                               if ($confhash{$itemid}{'roles'}{$role}) {
                                   $rolemaps .= ('&nbsp;'x2).&Apache::lonnet::plaintext($role,'Course').'='.
                                                $confhash{$itemid}{'roles'}{$role}.',';
                               }
                           }
                           if ($rolemaps) {
                               $rolemaps =~ s/,$//; 
                               $resulttext .= '<li>'.&mt('Role mapping:').$rolemaps.'</li>';
                           }
                       }
                       if (ref($confhash{$itemid}{'custom'}) eq 'HASH') {
                           my $customlist;
                           if (keys(%{$confhash{$itemid}{'custom'}})) {
                               foreach my $key (sort(keys(%{$confhash{$itemid}{'custom'}}))) {
                                   $customlist .= $key.':'.$confhash{$itemid}{'custom'}{$key}.('&nbsp;'x2);
                               } 
                           }
                           if ($customlist) {
                               $resulttext .= '<li>'.&mt('Custom items').':'.$customlist.'</li>';
                           }
                       } 
                       $resulttext .= '</ul></li>';
                   }
               }
               $resulttext .= '</ul>';
           } else {
               $resulttext = &mt('No changes made.');
           }
       } else {
           $errors .= '<li><span class="LC_error">'.&mt('Failed to save changes').'</span></li>';
       }
       if ($errors) {
           $resulttext .= &mt('The following errors occurred: ').'<ul>'.
                          $errors.'</ul>';
       }
       return $resulttext;
   }
   
   sub process_ltitools_image {
       my ($r,$dom,$confname,$caller,$itemid,$configuserok,$switchserver,$author_ok) = @_;
       my $filename = $env{'form.'.$caller.'.filename'};
       my ($error,$url);
       my ($width,$height) = (21,21);
       if ($configuserok eq 'ok') {
           if ($switchserver) {
               $error = &mt('Upload of Tool Provider (LTI) icon is not permitted to this server: [_1]',
                            $switchserver);
           } elsif ($author_ok eq 'ok') {
               my ($result,$imageurl,$madethumb) =
                   &publishlogo($r,'upload',$caller,$dom,$confname,
                                "ltitools/$itemid/icon",$width,$height);
               if ($result eq 'ok') {
                   if ($madethumb) {
                       my ($path,$imagefile) = ($imageurl =~ m{^(.+)/([^/]+)$});
                       my $imagethumb = "$path/tn-".$imagefile;
                       $url = $imagethumb;
                   } else {
                       $url = $imageurl;
                   }
               } else {
                   $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$result);
               }
           } else {
               $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3].  Error was: [_4].",$filename,$confname,$dom,$author_ok);
           }
       } else {
           $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3].  Error was: [_4].",$filename,$confname,$dom,$configuserok);
       }
       return ($url,$error);
   }
   
   sub get_ltitools_id {
       my ($cdom,$title) = @_;
       # get lock on ltitools db
       my $lockhash = {
                         lock => $env{'user.name'}.
                                 ':'.$env{'user.domain'},
                      };
       my $tries = 0;
       my $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
       my ($id,$error);
    
       while (($gotlock ne 'ok') && ($tries<10)) {
           $tries ++;
           sleep (0.1);
           $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
       }
       if ($gotlock eq 'ok') {
           my %currids = &Apache::lonnet::dump_dom('ltitools',$cdom);
           if ($currids{'lock'}) {
               delete($currids{'lock'});
               if (keys(%currids)) {
                   my @curr = sort { $a <=> $b } keys(%currids);
                   if ($curr[-1] =~ /^\d+$/) {
                       $id = 1 + $curr[-1];
                   }
               } else {
                   $id = 1;
               }
               if ($id) {
                   unless (&Apache::lonnet::newput_dom('ltitools',{ $id => $title },$cdom) eq 'ok') {
                       $error = 'nostore';
                   }
               } else {
                   $error = 'nonumber';
               }
           }
           my $dellockoutcome = &Apache::lonnet::del_dom('ltitools',['lock'],$cdom);
       } else {
           $error = 'nolock';
       }
       return ($id,$error);
   }
   
 sub modify_autoenroll {  sub modify_autoenroll {
     my ($dom,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,%changes);      my ($resulttext,%changes);
     my %currautoenroll;      my %currautoenroll;
     if (ref($domconfig{'autoenroll'}) eq 'HASH') {      if (ref($domconfig{'autoenroll'}) eq 'HASH') {
Line 5874  sub modify_autoenroll { Line 10188  sub modify_autoenroll {
     my $autorun = &Apache::lonnet::auto_run(undef,$dom),      my $autorun = &Apache::lonnet::auto_run(undef,$dom),
     my %title = ( run => 'Auto-enrollment active',      my %title = ( run => 'Auto-enrollment active',
                   sender => 'Sender for notification messages',                    sender => 'Sender for notification messages',
                   coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)');                    coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)',
                     failsafe => 'Failsafe for no drops if institutional data missing for a section');
     my @offon = ('off','on');      my @offon = ('off','on');
     my $sender_uname = $env{'form.sender_uname'};      my $sender_uname = $env{'form.sender_uname'};
     my $sender_domain = $env{'form.sender_domain'};      my $sender_domain = $env{'form.sender_domain'};
Line 5884  sub modify_autoenroll { Line 10199  sub modify_autoenroll {
         $sender_domain = '';          $sender_domain = '';
     }      }
     my $coowners = $env{'form.autoassign_coowners'};      my $coowners = $env{'form.autoassign_coowners'};
       my $failsafe = $env{'form.autoenroll_failsafe'};
       $failsafe =~ s{^\s+|\s+$}{}g;
       if ($failsafe =~ /\D/) {
           undef($failsafe);
       }
     my %autoenrollhash =  (      my %autoenrollhash =  (
                        autoenroll => { 'run' => $env{'form.autoenroll_run'},                         autoenroll => { 'run' => $env{'form.autoenroll_run'},
                                        'sender_uname' => $sender_uname,                                         'sender_uname' => $sender_uname,
                                        'sender_domain' => $sender_domain,                                         'sender_domain' => $sender_domain,
                                        'co-owners' => $coowners,                                         'co-owners' => $coowners,
                                          'autofailsafe' => $failsafe,
                                 }                                  }
                      );                       );
     my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,
Line 5915  sub modify_autoenroll { Line 10236  sub modify_autoenroll {
             }              }
         } elsif ($coowners) {          } elsif ($coowners) {
             $changes{'coowners'} = 1;              $changes{'coowners'} = 1;
         }                }
           if ($currautoenroll{'autofailsafe'} ne $failsafe) {
               $changes{'autofailsafe'} = 1;
           }
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if ($changes{'run'}) {              if ($changes{'run'}) {
Line 5931  sub modify_autoenroll { Line 10255  sub modify_autoenroll {
             if ($changes{'coowners'}) {              if ($changes{'coowners'}) {
                 $resulttext .= '<li>'.&mt("$title{'coowners'} set to $offon[$env{'form.autoassign_coowners'}]").'</li>';                  $resulttext .= '<li>'.&mt("$title{'coowners'} set to $offon[$env{'form.autoassign_coowners'}]").'</li>';
                 &Apache::loncommon::devalidate_domconfig_cache($dom);                  &Apache::loncommon::devalidate_domconfig_cache($dom);
                   if (ref($lastactref) eq 'HASH') {
                       $lastactref->{'domainconfig'} = 1;
                   }
               }
               if ($changes{'autofailsafe'}) {
                   if ($failsafe ne '') {
                       $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section set to: [_1]',$failsafe).'</li>';
                   } else {
                       $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section: deleted');
                   }
                   &Apache::lonnet::get_domain_defaults($dom,1);
                   if (ref($lastactref) eq 'HASH') {
                       $lastactref->{'domdefaults'} = 1;
                   }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
Line 6147  sub modify_autocreate { Line 10485  sub modify_autocreate {
         $newvals{$item} = 0 if ($newvals{$item} eq '');          $newvals{$item} = 0 if ($newvals{$item} eq '');
     }      }
     $newvals{'xmldc'} = $env{'form.autocreate_xmldc'};      $newvals{'xmldc'} = $env{'form.autocreate_xmldc'};
     my %domcoords = &get_active_dcs($dom);      my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);
     unless (exists($domcoords{$newvals{'xmldc'}})) {      unless (exists($domcoords{$newvals{'xmldc'}})) {
         $newvals{'xmldc'} = '';          $newvals{'xmldc'} = '';
     }       } 
Line 6181  sub modify_autocreate { Line 10519  sub modify_autocreate {
             foreach my $item (@types) {              foreach my $item (@types) {
                 if ($changes{$item}) {                  if ($changes{$item}) {
                     my $newtxt = $offon[$newvals{$item}];                      my $newtxt = $offon[$newvals{$item}];
                     $resulttext .= '<li>'.&mt("$title{$item} set to [_1]$newtxt [_2]",'<b>','</b>').'</li>';                      $resulttext .= '<li>'.
                                      &mt("$title{$item} set to [_1]$newtxt [_2]",
                                          '<b>','</b>').
                                      '</li>';
                 }                  }
             }              }
             if ($changes{'xmldc'}) {              if ($changes{'xmldc'}) {
                 my ($dcname,$dcdom) = split(':',$newvals{'xmldc'});                  my ($dcname,$dcdom) = split(':',$newvals{'xmldc'});
                 my $newtxt = &Apache::loncommon::plainname($dcname,$dcdom);                  my $newtxt = &Apache::loncommon::plainname($dcname,$dcdom);
                 $resulttext .= '<li>'.&mt("$title{'xmldc'} set to [_1]$newtxt [_2]",'<b>','</b>').'</li>';                   $resulttext .= '<li>'.&mt("$title{'xmldc'} set to [_1]",'<b>'.$newtxt.'</b>').'</li>'; 
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
Line 6201  sub modify_autocreate { Line 10542  sub modify_autocreate {
 }  }
   
 sub modify_directorysrch {  sub modify_directorysrch {
     my ($dom,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,%changes);      my ($resulttext,%changes);
     my %currdirsrch;      my %currdirsrch;
     if (ref($domconfig{'directorysrch'}) eq 'HASH') {      if (ref($domconfig{'directorysrch'}) eq 'HASH') {
Line 6209  sub modify_directorysrch { Line 10550  sub modify_directorysrch {
             $currdirsrch{$key} = $domconfig{'directorysrch'}{$key};              $currdirsrch{$key} = $domconfig{'directorysrch'}{$key};
         }          }
     }      }
     my %title = ( available => 'Directory search available',      my %title = ( available => 'Institutional directory search available',
                   localonly => 'Other domains can search',                    localonly => 'Other domains can search institution',
                     lcavailable => 'LON-CAPA directory search available',
                     lclocalonly => 'Other domains can search LON-CAPA domain',
                   searchby => 'Search types',                    searchby => 'Search types',
                   searchtypes => 'Search latitude');                    searchtypes => 'Search latitude');
     my @offon = ('off','on');      my @offon = ('off','on');
Line 6284  sub modify_directorysrch { Line 10627  sub modify_directorysrch {
     my %dirsrch_hash =  (      my %dirsrch_hash =  (
             directorysrch => { available => $env{'form.dirsrch_available'},              directorysrch => { available => $env{'form.dirsrch_available'},
                                cansearch => \@cansearch,                                 cansearch => \@cansearch,
                                localonly => $env{'form.dirsrch_localonly'},                                 localonly => $env{'form.dirsrch_instlocalonly'},
                                  lclocalonly => $env{'form.dirsrch_domlocalonly'},
                                  lcavailable => $env{'form.dirsrch_domavailable'},
                                searchby => \@searchby,                                 searchby => \@searchby,
                                searchtypes => \@searchtypes,                                 searchtypes => \@searchtypes,
                              }                               }
Line 6301  sub modify_directorysrch { Line 10646  sub modify_directorysrch {
                 $changes{'available'} = 1;                  $changes{'available'} = 1;
             }              }
         }          }
           if (exists($currdirsrch{'lcavailable'})) {
               if ($currdirsrch{'lcavailable'} ne $env{'form.dirsrch_domavailable'}) {
                   $changes{'lcavailable'} = 1;
               }
           } else {
               if ($env{'form.dirsrch_lcavailable'} eq '1') {
                   $changes{'lcavailable'} = 1;
               }
           }
         if (exists($currdirsrch{'localonly'})) {          if (exists($currdirsrch{'localonly'})) {
              if ($currdirsrch{'localonly'} ne $env{'form.dirsrch_localonly'}) {              if ($currdirsrch{'localonly'} ne $env{'form.dirsrch_instlocalonly'}) {
                  $changes{'localonly'} = 1;                  $changes{'localonly'} = 1;
              }              }
         } else {          } else {
             if ($env{'form.dirsrch_localonly'} eq '1') {              if ($env{'form.dirsrch_instlocalonly'} eq '1') {
                 $changes{'localonly'} = 1;                  $changes{'localonly'} = 1;
             }              }
         }          }
           if (exists($currdirsrch{'lclocalonly'})) {
               if ($currdirsrch{'lclocalonly'} ne $env{'form.dirsrch_domlocalonly'}) {
                   $changes{'lclocalonly'} = 1;
               }
           } else {
               if ($env{'form.dirsrch_domlocalonly'} eq '1') {
                   $changes{'lclocalonly'} = 1;
               }
           }
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if ($changes{'available'}) {              if ($changes{'available'}) {
                 $resulttext .= '<li>'.&mt("$title{'available'} set to: $offon[$env{'form.dirsrch_available'}]").'</li>';                  $resulttext .= '<li>'.&mt("$title{'available'} set to: $offon[$env{'form.dirsrch_available'}]").'</li>';
             }              }
               if ($changes{'lcavailable'}) {
                   $resulttext .= '<li>'.&mt("$title{'lcavailable'} set to: $offon[$env{'form.dirsrch_domavailable'}]").'</li>';
               }
             if ($changes{'localonly'}) {              if ($changes{'localonly'}) {
                 $resulttext .= '<li>'.&mt("$title{'localonly'} set to: $otherdoms[$env{'form.dirsrch_localonly'}]").'</li>';                  $resulttext .= '<li>'.&mt("$title{'localonly'} set to: $otherdoms[$env{'form.dirsrch_instlocalonly'}]").'</li>';
               }
               if ($changes{'lclocalonly'}) {
                   $resulttext .= '<li>'.&mt("$title{'lclocalonly'} set to: $otherdoms[$env{'form.dirsrch_domlocalonly'}]").'</li>';
             }              }
   
             if (ref($changes{'cansearch'}) eq 'ARRAY') {              if (ref($changes{'cansearch'}) eq 'ARRAY') {
                 my $chgtext;                  my $chgtext;
                 if (ref($usertypes) eq 'HASH') {                  if (ref($usertypes) eq 'HASH') {
Line 6333  sub modify_directorysrch { Line 10701  sub modify_directorysrch {
                         } else {                          } else {
                             $chgtext =~ s/\; $//;                              $chgtext =~ s/\; $//;
                         }                          }
                         $resulttext .= '<li>'.&mt("Users from domain '<span class=\"LC_cusr_emph\">[_1]</span>' permitted to search the institutional directory set to: [_2]",$dom,$chgtext).'</li>';                          $resulttext .=
                               '<li>'.
                               &mt("Users from domain '[_1]' permitted to search the institutional directory set to: [_2]",
                                   '<span class="LC_cusr_emph">'.$dom.'</span>',$chgtext).
                               '</li>';
                     }                      }
                 }                  }
             }              }
Line 6361  sub modify_directorysrch { Line 10733  sub modify_directorysrch {
                     }                      }
                 }                  }
                 $chgtext =~ s/\; $//;                  $chgtext =~ s/\; $//;
                 $resulttext .= '<li>'.&mt("$title{'searchtypes'} set to: \"[_1]\"",$chgtext).'</li>';                  $resulttext .= '<li>'.&mt($title{'searchtypes'}.' set to: "[_1]"',$chgtext).'</li>';
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
               &Apache::lonnet::do_cache_new('directorysrch',$dom,$dirsrch_hash{'directorysrch'},3600);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'directorysrch'} = 1;
               }
         } else {          } else {
             $resulttext = &mt('No changes made to institution directory search settings');              $resulttext = &mt('No changes made to directory search settings');
         }          }
     } else {      } else {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
Line 6375  sub modify_directorysrch { Line 10751  sub modify_directorysrch {
 }  }
   
 sub modify_contacts {  sub modify_contacts {
     my ($dom,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,%currsetting,%newsetting,%changes,%contacts_hash);      my ($resulttext,%currsetting,%newsetting,%changes,%contacts_hash);
     if (ref($domconfig{'contacts'}) eq 'HASH') {      if (ref($domconfig{'contacts'}) eq 'HASH') {
         foreach my $key (keys(%{$domconfig{'contacts'}})) {          foreach my $key (keys(%{$domconfig{'contacts'}})) {
             $currsetting{$key} = $domconfig{'contacts'}{$key};              $currsetting{$key} = $domconfig{'contacts'}{$key};
         }          }
     }      }
     my (%others,%to,%bcc);      my (%others,%to,%bcc,%includestr,%includeloc);
     my @contacts = ('supportemail','adminemail');      my @contacts = ('supportemail','adminemail');
     my @mailings = ('errormail','packagesmail','helpdeskmail','lonstatusmail',      my @mailings = ('errormail','packagesmail','helpdeskmail','otherdomsmail',
                     'requestsmail');                      'lonstatusmail','requestsmail','updatesmail','idconflictsmail');
       my @toggles = ('reporterrors','reportupdates');
       my ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();
     foreach my $type (@mailings) {      foreach my $type (@mailings) {
         @{$newsetting{$type}} =           @{$newsetting{$type}} = 
             &Apache::loncommon::get_env_multiple('form.'.$type);              &Apache::loncommon::get_env_multiple('form.'.$type);
Line 6395  sub modify_contacts { Line 10773  sub modify_contacts {
             } else {              } else {
                 $contacts_hash{contacts}{$type}{$item} = 0;                  $contacts_hash{contacts}{$type}{$item} = 0;
             }              }
         }            }
         $others{$type} = $env{'form.'.$type.'_others'};          $others{$type} = $env{'form.'.$type.'_others'};
         $contacts_hash{contacts}{$type}{'others'} = $others{$type};          $contacts_hash{contacts}{$type}{'others'} = $others{$type};
         if ($type eq 'helpdeskmail') {          if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
             $bcc{$type} = $env{'form.'.$type.'_bcc'};              $bcc{$type} = $env{'form.'.$type.'_bcc'};
             $contacts_hash{contacts}{$type}{'bcc'} = $bcc{$type};              $contacts_hash{contacts}{$type}{'bcc'} = $bcc{$type};
               if (($env{'form.'.$type.'_includestr'} ne '') && ($env{'form.'.$type.'_includeloc'} =~ /^s|b$/)) {
                   $includestr{$type} = $env{'form.'.$type.'_includestr'};
                   $includeloc{$type} = $env{'form.'.$type.'_includeloc'};
                   $contacts_hash{contacts}{$type}{'include'} = $includeloc{$type}.':'.&escape($includestr{$type});
               }
         }          }
     }      }
     foreach my $item (@contacts) {      foreach my $item (@contacts) {
         $to{$item} = $env{'form.'.$item};          $to{$item} = $env{'form.'.$item};
         $contacts_hash{'contacts'}{$item} = $to{$item};          $contacts_hash{'contacts'}{$item} = $to{$item};
     }      }
       foreach my $item (@toggles) {
           if ($env{'form.'.$item} =~ /^(0|1)$/) {
               $contacts_hash{'contacts'}{$item} = $env{'form.'.$item};
           }
       }
       if ((ref($fields) eq 'ARRAY') && (ref($possoptions) eq 'HASH')) {
           foreach my $field (@{$fields}) {
               if (ref($possoptions->{$field}) eq 'ARRAY') {
                   my $value = $env{'form.helpform_'.$field};
                   $value =~ s/^\s+|\s+$//g;
                   if (grep(/^\Q$value\E$/,@{$possoptions->{$field}})) {
                       $contacts_hash{contacts}{'helpform'}{$field} = $value;
                       if ($field eq 'screenshot') {
                           $env{'form.helpform_maxsize'} =~ s/^\s+|\s+$//g;
                           if ($env{'form.helpform_maxsize'} =~ /^\d+\.?\d*$/) {
                               $contacts_hash{contacts}{'helpform'}{'maxsize'} = $env{'form.helpform_maxsize'};
                           }
                       }
                   }
               }
           }
       }
     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 6426  sub modify_contacts { Line 10831  sub modify_contacts {
             if ($others{$type} ne $currsetting{$type}{'others'}) {              if ($others{$type} ne $currsetting{$type}{'others'}) {
                 push(@{$changes{$type}},'others');                  push(@{$changes{$type}},'others');
             }              }
             if ($type eq 'helpdeskmail') {                 if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                 if ($bcc{$type} ne $currsetting{$type}{'bcc'}) {                  if ($bcc{$type} ne $currsetting{$type}{'bcc'}) {
                     push(@{$changes{$type}},'bcc');                       push(@{$changes{$type}},'bcc'); 
                 }                  }
                   my ($currloc,$currstr) = split(/:/,$currsetting{$type}{'include'},2);
                   if (($includeloc{$type} ne $currloc) || (&escape($includestr{$type}) ne $currstr)) {
                       push(@{$changes{$type}},'include');
                   }
               }
           }
           if (ref($fields) eq 'ARRAY') {
               if (ref($currsetting{'helpform'}) eq 'HASH') {
                   foreach my $field (@{$fields}) {
                       if ($currsetting{'helpform'}{$field} ne $contacts_hash{'contacts'}{'helpform'}{$field}) {
                           push(@{$changes{'helpform'}},$field);
                       }
                       if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {
                           if ($currsetting{'helpform'}{'maxsize'} ne $contacts_hash{'contacts'}{'helpform'}{'maxsize'}) {
                               push(@{$changes{'helpform'}},'maxsize');
                           }
                       }
                   }
               } else {
                   foreach my $field (@{$fields}) {
                       if ($contacts_hash{'contacts'}{'helpform'}{$field} ne 'yes') {
                           push(@{$changes{'helpform'}},$field);
                       }
                       if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {
                           if ($contacts_hash{'contacts'}{'helpform'}{'maxsize'} != 1) {
                               push(@{$changes{'helpform'}},'maxsize');
                           }
                       }
                   }
             }              }
         }          }
     } else {      } else {
Line 6439  sub modify_contacts { Line 10873  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';
         foreach my $item (@contacts) {          foreach my $item (@contacts) {
            if ($to{$item} ne $default{$item}) {             if ($to{$item} ne $default{$item}) {
               $changes{$item} = 1;                 $changes{$item} = 1;
            }              }
         }          }
         foreach my $type (@mailings) {          foreach my $type (@mailings) {
             if ((@{$newsetting{$type}} != 1) || ($newsetting{$type}[0] ne $default{$type})) {              if ((@{$newsetting{$type}} != 1) || ($newsetting{$type}[0] ne $default{$type})) {
                  
                 push(@{$changes{$type}},@{$newsetting{$type}});                  push(@{$changes{$type}},@{$newsetting{$type}});
             }              }
             if ($others{$type} ne '') {              if ($others{$type} ne '') {
                 push(@{$changes{$type}},'others');                  push(@{$changes{$type}},'others');
             }              }
             if ($type eq 'helpdeskmail') {              if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                 if ($bcc{$type} ne '') {                  if ($bcc{$type} ne '') {
                     push(@{$changes{$type}},'bcc');                      push(@{$changes{$type}},'bcc');
                 }                  }
                   if (($includeloc{$type} =~ /^b|s$/) && ($includestr{$type} ne '')) {
                       push(@{$changes{$type}},'include');
                   }
             }              }
         }          }
           if (ref($fields) eq 'ARRAY') {
               foreach my $field (@{$fields}) {
                   if ($contacts_hash{'contacts'}{'helpform'}{$field} ne 'yes') {
                       push(@{$changes{'helpform'}},$field);
                   }
                   if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {
                       if ($contacts_hash{'contacts'}{'helpform'}{'maxsize'} != 1) {
                           push(@{$changes{'helpform'}},'maxsize');
                       }
                   }
               }
           }
       }
       foreach my $item (@toggles) {
           if (($env{'form.'.$item} == 1) && ($currsetting{$item} == 0)) {
               $changes{$item} = 1;
           } elsif ((!$env{'form.'.$item}) &&
                    (($currsetting{$item} eq '') || ($currsetting{$item} == 1))) {
               $changes{$item} = 1;
           }
     }      }
     my $putresult = &Apache::lonnet::put_dom('configuration',\%contacts_hash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%contacts_hash,
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
               &Apache::loncommon::devalidate_domconfig_cache($dom);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domainconfig'} = 1;
               }
             my ($titles,$short_titles)  = &contact_titles();              my ($titles,$short_titles)  = &contact_titles();
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             foreach my $item (@contacts) {              foreach my $item (@contacts) {
Line 6477  sub modify_contacts { Line 10939  sub modify_contacts {
             }              }
             foreach my $type (@mailings) {              foreach my $type (@mailings) {
                 if (ref($changes{$type}) eq 'ARRAY') {                  if (ref($changes{$type}) eq 'ARRAY') {
                     $resulttext .= '<li>'.$titles->{$type}.': ';                      if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                           $resulttext .= '<li>'.$titles->{$type}.' -- '.&mt('sent to').': ';
                       } else {
                           $resulttext .= '<li>'.$titles->{$type}.': ';
                       }
                     my @text;                      my @text;
                     foreach my $item (@{$newsetting{$type}}) {                      foreach my $item (@{$newsetting{$type}}) {
                         push(@text,$short_titles->{$item});                          push(@text,$short_titles->{$item});
Line 6485  sub modify_contacts { Line 10951  sub modify_contacts {
                     if ($others{$type} ne '') {                      if ($others{$type} ne '') {
                         push(@text,$others{$type});                          push(@text,$others{$type});
                     }                      }
                     $resulttext .= '<span class="LC_cusr_emph">'.                      if (@text) {
                                    join(', ',@text).'</span>';                          $resulttext .= '<span class="LC_cusr_emph">'.
                     if ($type eq 'helpdeskmail') {                                         join(', ',@text).'</span>';
                       }
                       if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
                         if ($bcc{$type} ne '') {                          if ($bcc{$type} ne '') {
                             $resulttext .= '&nbsp;'.&mt('with Bcc to').': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';                              my $bcctext;
                               if (@text) {
                                   $bcctext = '&nbsp;'.&mt('with Bcc to');
                               } else {
                                   $bcctext = '(Bcc)';
                               }
                               $resulttext .= $bcctext.': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';
                           } elsif (!@text) {
                               $resulttext .= &mt('No one');
                           }   
                           if ($includestr{$type} ne '') {
                               if ($includeloc{$type} eq 'b') {
                                   $resulttext .= '<br />'.&mt('Text automatically added to e-mail body:').' '.$includestr{$type};
                               } elsif ($includeloc{$type} eq 's') {
                                   $resulttext .= '<br />'.&mt('Text automatically added to e-mail subject:').' '.$includestr{$type};
                               }
                         }                          }
                       } elsif (!@text) {
                           $resulttext .= &mt('No recipients');
                     }                      }
                     $resulttext .= '</li>';                      $resulttext .= '</li>';
                 }                  }
             }              }
               my @offon = ('off','on');
               if ($changes{'reporterrors'}) {
                   $resulttext .= '<li>'.
                                  &mt('E-mail error reports to [_1] set to "'.
                                      $offon[$env{'form.reporterrors'}].'".',
                                      &Apache::loncommon::modal_link('http://loncapa.org/core.html',
                                          &mt('LON-CAPA core group - MSU'),600,500)).
                                  '</li>';
               }
               if ($changes{'reportupdates'}) {
                   $resulttext .= '<li>'.
                                   &mt('E-mail record of completed LON-CAPA updates to [_1] set to "'.
                                       $offon[$env{'form.reportupdates'}].'".',
                                       &Apache::loncommon::modal_link('http://loncapa.org/core.html',
                                           &mt('LON-CAPA core group - MSU'),600,500)).
                                   '</li>';
               }
               if ((ref($changes{'helpform'}) eq 'ARRAY') && (ref($fields) eq 'ARRAY')) {
                   my (@optional,@required,@unused,$maxsizechg);
                   foreach my $field (@{$changes{'helpform'}}) {
                       if ($field eq 'maxsize') {
                           $maxsizechg = 1;
                           next;
                       }
                       if ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'yes') {
                           push(@optional,$field);
                       } elsif ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'no') {
                           push(@unused,$field);
                       } elsif ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'req') {
                           push(@required,$field);
                       }
                   }
                   if (@optional) {
                       $resulttext .= '<li>'.
                                      &mt('Help form fields changed to "Optional": [_1].',
                                          '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @optional)).'</span>'.
                                      '</li>';
                   }
                   if (@required) {
                       $resulttext .= '<li>'.
                                      &mt('Help form fields changed to "Required": [_1].',
                                          '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @required)).'</span>'.
                                      '</li>';
                   }
                   if (@unused) {
                       $resulttext .= '<li>'.
                                      &mt('Help form fields changed to "Not shown": [_1].',
                                          '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @unused)).'</span>'.
                                      '</li>';
                   }
                   if ($maxsizechg) {
                       $resulttext .= '<li>'.
                                      &mt('Max size for file uploaded to help form by logged-in user set to [_1] MB.',
                                          $contacts_hash{'contacts'}{'helpform'}{'maxsize'}).
                                      '</li>';
   
                   }
               }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
             $resulttext = &mt('No changes made to contact information');              $resulttext = &mt('No changes made to contacts and form settings');
         }          }
     } else {      } else {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
Line 6508  sub modify_contacts { Line 11051  sub modify_contacts {
   
 sub modify_usercreation {  sub modify_usercreation {
     my ($dom,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate);      my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate,%save_usercreate);
     my $warningmsg;      my $warningmsg;
     if (ref($domconfig{'usercreation'}) eq 'HASH') {      if (ref($domconfig{'usercreation'}) eq 'HASH') {
         foreach my $key (keys(%{$domconfig{'usercreation'}})) {          foreach my $key (keys(%{$domconfig{'usercreation'}})) {
             $curr_usercreation{$key} = $domconfig{'usercreation'}{$key};              if ($key eq 'cancreate') {
         }                  if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {
     }                      foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
     my @username_rule = &Apache::loncommon::get_env_multiple('form.username_rule');                          if (($item eq 'requestcrs') || ($item eq 'course') || ($item eq 'author')) {
     my @id_rule = &Apache::loncommon::get_env_multiple('form.id_rule');                              $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
     my @email_rule = &Apache::loncommon::get_env_multiple('form.email_rule');                          } else {
     my @contexts = ('author','course','requestcrs','selfcreate');                              $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
     foreach my $item(@contexts) {                          }
         if ($item eq 'selfcreate') {  
             @{$cancreate{$item}} = &Apache::loncommon::get_env_multiple('form.can_createuser_'.$item);  
             my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);  
             if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) || ($domdefaults{'auth_def'} eq 'localauth'))) {  
                 if (ref($cancreate{$item}) eq 'ARRAY') {   
                     if (grep(/^login$/,@{$cancreate{$item}})) {  
                         $warningmsg = &mt('Although account creation has been set to be available for institutional logins, currently default authentication in this domain has not been set to support this.').' '.&mt('You need to set the default authentication type to Kerberos 4 or 5 (with a Kerberos domain specified), or to Local authentication, if the localauth module has been customized in your domain to authenticate institutional logins.');     
                     }                      }
                 }                  }
               } elsif ($key eq 'email_rule') {
                   $save_usercreate{$key} = $domconfig{'usercreation'}{$key};
               } else {
                   $curr_usercreation{$key} = $domconfig{'usercreation'}{$key};
             }              }
         } else {  
             $cancreate{$item} = $env{'form.can_createuser_'.$item};  
         }          }
     }      }
     my ($othertitle,$usertypes,$types) =       my @username_rule = &Apache::loncommon::get_env_multiple('form.username_rule');
         &Apache::loncommon::sorted_inst_types($dom);      my @id_rule = &Apache::loncommon::get_env_multiple('form.id_rule');
     if (ref($types) eq 'ARRAY') {      my @contexts = ('author','course','requestcrs');
         if (@{$types} > 0) {      foreach my $item(@contexts) {
             @{$cancreate{'statustocreate'}} =           $cancreate{$item} = $env{'form.can_createuser_'.$item};
                 &Apache::loncommon::get_env_multiple('form.statustocreate');  
         } else {  
             @{$cancreate{'statustocreate'}} = ();  
         }  
         push(@contexts,'statustocreate');  
     }      }
     &process_captcha('cancreate',\%changes,\%cancreate,\%curr_usercreation);  
     if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {      if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {
         foreach my $item (@contexts) {          foreach my $item (@contexts) {
             if (($item eq 'selfcreate') || ($item eq 'statustocreate')) {              if ($curr_usercreation{'cancreate'}{$item} ne $cancreate{$item}) {
                 if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') {                  push(@{$changes{'cancreate'}},$item);
                     foreach my $curr (@{$curr_usercreation{'cancreate'}{$item}}) {  
                         if (ref($cancreate{$item}) eq 'ARRAY') {  
                             if (!grep(/^$curr$/,@{$cancreate{$item}})) {  
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                     push(@{$changes{'cancreate'}},$item);  
                                 }  
                             }  
                         }  
                     }  
                 } else {  
                     if ($curr_usercreation{'cancreate'}{$item} eq '') {  
                         if (@{$cancreate{$item}} > 0) {  
                             if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                 push(@{$changes{'cancreate'}},$item);  
                             }  
                         }  
                     } else {  
                         if ($curr_usercreation{'cancreate'}{$item} eq 'any') {  
                             if (@{$cancreate{$item}} < 3) {  
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                     push(@{$changes{'cancreate'}},$item);  
                                 }  
                             }  
                         } elsif ($curr_usercreation{'cancreate'}{$item} eq 'none') {  
                             if (@{$cancreate{$item}} > 0) {  
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                     push(@{$changes{'cancreate'}},$item);  
                                 }  
                             }  
                         } elsif (!grep(/^$curr_usercreation{'cancreate'}{$item}$/,@{$cancreate{$item}})) {  
                             if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                 push(@{$changes{'cancreate'}},$item);  
                             }  
                         }  
                     }  
                 }  
                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                     foreach my $type (@{$cancreate{$item}}) {  
                         if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') {  
                             if (!grep(/^$type$/,@{$curr_usercreation{'cancreate'}{$item}})) {  
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                     push(@{$changes{'cancreate'}},$item);  
                                 }  
                             }  
                         } elsif (($curr_usercreation{'cancreate'}{$item} ne 'any') &&  
                                  ($curr_usercreation{'cancreate'}{$item} ne 'none')) {  
                             if ($curr_usercreation{'cancreate'}{$item} ne $type) {  
                                 if (!grep(/^$item$/,@{$changes{'cancreate'}})) {  
                                     push(@{$changes{'cancreate'}},$item);  
                                 }  
                             }  
                         }  
                     }  
                 }  
             } else {  
                 if ($curr_usercreation{'cancreate'}{$item} ne $cancreate{$item}) {  
                     push(@{$changes{'cancreate'}},$item);  
                 }  
             }              }
         }          }
     } elsif (ref($curr_usercreation{'cancreate'}) eq 'ARRAY') {      } elsif (ref($curr_usercreation{'cancreate'}) eq 'ARRAY') {
Line 6658  sub modify_usercreation { Line 11132  sub modify_usercreation {
         push(@{$changes{'id_rule'}},@id_rule);          push(@{$changes{'id_rule'}},@id_rule);
     }      }
   
     if (ref($curr_usercreation{'email_rule'}) eq 'ARRAY') {  
         foreach my $type (@{$curr_usercreation{'email_rule'}}) {  
             if (!grep(/^\Q$type\E$/,@email_rule)) {  
                 push(@{$changes{'email_rule'}},$type);  
             }  
         }  
         foreach my $type (@email_rule) {  
             if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'email_rule'}})) {  
                 push(@{$changes{'email_rule'}},$type);  
             }  
         }  
     } else {  
         push(@{$changes{'email_rule'}},@email_rule);  
     }  
   
     my @authen_contexts = ('author','course','domain');      my @authen_contexts = ('author','course','domain');
     my @authtypes = ('int','krb4','krb5','loc');      my @authtypes = ('int','krb4','krb5','loc');
     my %authhash;      my %authhash;
Line 6703  sub modify_usercreation { Line 11162  sub modify_usercreation {
         }          }
     }      }
   
       $save_usercreate{'cancreate'}{'course'} = $cancreate{'course'}; 
       $save_usercreate{'cancreate'}{'author'} = $cancreate{'author'};
       $save_usercreate{'cancreate'}{'requestcrs'} = $cancreate{'requestcrs'};
       $save_usercreate{'id_rule'} = \@id_rule;
       $save_usercreate{'username_rule'} = \@username_rule,
       $save_usercreate{'authtypes'} = \%authhash;
   
     my %usercreation_hash =  (      my %usercreation_hash =  (
             usercreation => {          usercreation     => \%save_usercreate,
                               cancreate     => \%cancreate,      );
                               username_rule => \@username_rule,  
                               id_rule       => \@id_rule,  
                               email_rule    => \@email_rule,  
                               authtypes     => \%authhash,  
                             }  
             );  
   
     my $putresult = &Apache::lonnet::put_dom('configuration',\%usercreation_hash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%usercreation_hash,
                                              $dom);                                               $dom);
   
       if ($putresult eq 'ok') {
           if (keys(%changes) > 0) {
               $resulttext = &mt('Changes made:').'<ul>';
               if (ref($changes{'cancreate'}) eq 'ARRAY') {
                   my %lt = &usercreation_types();
                   foreach my $type (@{$changes{'cancreate'}}) {
                       my $chgtext = $lt{$type}.', ';
                       if ($cancreate{$type} eq 'none') {
                           $chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.');
                       } elsif ($cancreate{$type} eq 'any') {
                           $chgtext .= &mt('creation of new users is permitted for both institutional and non-institutional usernames.');
                       } elsif ($cancreate{$type} eq 'official') {
                           $chgtext .= &mt('creation of new users is only permitted for institutional usernames.');
                       } elsif ($cancreate{$type} eq 'unofficial') {
                           $chgtext .= &mt('creation of new users is only permitted for non-institutional usernames.');
                       }
                       $resulttext .= '<li>'.$chgtext.'</li>';
                   }
               }
               if (ref($changes{'username_rule'}) eq 'ARRAY') {
                   my ($rules,$ruleorder) = 
                       &Apache::lonnet::inst_userrules($dom,'username');
                   my $chgtext = '<ul>';
                   foreach my $type (@username_rule) {
                       if (ref($rules->{$type}) eq 'HASH') {
                           $chgtext .= '<li>'.$rules->{$type}{'name'}.'</li>';
                       }
                   }
                   $chgtext .= '</ul>';
                   if (@username_rule > 0) {
                       $resulttext .= '<li>'.&mt('Usernames with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';     
                   } else {
                       $resulttext .= '<li>'.&mt('There are now no username formats restricted to verified users in the institutional directory.').'</li>'; 
                   }
               }
               if (ref($changes{'id_rule'}) eq 'ARRAY') {
                   my ($idrules,$idruleorder) = 
                       &Apache::lonnet::inst_userrules($dom,'id');
                   my $chgtext = '<ul>';
                   foreach my $type (@id_rule) {
                       if (ref($idrules->{$type}) eq 'HASH') {
                           $chgtext .= '<li>'.$idrules->{$type}{'name'}.'</li>';
                       }
                   }
                   $chgtext .= '</ul>';
                   if (@id_rule > 0) {
                       $resulttext .= '<li>'.&mt('IDs with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';
                   } else {
                       $resulttext .= '<li>'.&mt('There are now no ID formats restricted to verified users in the institutional directory.').'</li>';
                   }
               }
               my %authname = &authtype_names();
               my %context_title = &context_names();
               if (ref($changes{'authtypes'}) eq 'ARRAY') {
                   my $chgtext = '<ul>';
                   foreach my $type (@{$changes{'authtypes'}}) {
                       my @allowed;
                       $chgtext .= '<li><span class="LC_cusr_emph">'.$context_title{$type}.'</span> - '.&mt('assignable authentication types: ');
                       foreach my $auth (@authtypes) {
                           if ($authhash{$type}{$auth}) {
                               push(@allowed,$authname{$auth});
                           }
                       }
                       if (@allowed > 0) {
                           $chgtext .= join(', ',@allowed).'</li>';
                       } else {
                           $chgtext .= &mt('none').'</li>';
                       }
                   }
                   $chgtext .= '</ul>';
                   $resulttext .= '<li>'.&mt('Authentication types available for assignment to new users').'<br />'.$chgtext;
                   $resulttext .= '</li>';
               }
               $resulttext .= '</ul>';
           } else {
               $resulttext = &mt('No changes made to user creation settings');
           }
       } else {
           $resulttext = '<span class="LC_error">'.
               &mt('An error occurred: [_1]',$putresult).'</span>';
       }
       if ($warningmsg ne '') {
           $resulttext .= '<br /><span class="LC_warning">'.$warningmsg.'</span><br />';
       }
       return $resulttext;
   }
   
   sub modify_selfcreation {
       my ($dom,%domconfig) = @_;
       my ($resulttext,$warningmsg,%curr_usercreation,%curr_usermodify,%changes,%cancreate);
       my (%save_usercreate,%save_usermodify,@types,%usertypes);
       my ($othertitle,$usertypesref,$typesref) = &Apache::loncommon::sorted_inst_types($dom);
       if (ref($typesref) eq 'ARRAY') {
           @types = @{$typesref};
       }
       unless (grep(/^default$/,@types)) {
           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'}.
   #
       if (ref($domconfig{'usercreation'}) eq 'HASH') {
           foreach my $key (keys(%{$domconfig{'usercreation'}})) {
               if ($key eq 'cancreate') {
                   if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {
                       foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
                           if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||
                               ($item eq 'captcha') || ($item eq 'recaptchakeys') ||
                               ($item eq 'recaptchaversion') || ($item eq 'notify') ||
                               ($item eq 'emailusername') || ($item eq 'shibenv') ||
                               ($item eq 'selfcreateprocessing') || ($item eq 'emailverified') ||
                               ($item eq 'emaildomain')) {
                               $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
                           } else {
                               $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
                           }
                       }
                   }
               } elsif ($key eq 'email_rule') {
                   $curr_usercreation{$key} = $domconfig{'usercreation'}{$key};
               } else {
                   $save_usercreate{$key} = $domconfig{'usercreation'}{$key};
               }
           }
       }
   #
   # Retrieve current domain configuration for self-creation of usernames from $domconfig{'usermodification'}.
   #
       if (ref($domconfig{'usermodification'}) eq 'HASH') {
           foreach my $key (keys(%{$domconfig{'usermodification'}})) {
               if ($key eq 'selfcreate') {
                   $curr_usermodify{$key} = $domconfig{'usermodification'}{$key};
               } else {
                   $save_usermodify{$key} = $domconfig{'usermodification'}{$key};
               }
           }
       }
   
       my @contexts = ('selfcreate');
       @{$cancreate{'selfcreate'}} = ();
       %{$cancreate{'emailusername'}} = ();
       @{$cancreate{'statustocreate'}} = ();
       %{$cancreate{'selfcreateprocessing'}} = ();
       %{$cancreate{'shibenv'}} = ();
       %{$cancreate{'emailverified'}} = ();
       %{$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 who provide a valid e-mail address for use as the username',                               email => 'users verified by e-mail',
                           );                            );
   #
   # Populate $cancreate{'selfcreate'} array reference with types of user, for which self-creation of user accounts
   # is permitted.
   #
   
       my @statuses;
       if (ref($domconfig{'inststatus'}) eq 'HASH') {
           if (ref($domconfig{'inststatus'}{'inststatusguest'}) eq 'ARRAY') {
               @statuses = @{$domconfig{'inststatus'}{'inststatusguest'}};
           }
       }
       push(@statuses,'default');
   
       foreach my $item ('login','sso','email') {
           if ($item eq 'email') {
               if ($env{'form.cancreate_email'}) {
                   push(@{$cancreate{'selfcreate'}},'email');
                   push(@contexts,('selfcreateprocessing','emailverified','emaildomain'));
                   foreach my $type (@statuses) {
                       if ($type eq 'default') {
                           $cancreate{'selfcreateprocessing'}{$type} = $env{'form.cancreate_emailprocess'};
                           unless ($cancreate{'selfcreateprocessing'}{$type} eq 'notinuse') {
                               $cancreate{'emailverified'}{$type} = $env{'form.cancreate_emailverified'};
                               if ($cancreate{'emailverified'}{$type} eq 'other') {
                                   $cancreate{'emaildomain'}{$type} =$env{'form.cancreate_emaildomain'};
                               }
                           }
                       } else { 
                           $cancreate{'selfcreateprocessing'}{$type} = $env{'form.cancreate_emailprocess_'.$type};
                           $cancreate{'emailverified'}{$type} = $env{'form.cancreate_emailverified_'.$type};
                           if ($cancreate{'emailverified'}{$type} eq 'other') {
                               $cancreate{'emaildomain'}{$type} =$env{'form.cancreate_emaildomain_'.$type};
                           }
                       }
                   }
               }
           } else {
               if ($env{'form.cancreate_'.$item}) {
                   push(@{$cancreate{'selfcreate'}},$item);
               }
           }
       }
       my (@email_rule,%userinfo,%savecaptcha);
       my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();
   #
   # Populate $cancreate{'emailusername'}{$type} hash ref with information fields (if new user will provide data
   # value set to one), if self-creation with e-mail address permitted, where $type is user type: faculty, staff, student etc.
   #
   
       if ($env{'form.cancreate_email'}) {
           push(@contexts,'emailusername');
           if (@types) {
               foreach my $type (@types) {
                   if (ref($infofields) eq 'ARRAY') {
                       foreach my $field (@{$infofields}) {
                           if ($env{'form.canmodify_emailusername_'.$type.'_'.$field} =~ /^(required|optional)$/) {
                               $cancreate{'emailusername'}{$type}{$field} = $1;
                           }
                       }
                   }
               }
           }
   #
   # Populate $cancreate{'notify'} hash ref with names of Domain Coordinators who are to be notified of
   # queued requests for self-creation of account verified by e-mail.
   #
   
           my @approvalnotify = &Apache::loncommon::get_env_multiple('form.selfcreationnotifyapproval');
           @approvalnotify = sort(@approvalnotify);
           $cancreate{'notify'}{'approval'} = join(',',@approvalnotify);
           if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {
               if (ref($curr_usercreation{'cancreate'}{'notify'}) eq 'HASH') {
                   if ($curr_usercreation{'cancreate'}{'notify'}{'approval'} ne $cancreate{'notify'}{'approval'}) {
                       push(@{$changes{'cancreate'}},'notify');
                   }
               } else {
                   if ($cancreate{'notify'}{'approval'}) {
                       push(@{$changes{'cancreate'}},'notify');
                   }
               }
           } elsif ($cancreate{'notify'}{'approval'}) {
               push(@{$changes{'cancreate'}},'notify');
           }
   
   #
   # Retrieve rules (if any) governing types of e-mail address which may be used to verify a username.
   #
           @email_rule = &Apache::loncommon::get_env_multiple('form.email_rule');
           &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
   # institutional log-in.
   #
       if (grep(/^login$/,@{$cancreate{'selfcreate'}})) {
           my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
           if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) || 
                  ($domdefaults{'auth_def'} eq 'localauth'))) {
               $warningmsg = &mt('Although account creation has been set to be available for institutional logins, currently default authentication in this domain has not been set to support this.').' '.
                             &mt('You need to set the default authentication type to Kerberos 4 or 5 (with a Kerberos domain specified), or to Local authentication, if the localauth module has been customized in your domain to authenticate institutional logins.');
           }
       }
       my @fields = ('lastname','firstname','middlename','generation',
                     'permanentemail','id');
       my @shibfields = (@fields,'inststatus');
       my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
   #
   # Where usernames may created for institutional log-in and/or institutional single sign on:
   # (a) populate $cancreate{'statustocreate'} array reference with institutional status types who
   # may self-create accounts 
   # (b) populate $save_usermodify{'selfcreate'} hash reference with status types, and information fields
   # which the user may supply, if institutional data is unavailable.
   #
       if (($env{'form.cancreate_login'}) || ($env{'form.cancreate_sso'})) {
           if (@types) {
               if (@types > 1) {
                   @{$cancreate{'statustocreate'}} = &Apache::loncommon::get_env_multiple('form.statustocreate');
                   push(@contexts,'statustocreate');
               } else {
                   undef($cancreate{'statustocreate'});
               } 
               foreach my $type (@types) {
                   my @modifiable =  &Apache::loncommon::get_env_multiple('form.canmodify_'.$type);
                   foreach my $field (@fields) {
                       if (grep(/^\Q$field\E$/,@modifiable)) {
                           $save_usermodify{'selfcreate'}{$type}{$field} = 1;
                       } else {
                           $save_usermodify{'selfcreate'}{$type}{$field} = 0;
                       }
                   }
               }
               if (ref($curr_usermodify{'selfcreate'}) eq 'HASH') {
                   foreach my $type (@types) {
                       if (ref($curr_usermodify{'selfcreate'}{$type}) eq 'HASH') {
                           foreach my $field (@fields) {
                               if ($save_usermodify{'selfcreate'}{$type}{$field} ne
                                   $curr_usermodify{'selfcreate'}{$type}{$field}) {
                                   push(@{$changes{'selfcreate'}},$type);
                                   last;
                               }
                           }
                       }
                   }
               } else {
                   foreach my $type (@types) {
                       push(@{$changes{'selfcreate'}},$type);
                   }
               }
           }
           foreach my $field (@shibfields) {
               if ($env{'form.shibenv_'.$field} ne '') {
                   $cancreate{'shibenv'}{$field} = $env{'form.shibenv_'.$field};
               }
           }
           if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {
               if (ref($curr_usercreation{'cancreate'}{'shibenv'}) eq 'HASH') {
                   foreach my $field (@shibfields) {
                       if ($env{'form.shibenv_'.$field} ne $curr_usercreation{'cancreate'}{'shibenv'}{$field}) {
                           push(@{$changes{'cancreate'}},'shibenv');
                       }
                   }
               } else {
                   foreach my $field (@shibfields) {
                       if ($env{'form.shibenv_'.$field}) {
                           push(@{$changes{'cancreate'}},'shibenv');
                           last;
                       }
                   }
               }
           }
       }
       foreach my $item (@contexts) {
           if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') {
               foreach my $curr (@{$curr_usercreation{'cancreate'}{$item}}) {
                   if (ref($cancreate{$item}) eq 'ARRAY') {
                       if (!grep(/^$curr$/,@{$cancreate{$item}})) {
                           if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                               push(@{$changes{'cancreate'}},$item);
                           }
                       }
                   }
               }
               if (ref($cancreate{$item}) eq 'ARRAY') {
                   foreach my $type (@{$cancreate{$item}}) {
                       if (!grep(/^$type$/,@{$curr_usercreation{'cancreate'}{$item}})) {
                           if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                               push(@{$changes{'cancreate'}},$item);
                           }
                       }
                   }
               }
           } elsif (ref($curr_usercreation{'cancreate'}{$item}) eq 'HASH') {
               if (ref($cancreate{$item}) eq 'HASH') {
                   foreach my $curr (keys(%{$curr_usercreation{'cancreate'}{$item}})) {
                       if (ref($curr_usercreation{'cancreate'}{$item}{$curr}) eq 'HASH') {
                           foreach my $field (keys(%{$curr_usercreation{'cancreate'}{$item}{$curr}})) {
                               unless ($curr_usercreation{'cancreate'}{$item}{$curr}{$field} eq $cancreate{$item}{$curr}{$field}) {
                                   if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                       push(@{$changes{'cancreate'}},$item);
                                   }
                               }
                           }
                       } elsif (($item eq 'selfcreateprocessing') || ($item eq 'emailverified') || ($item eq 'emaildomain')) {
                           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'}})) {
                                   push(@{$changes{'cancreate'}},$item);
                               }
                           }
                       }
                   }
                   foreach my $field (keys(%{$cancreate{$item}})) {
                       if (ref($cancreate{$item}{$field}) eq 'HASH') {
                           foreach my $inner (keys(%{$cancreate{$item}{$field}})) {
                               if (ref($curr_usercreation{'cancreate'}{$item}{$field}) eq 'HASH') {
                                   unless ($curr_usercreation{'cancreate'}{$item}{$field}{$inner} eq $cancreate{$item}{$field}{$inner}) {
                                       if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                           push(@{$changes{'cancreate'}},$item);
                                       }
                                   }
                               } else {
                                   if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                       push(@{$changes{'cancreate'}},$item);
                                   }
                               }
                           }
                       } elsif ($item eq 'selfcreateprocessing') {
                           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'}})) {
                                   push(@{$changes{'cancreate'}},$item);
                               }
                           }
                       }
                   }
               }
           } elsif ($curr_usercreation{'cancreate'}{$item}) {
               if (ref($cancreate{$item}) eq 'ARRAY') {
                   if (!grep(/^\Q$curr_usercreation{'cancreate'}{$item}\E$/,@{$cancreate{$item}})) {
                       if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                           push(@{$changes{'cancreate'}},$item);
                       }
                   }
               } elsif (ref($cancreate{$item}) eq 'HASH') {
                   if (!$cancreate{$item}{$curr_usercreation{'cancreate'}{$item}}) {
                       if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                           push(@{$changes{'cancreate'}},$item);
                       }
                   }
               }
           } elsif ($item eq 'emailusername') {
               if (ref($cancreate{$item}) eq 'HASH') {
                   foreach my $type (keys(%{$cancreate{$item}})) {
                       if (ref($cancreate{$item}{$type}) eq 'HASH') {
                           foreach my $field (keys(%{$cancreate{$item}{$type}})) {
                               if ($cancreate{$item}{$type}{$field}) {
                                   if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
                                       push(@{$changes{'cancreate'}},$item);
                                   }
                                   last;
                               }
                           }
                       }
                   }
               }
           }
       }
   #
   # Populate %save_usercreate hash with updates to self-creation configuration.
   #
       $save_usercreate{'cancreate'}{'captcha'} = $savecaptcha{'captcha'};
       $save_usercreate{'cancreate'}{'recaptchakeys'} = $savecaptcha{'recaptchakeys'};
       $save_usercreate{'cancreate'}{'recaptchaversion'} = $savecaptcha{'recaptchaversion'};
       $save_usercreate{'cancreate'}{'selfcreate'} = $cancreate{'selfcreate'};
       if (ref($cancreate{'notify'}) eq 'HASH') {
           $save_usercreate{'cancreate'}{'notify'} = $cancreate{'notify'};
       }
       if (ref($cancreate{'selfcreateprocessing'}) eq 'HASH') {
           $save_usercreate{'cancreate'}{'selfcreateprocessing'} = $cancreate{'selfcreateprocessing'};
       }
       if (ref($cancreate{'emailverified'}) eq 'HASH') {
           $save_usercreate{'cancreate'}{'emailverified'} = $cancreate{'emailverified'};
       }
       if (ref($cancreate{'emaildomain'}) eq 'HASH') {
           $save_usercreate{'cancreate'}{'emaildomain'} = $cancreate{'emaildomain'};
       }
       if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {
           $save_usercreate{'cancreate'}{'statustocreate'} = $cancreate{'statustocreate'};
       }
       if (ref($cancreate{'shibenv'}) eq 'HASH') {
           $save_usercreate{'cancreate'}{'shibenv'} = $cancreate{'shibenv'};
       }
       $save_usercreate{'cancreate'}{'emailusername'} = $cancreate{'emailusername'};
       $save_usercreate{'emailrule'} = \@email_rule;
   
       my %userconfig_hash = (
               usercreation     => \%save_usercreate,
               usermodification => \%save_usermodify,
       );
       my $putresult = &Apache::lonnet::put_dom('configuration',\%userconfig_hash,
                                                $dom);
   #
   # 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) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if (ref($changes{'cancreate'}) eq 'ARRAY') {              if (ref($changes{'cancreate'}) eq 'ARRAY') {
                 my %lt = &usercreation_types();                  my %lt = &selfcreation_types();
                 foreach my $type (@{$changes{'cancreate'}}) {                  foreach my $type (@{$changes{'cancreate'}}) {
                     my $chgtext;                      my $chgtext = '';
                     unless (($type eq 'statustocreate') || ($type eq 'captcha') || ($type eq 'recaptchakeys')) {  
                         $chgtext = $lt{$type}.', ';  
                     }  
                     if ($type eq 'selfcreate') {                      if ($type eq 'selfcreate') {
                         if (@{$cancreate{$type}} == 0) {                          if (@{$cancreate{$type}} == 0) {
                             $chgtext .= &mt('creation of a new user account is not permitted.');                              $chgtext .= &mt('Self creation of a new user account is not permitted.');
                         } else {                          } else {
                             $chgtext .= &mt('creation of a new account is permitted for:').'<ul>';                              $chgtext .= &mt('Self-creation of a new account is permitted for:').
                                           '<ul>';
                             foreach my $case (@{$cancreate{$type}}) {                              foreach my $case (@{$cancreate{$type}}) {
                                 $chgtext .= '<li>'.$selfcreatetypes{$case}.'</li>';                                  $chgtext .= '<li>'.$selfcreatetypes{$case}.'</li>';
                             }                              }
Line 6744  sub modify_usercreation { Line 11684  sub modify_usercreation {
                                 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 .= '<br /><span class="LC_warning">'.&mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").'</span>';                                              $chgtext .= '<span class="LC_warning">'.
                                                           &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts via log-in or single sign-on.").
                                                           '</span><br />';
                                           }
                                       }
                                   }
                                   if (grep(/^email$/,@{$cancreate{$type}})) {
                                       if (@statuses > 1) {
                                           my $numtypes = 0;
                                           foreach my $type (@statuses) {
                                               unless ($cancreate{'selfcreateprocessing'}{$type} eq 'notinuse') {
                                                   $numtypes ++;
                                               }
                                           }
                                           if (!$numtypes) {
                                               $chgtext .= '<span class="LC_warning">'.
                                                           &mt("However, e-mail verification is currently set to 'unavailable' for all user types (including 'other'), so self-creation of accounts is not possible for non-institutional log-in.").
                                                           '</span><br />';
   
                                         }                                          }
                                     }                                      }
                                 }                                  }
                             }                              }
                         }                          }
                       } elsif ($type eq 'shibenv') {
                           if (keys(%{$cancreate{$type}}) == 0) {
                               $chgtext .= &mt('Shibboleth-autheticated user does not use environment variables to set user information').'<br />'; 
                           } else {
                               $chgtext .= &mt('Shibboleth-autheticated user information set from environment variables, as follows:').
                                           '<ul>';
                               foreach my $field (@shibfields) {
                                   next if ($cancreate{$type}{$field} eq '');
                                   if ($field eq 'inststatus') {
                                       $chgtext .= '<li>'.&mt('Institutional status').' -- '.$cancreate{$type}{$field}.'</li>';
                                   } else {
                                       $chgtext .= '<li>'.$fieldtitles{$field}.' -- '.$cancreate{$type}{$field}.'</li>';
                                   }
                               }
                               $chgtext .= '</ul>';
                           }
                     } elsif ($type eq 'statustocreate') {                      } elsif ($type eq 'statustocreate') {
                         if ((ref($cancreate{'selfcreate'}) eq 'ARRAY') &&                          if ((ref($cancreate{'selfcreate'}) eq 'ARRAY') &&
                             (ref($cancreate{'statustocreate'}) eq 'ARRAY')) {                              (ref($cancreate{'statustocreate'}) eq 'ARRAY')) {
                             if (@{$cancreate{'selfcreate'}} > 0) {                              if (@{$cancreate{'selfcreate'}} > 0) {
                                 if (@{$cancreate{'statustocreate'}} == 0) {                                  if (@{$cancreate{'statustocreate'}} == 0) {
   
                                     $chgtext .= &mt("Institutional affiliations permitted to create accounts set to 'None'.");                                      $chgtext .= &mt("Institutional affiliations permitted to create accounts set to 'None'.");
                                     if (!grep(/^email$/,@{$cancreate{'selfcreate'}})) {                                      if (!grep(/^email$/,@{$cancreate{'selfcreate'}})) {
                                         $chgtext .= '<br /><span class="LC_warning">'.&mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").'</span>';                                          $chgtext .= '<br />'.
                                     }                                                       '<span class="LC_warning">'.
                                 } elsif (ref($usertypes) eq 'HASH') {                                                      &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").
                                                       '</span>';
                                       }
                                   } elsif (keys(%usertypes) > 0) {
                                     if (grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {                                      if (grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {
                                         $chgtext .= &mt('Creation of a new account for an institutional user is restricted to the following institutional affiliation(s):');                                          $chgtext .= &mt('Creation of a new account for an institutional user is restricted to the following institutional affiliation(s):');
                                     } else {                                      } else {
Line 6771  sub modify_usercreation { Line 11747  sub modify_usercreation {
                                         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 .= '<br /><span class="LC_warning">'.&mt('However, users authenticated by institutional login/single sign on are not currently permitted to create accounts.').'</span>';                                          $chgtext .= '<span class="LC_warning">'.
                                                       &mt('However, users authenticated by institutional login/single sign on are not currently permitted to create accounts.').
                                                       '</span>';
                                     }                                      }
                                 }                                  }
                             } else {                              } else {
Line 6786  sub modify_usercreation { Line 11764  sub modify_usercreation {
                                     $chgtext .= &mt('Although institutional affiliations permitted to create accounts were changed, self creation of accounts is not currently permitted for any authentication types.');                                      $chgtext .= &mt('Although institutional affiliations permitted to create accounts were changed, self creation of accounts is not currently permitted for any authentication types.');
                                 }                                  }
                             }                              }
                               $chgtext .= '<br />';
                           }
                       } elsif ($type eq 'selfcreateprocessing') {
                           my %choices = &Apache::lonlocal::texthash (
                                                                       automatic => 'Automatic approval',
                                                                       approval  => 'Queued for approval',
                                                                       notinuse  => 'Unavailable',
                                                                     );
                           if (@statuses > 1) {
                               my $numtypes = 0;
                               foreach my $type (@statuses) {
                                   unless ($cancreate{'selfcreateprocessing'}{$type} eq 'notinuse') {
                                       $numtypes ++;
                                   }
                               }
                               if ($numtypes) {
                                   $chgtext .= &mt('Processing of requests to create account with e-mail verification set as follows:'). 
                                               '<ul>';
                                   foreach my $type (@statuses) {
                                       if ($type eq 'default') {
                                           $chgtext .= '<li>'.$othertitle.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$type}}.'</li>';
                                       } else {
                                           $chgtext .= '<li>'.$usertypes{$type}.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$type}}.'</li>';
                                       }
                                   }
                                   $chgtext .= '</ul>';
                               }
                           } else {
                               $chgtext .= &mt('Processing of requests to create account with e-mail verification set to: "[_1]"',
                                               $choices{$cancreate{'selfcreateprocessing'}{'default'}});
                           }
                       } elsif ($type eq 'emailverified') {
                           my %options = &Apache::lonlocal::texthash (
                                                                       email => 'Username is e-mail',
                                                                       other => 'Username is chosen',
                                                                     );
                           if (@statuses > 1) {
                               my $numtypes = 0;
                               foreach my $type (@statuses) {
                                   unless ($cancreate{'selfcreateprocessing'}{$type} eq 'notinuse') {
                                       $numtypes ++;
                                   }
                               }
                               if ($numtypes) {
                                   $chgtext .= &mt('For self-created accounts verified by e-mail address, username is set as follows:').
                                               '<ul>';
                                   foreach my $type (@statuses) {
                                       next if ($cancreate{'selfcreateprocessing'}{$type} eq 'notinuse'); 
                                       if ($type eq 'default') {
                                           $chgtext .= '<li>'.$othertitle.' -- '.$options{$cancreate{'emailverified'}{$type}}.'</li>';
                                       } else {
                                           $chgtext .= '<li>'.$usertypes{$type}.' -- '.$options{$cancreate{'emailverified'}{$type}}.'</li>';
                                       }
                                   }
                                   $chgtext .= '</ul>';
                               }
                           } else {
                               $chgtext .= &mt('For self-created accounts verified by e-mail address: "[_1]"',
                                               $choices{$cancreate{'emailverified'}{'default'}});
                           }
                       } elsif ($type eq 'emaildomain') {
                           if (@statuses > 1) {
                               my $numtypes = 0;
                               foreach my $type (@statuses) {
                                   unless ($cancreate{'selfcreateprocessing'}{$type} eq 'notinuse') {
                                       if ($cancreate{'emailverified'}{$type} eq 'other') {
                                           $numtypes ++;
                                       }
                                   }
                               }
                               if ($numtypes) {                     
                                   $chgtext .= &mt('For self-created accounts verified by e-mail address, with username chosen by user ...').
                                               '<ul>';
                                   foreach my $type (@statuses) {
                                       next if (($cancreate{'selfcreateprocessing'}{$type} eq 'notinuse') ||
                                                ($cancreate{'emailverified'}{$type} eq 'email'));
                                       if ($type eq 'default') {
                                           if ($cancreate{'emaildomain'}{$type} eq '') {
                                               $chgtext .= '<li>'.$othertitle.' -- '.&mt('No restriction on e-mail domain').'</li>';
                                           } else {
                                               $chgtext .= '<li>'.$othertitle.' -- '.&mt("User's e-mail domain needs to be: [_1]",
                                                                                         $cancreate{'emaildomain'}{$type}).'</li>';
                                           }
                                       } else {
                                           if ($cancreate{'emaildomain'}{$type} eq '') {
                                               $chgtext .= '<li>'.$usertypes{$type}.' -- '.&mt('No restriction on e-mail domain').'</li>';
                                           } else {
                                               $chgtext .= '<li>'.$usertypes{$type}.' -- '.&mt("User's e-mail domain needs to be: [_1]",
                                                                                               $cancreate{'emaildomain'}{$type}).'</li>'; 
                                           }
                                       }
                                   }
                                   $chgtext .= '</ul>';
                               }
                           } else {
                               if ($cancreate{'emailverified'}{'default'} eq 'other') {
                                   if ($cancreate{'emaildomain'}{'default'} eq '') {
                                       $chgtext .= &mt('No restriction on e-mail domain for self-created accounts verified by e-mail address, where username is chosen by user.');
                                   } else {
                                       $chgtext .= &mt('For self-created accounts verified by e-mail address, where username is chosen by user, e-mail domain needs to be: [_1],
                                                       $cancreate{'selfcreateprocessing'}{'default'});
                                   }
                               }
                         }                          }
                     } elsif ($type eq 'captcha') {                      } elsif ($type eq 'captcha') {
                         if ($cancreate{$type} eq 'notused') {                          if ($savecaptcha{$type} eq 'notused') {
                             $chgtext .= &mt('No CAPTCHA validation in use for self-creation screen.');                              $chgtext .= &mt('No CAPTCHA validation in use for self-creation screen.');
                         } else {                          } else {
                             my %captchas = &captcha_phrases();                              my %captchas = &captcha_phrases();
                             if ($captchas{$cancreate{$type}}) {                              if ($captchas{$savecaptcha{$type}}) {
                                 $chgtext .= &mt("Validation for self-creation screen set to $captchas{$cancreate{$type}}.");                                  $chgtext .= &mt("Validation for self-creation screen set to $captchas{$savecaptcha{$type}}.");
                             } else {                              } else {
                                 $chgtext .= &mt('Validation for self-creation screen set to unknown type.');                                  $chgtext .= &mt('Validation for self-creation screen set to unknown type.');
                             }                              }
                         }                          }
                     } elsif ($type eq 'recaptchakeys') {                      } elsif ($type eq 'recaptchakeys') {
                         my ($privkey,$pubkey);                          my ($privkey,$pubkey);
                         if (ref($cancreate{$type}) eq 'HASH') {                          if (ref($savecaptcha{$type}) eq 'HASH') {
                             $pubkey = $cancreate{$type}{'public'};                              $pubkey = $savecaptcha{$type}{'public'};
                             $privkey = $cancreate{$type}{'private'};                              $privkey = $savecaptcha{$type}{'private'};
                         }                          }
                         $chgtext .= &mt('ReCAPTCHA keys changes').'<ul>';                          $chgtext .= &mt('ReCAPTCHA keys changes').'<ul>';
                         if (!$pubkey) {                          if (!$pubkey) {
Line 6816  sub modify_usercreation { Line 11897  sub modify_usercreation {
                             $chgtext .= '<li>'.&mt('Private key set to [_1]',$pubkey).'</li>';                              $chgtext .= '<li>'.&mt('Private key set to [_1]',$pubkey).'</li>';
                         }                          }
                         $chgtext .= '</ul>';                          $chgtext .= '</ul>';
                     } else {                      } elsif ($type eq 'recaptchaversion') {
                         if ($cancreate{$type} eq 'none') {                          if ($savecaptcha{'captcha'} eq 'recaptcha') {
                             $chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.');                              $chgtext .= &mt('ReCAPTCHA set to version [_1]',$savecaptcha{$type});
                         } elsif ($cancreate{$type} eq 'any') {                          }
                             $chgtext .= &mt('creation of new users is permitted for both institutional and non-institutional usernames.');                      } elsif ($type eq 'emailusername') {
                         } elsif ($cancreate{$type} eq 'official') {                          if (ref($cancreate{'emailusername'}) eq 'HASH') {
                             $chgtext .= &mt('creation of new users is only permitted for institutional usernames.');                              if (@types) {
                         } elsif ($cancreate{$type} eq 'unofficial') {                                  foreach my $type (@types) {
                             $chgtext .= &mt('creation of new users is only permitted for non-institutional usernames.');                                      if (ref($cancreate{'emailusername'}{$type}) eq 'HASH') {
                                           if (keys(%{$cancreate{'emailusername'}{$type}}) > 0) {
                                               $chgtext .= &mt('When self-creating account with e-mail verification, the following information will be provided by [_1]:',"'$usertypes{$type}'").
                                                       '<ul>';
                                               foreach my $field (@{$infofields}) {
                                                   if ($cancreate{'emailusername'}{$type}{$field}) {
                                                       $chgtext .= '<li>'.$infotitles->{$field}.'</li>';
                                                   }
                                               }
                                               $chgtext .= '</ul>';
                                           } else {
                                               $chgtext .= &mt('When self creating account with e-mail verification, no information besides e-mail address will be provided by [_1].',"'$usertypes{$type}'").'<br />';
                                           }
                                       } else {
                                           $chgtext .= &mt('When self creating account with e-mail verification, no information besides e-mail address will be provided by [_1].',"'$usertypes{$type}'").'<br />';
                                       }
                                   }
                               }
                           }
                       } elsif ($type eq 'notify') {
                           my $numapprove = 0;
                           if (ref($changes{'cancreate'}) eq 'ARRAY') {
                               if ((grep(/^notify$/,@{$changes{'cancreate'}})) && (ref($cancreate{'notify'}) eq 'HASH')) {
                                   if ($cancreate{'notify'}{'approval'}) {
                                       $chgtext .= &mt('Notification of username requests requiring approval will be sent to: ').$cancreate{'notify'}{'approval'};
                                       $numapprove ++;
                                   }
                               }
                           }
                           unless ($numapprove) {
                               $chgtext .= &mt('No Domain Coordinators will receive notification of username requests requiring approval.');
                         }                          }
                     }                      }
                     $resulttext .= '<li>'.$chgtext.'</li>';                      if ($chgtext) {
                 }                          $resulttext .= '<li>'.$chgtext.'</li>';
             }  
             if (ref($changes{'username_rule'}) eq 'ARRAY') {  
                 my ($rules,$ruleorder) =   
                     &Apache::lonnet::inst_userrules($dom,'username');  
                 my $chgtext = '<ul>';  
                 foreach my $type (@username_rule) {  
                     if (ref($rules->{$type}) eq 'HASH') {  
                         $chgtext .= '<li>'.$rules->{$type}{'name'}.'</li>';  
                     }  
                 }  
                 $chgtext .= '</ul>';  
                 if (@username_rule > 0) {  
                     $resulttext .= '<li>'.&mt('Usernames with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';       
                 } else {  
                     $resulttext .= '<li>'.&mt('There are now no username formats restricted to verified users in the institutional directory.').'</li>';   
                 }  
             }  
             if (ref($changes{'id_rule'}) eq 'ARRAY') {  
                 my ($idrules,$idruleorder) =   
                     &Apache::lonnet::inst_userrules($dom,'id');  
                 my $chgtext = '<ul>';  
                 foreach my $type (@id_rule) {  
                     if (ref($idrules->{$type}) eq 'HASH') {  
                         $chgtext .= '<li>'.$idrules->{$type}{'name'}.'</li>';  
                     }                      }
                 }                  }
                 $chgtext .= '</ul>';  
                 if (@id_rule > 0) {  
                     $resulttext .= '<li>'.&mt('IDs with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';  
                 } else {  
                     $resulttext .= '<li>'.&mt('There are now no ID formats restricted to verified users in the institutional directory.').'</li>';  
                 }  
             }              }
             if (ref($changes{'email_rule'}) eq 'ARRAY') {              if (ref($changes{'email_rule'}) eq 'ARRAY') {
                 my ($emailrules,$emailruleorder) =                  my ($emailrules,$emailruleorder) =
Line 6873  sub modify_usercreation { Line 11954  sub modify_usercreation {
                 }                  }
                 $chgtext .= '</ul>';                  $chgtext .= '</ul>';
                 if (@email_rule > 0) {                  if (@email_rule > 0) {
                     $resulttext .= '<li>'.&mt('Accounts may not be created by users self-enrolling with e-mail addresses of the following types: ').$chgtext.'</li>';                      $resulttext .= '<li>'.
                 } else {                                     &mt('Accounts may not be created by users verified by e-mail, for e-mail addresses of the following types: ').
                     $resulttext .= '<li>'.&mt('There are now no restrictions on e-mail addresses which may be used as a username when self-enrolling.').'</li>';                                         $chgtext.
                 }                                     '</li>';
             }                  } else {
                       $resulttext .= '<li>'.
             my %authname = &authtype_names();                                     &mt('There are now no restrictions on e-mail addresses which may be used for verification when self-enrolling.').
             my %context_title = &context_names();                                     '</li>';
             if (ref($changes{'authtypes'}) eq 'ARRAY') {                  }
                 my $chgtext = '<ul>';              }
                 foreach my $type (@{$changes{'authtypes'}}) {              if (ref($changes{'selfcreate'}) eq 'ARRAY') {
                     my @allowed;                  $resulttext .= '<li>'.&mt('When self-creating institutional account:').'<ul>';
                     $chgtext .= '<li><span class="LC_cusr_emph">'.$context_title{$type}.'</span> - '.&mt('assignable authentication types: ');                  my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
                     foreach my $auth (@authtypes) {                  foreach my $type (@{$changes{'selfcreate'}}) {
                         if ($authhash{$type}{$auth}) {                      my $typename = $type;
                             push(@allowed,$authname{$auth});                      if (keys(%usertypes) > 0) {
                           if ($usertypes{$type} ne '') {
                               $typename = $usertypes{$type};
                           }
                       }
                       my @modifiable;
                       $resulttext .= '<li>'.
                                       &mt('Self-creation of account by users with status: [_1]',
                                           '<span class="LC_cusr_emph">'.$typename.'</span>').
                                       ' - '.&mt('modifiable fields (if institutional data blank): ');
                       foreach my $field (@fields) {
                           if ($save_usermodify{'selfcreate'}{$type}{$field}) {
                               push(@modifiable,'<b>'.$fieldtitles{$field}.'</b>');
                         }                          }
                     }                      }
                     if (@allowed > 0) {                      if (@modifiable > 0) {
                         $chgtext .= join(', ',@allowed).'</li>';                          $resulttext .= join(', ',@modifiable);
                     } else {                      } else {
                         $chgtext .= &mt('none').'</li>';                          $resulttext .= &mt('none');
                     }                      }
                       $resulttext .= '</li>';
                 }                  }
                 $chgtext .= '</ul>';                  $resulttext .= '</ul></li>';
                 $resulttext .= '<li>'.&mt('Authentication types available for assignment to new users').'<br />'.$chgtext;  
                 $resulttext .= '</li>';  
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
         } else {          } else {
             $resulttext = &mt('No changes made to user creation settings');              $resulttext = &mt('No changes made to self-creation settings');
         }          }
     } else {      } else {
         $resulttext = '<span class="LC_error">'.          $resulttext = '<span class="LC_error">'.
Line 6933  sub process_captcha { Line 12025  sub process_captcha {
             $changes->{'captcha'} = 1;              $changes->{'captcha'} = 1;
         }          }
     }      }
     my ($newpub,$newpriv,$currpub,$currpriv);      my ($newpub,$newpriv,$currpub,$currpriv,$newversion,$currversion);
     if ($newsettings->{'captcha'} eq 'recaptcha') {      if ($newsettings->{'captcha'} eq 'recaptcha') {
         $newpub = $env{'form.'.$container.'_recaptchapub'};          $newpub = $env{'form.'.$container.'_recaptchapub'};
         $newpriv = $env{'form.'.$container.'_recaptchapriv'};          $newpriv = $env{'form.'.$container.'_recaptchapriv'};
         $newpub =~ s/\W//g;          $newpub =~ s/[^\w\-]//g;
         $newpriv =~ s/\W//g;          $newpriv =~ s/[^\w\-]//g;
         $newsettings->{'recaptchakeys'} = {          $newsettings->{'recaptchakeys'} = {
                                              public  => $newpub,                                               public  => $newpub,
                                              private => $newpriv,                                               private => $newpriv,
                                           };                                            };
           $newversion = $env{'form.'.$container.'_recaptchaversion'};
           $newversion =~ s/\D//g;
           if ($newversion ne '2') {
               $newversion = 1;
           }
           $newsettings->{'recaptchaversion'} = $newversion;
     }      }
     if (ref($current->{'recaptchakeys'}) eq 'HASH') {      if (ref($current->{'recaptchakeys'}) eq 'HASH') {
         $currpub = $current->{'recaptchakeys'}{'public'};          $currpub = $current->{'recaptchakeys'}{'public'};
         $currpriv = $current->{'recaptchakeys'}{'private'};          $currpriv = $current->{'recaptchakeys'}{'private'};
         $newsettings->{'recaptchakeys'} = {          unless ($newsettings->{'captcha'} eq 'recaptcha') {
                                              public  => '',              $newsettings->{'recaptchakeys'} = {
                                              private => '',                                                   public  => '',
                                           }                                                   private => '',
                                                 }
           }
       }
       if ($current->{'captcha'} eq 'recaptcha') {
           $currversion = $current->{'recaptchaversion'};
           if ($currversion ne '2') {
               $currversion = 1;
           }
       }
       if ($currversion ne $newversion) {
           if ($container eq 'cancreate') {
               if (ref($changes->{'cancreate'}) eq 'ARRAY') {
                   push(@{$changes->{'cancreate'}},'recaptchaversion');
               } elsif (!defined($changes->{'cancreate'})) {
                   $changes->{'cancreate'} = ['recaptchaversion'];
               }
           } else {
               $changes->{'recaptchaversion'} = 1;
           }
     }      }
     if (($newpub ne $currpub) || ($newpriv ne $currpriv)) {      if (($newpub ne $currpub) || ($newpriv ne $currpriv)) {
         if ($container eq 'cancreate') {          if ($container eq 'cancreate') {
Line 6968  sub process_captcha { Line 12085  sub process_captcha {
   
 sub modify_usermodification {  sub modify_usermodification {
     my ($dom,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%curr_usermodification,%changes);      my ($resulttext,%curr_usermodification,%changes,%modifyhash);
     if (ref($domconfig{'usermodification'}) eq 'HASH') {      if (ref($domconfig{'usermodification'}) eq 'HASH') {
         foreach my $key (keys(%{$domconfig{'usermodification'}})) {          foreach my $key (keys(%{$domconfig{'usermodification'}})) {
             $curr_usermodification{$key} = $domconfig{'usermodification'}{$key};              if ($key eq 'selfcreate') {
                   $modifyhash{$key} = $domconfig{'usermodification'}{$key};
               } else {  
                   $curr_usermodification{$key} = $domconfig{'usermodification'}{$key};
               }
         }          }
     }      }
     my @contexts = ('author','course','selfcreate');      my @contexts = ('author','course');
     my %context_title = (      my %context_title = (
                            author => 'In author context',                             author => 'In author context',
                            course => 'In course context',                             course => 'In course context',
                            selfcreate => 'When self creating account',   
                         );                          );
     my @fields = ('lastname','firstname','middlename','generation',      my @fields = ('lastname','firstname','middlename','generation',
                   'permanentemail','id');                    'permanentemail','id');
Line 6986  sub modify_usermodification { Line 12106  sub modify_usermodification {
                   author => ['ca','aa'],                    author => ['ca','aa'],
                   course => ['st','ep','ta','in','cr'],                    course => ['st','ep','ta','in','cr'],
                 );                  );
     my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);  
     if (ref($types) eq 'ARRAY') {  
         push(@{$types},'default');  
         $usertypes->{'default'} = $othertitle;  
     }  
     $roles{'selfcreate'} = $types;    
     my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();      my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
     my %modifyhash;  
     foreach my $context (@contexts) {      foreach my $context (@contexts) {
         foreach my $role (@{$roles{$context}}) {          foreach my $role (@{$roles{$context}}) {
             my @modifiable =  &Apache::loncommon::get_env_multiple('form.canmodify_'.$role);              my @modifiable =  &Apache::loncommon::get_env_multiple('form.canmodify_'.$role);
Line 7039  sub modify_usermodification { Line 12152  sub modify_usermodification {
                     if (ref($changes{$context}) eq 'ARRAY') {                      if (ref($changes{$context}) eq 'ARRAY') {
                         foreach my $role (@{$changes{$context}}) {                          foreach my $role (@{$changes{$context}}) {
                             my $rolename;                              my $rolename;
                             if ($context eq 'selfcreate') {                              if ($role eq 'cr') {
                                 $rolename = $role;                                  $rolename = &mt('Custom');
                                 if (ref($usertypes) eq 'HASH') {  
                                     if ($usertypes->{$role} ne '') {  
                                         $rolename = $usertypes->{$role};  
                                     }  
                                 }  
                             } else {                              } else {
                                 if ($role eq 'cr') {                                  $rolename = &Apache::lonnet::plaintext($role);
                                     $rolename = &mt('Custom');  
                                 } else {  
                                     $rolename = &Apache::lonnet::plaintext($role);  
                                 }  
                             }                              }
                             my @modifiable;                              my @modifiable;
                             if ($context eq 'selfcreate') {                              $resulttext .= '<li><span class="LC_cusr_emph">'.&mt('Target user with [_1] role',$rolename).'</span> - '.&mt('modifiable fields: ');
                                 $resulttext .= '<li><span class="LC_cusr_emph">'.&mt('Self-creation of account by users with status: [_1]',$rolename).'</span> - '.&mt('modifiable fields (if institutional data blank): ');  
                             } else {  
                                 $resulttext .= '<li><span class="LC_cusr_emph">'.&mt('Target user with [_1] role',$rolename).'</span> - '.&mt('modifiable fields: ');  
                             }  
                             foreach my $field (@fields) {                              foreach my $field (@fields) {
                                 if ($modifyhash{$context}{$role}{$field}) {                                  if ($modifyhash{$context}{$role}{$field}) {
                                     push(@modifiable,$fieldtitles{$field});                                      push(@modifiable,$fieldtitles{$field});
Line 7087  sub modify_usermodification { Line 12187  sub modify_usermodification {
 }  }
   
 sub modify_defaults {  sub modify_defaults {
     my ($dom,$r) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors);      my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors);
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
     my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def','portal_def');      my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def',
                    'portal_def','intauth_cost','intauth_check','intauth_switch');
     my @authtypes = ('internal','krb4','krb5','localauth');      my @authtypes = ('internal','krb4','krb5','localauth');
     foreach my $item (@items) {      foreach my $item (@items) {
         $newvalues{$item} = $env{'form.'.$item};          $newvalues{$item} = $env{'form.'.$item};
Line 7132  sub modify_defaults { Line 12233  sub modify_defaults {
                     push(@errors,$item);                      push(@errors,$item);
                 }                  }
             }              }
           } elsif ($item eq 'intauth_cost') {
               if ($newvalues{$item} ne '') {
                   if ($newvalues{$item} =~ /\D/) {
                       push(@errors,$item);
                   }
               }
           } elsif ($item eq 'intauth_check') {
               if ($newvalues{$item} ne '') {
                   unless ($newvalues{$item} =~ /^(0|1|2)$/) {
                       push(@errors,$item);
                   }
               }
           } elsif ($item eq 'intauth_switch') {
               if ($newvalues{$item} ne '') {
                   unless ($newvalues{$item} =~ /^(0|1|2)$/) {
                       push(@errors,$item);
                   }
               }
         }          }
         if (grep(/^\Q$item\E$/,@errors)) {          if (grep(/^\Q$item\E$/,@errors)) {
             $newvalues{$item} = $domdefaults{$item};              $newvalues{$item} = $domdefaults{$item};
Line 7144  sub modify_defaults { Line 12263  sub modify_defaults {
                          defaults => \%newvalues,                           defaults => \%newvalues,
                         );                          );
     my $title = &defaults_titles();      my $title = &defaults_titles();
   
       my $currinststatus;
       if (ref($domconfig{'inststatus'}) eq 'HASH') {
           $currinststatus = $domconfig{'inststatus'};
       } else {
           my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
           $currinststatus = {
                                inststatustypes => $usertypes,
                                inststatusorder => $types,
                                inststatusguest => [],
                             };
       }
       my @todelete = &Apache::loncommon::get_env_multiple('form.inststatus_delete');
       my @allpos;
       my %guests;
       my %alltypes;
       my ($currtitles,$currguests,$currorder);
       if (ref($currinststatus) eq 'HASH') {
           if (ref($currinststatus->{'inststatusorder'}) eq 'ARRAY') {
               foreach my $type (@{$currinststatus->{'inststatusorder'}}) {
                   if (ref($currinststatus->{inststatustypes}) eq 'HASH') {
                       if ($currinststatus->{inststatustypes}->{$type} ne '') {
                           $currtitles .= $currinststatus->{inststatustypes}->{$type}.',';
                       }
                   }
                   unless (grep(/^\Q$type\E$/,@todelete)) { 
                       my $position = $env{'form.inststatus_pos_'.$type};
                       $position =~ s/\D+//g;
                       $allpos[$position] = $type;
                       $alltypes{$type} = $env{'form.inststatus_title_'.$type};
                       $alltypes{$type} =~ s/`//g;
                       if ($env{'form.inststatus_guest_'.$type}) {
                           $guests{$type} = 1;
                       }
                   }
               }
               if (ref($currinststatus->{'inststatusguest'}) eq 'ARRAY') {
                   $currguests = join(',',@{$currinststatus->{'inststatusguest'}});
               }
               $currorder = join(',',@{$currinststatus->{'inststatusorder'}});
               $currtitles =~ s/,$//;
           }
       }
       if ($env{'form.addinststatus'}) {
           my $newtype = $env{'form.addinststatus'};
           $newtype =~ s/\W//g;
           unless (exists($alltypes{$newtype})) {
               if ($env{'form.addinststatus_guest'}) {
                   $guests{$newtype} = 1;
               }
               $alltypes{$newtype} = $env{'form.addinststatus_title'};
               $alltypes{$newtype} =~ s/`//g; 
               my $position = $env{'form.addinststatus_pos'};
               $position =~ s/\D+//g;
               if ($position ne '') {
                   $allpos[$position] = $newtype;
               }
           }
       }
       my (@orderedstatus,@orderedguests);
       foreach my $type (@allpos) {
           unless (($type eq '') || (grep(/^\Q$type\E$/,@orderedstatus))) {
               push(@orderedstatus,$type);
               if ($guests{$type}) {
                   push(@orderedguests,$type);
               }
           }
       }
       foreach my $type (keys(%alltypes)) {
           unless (grep(/^\Q$type\E$/,@orderedstatus)) {
               delete($alltypes{$type});
           }
       }
       $defaults_hash{'inststatus'} = {
                                        inststatustypes => \%alltypes,
                                        inststatusorder => \@orderedstatus,
                                        inststatusguest => \@orderedguests,
                                      };
       if (ref($defaults_hash{'inststatus'}) eq 'HASH') {
           foreach my $item ('inststatustypes','inststatusorder','inststatusguest') {
               $domdefaults{$item} = $defaults_hash{'inststatus'}{$item};
           }
       }
       if ($currorder ne join(',',@orderedstatus)) {
           $changes{'inststatus'}{'inststatusorder'} = 1;
       }
       if ($currguests ne join(',',@orderedguests)) {
           $changes{'inststatus'}{'inststatusguest'} = 1;
       }
       my $newtitles;
       foreach my $item (@orderedstatus) {
           $newtitles .= $alltypes{$item}.',';
       }
       $newtitles =~ s/,$//;
       if ($currtitles ne $newtitles) {
           $changes{'inststatus'}{'inststatustypes'} = 1;
       }
     my $putresult = &Apache::lonnet::put_dom('configuration',\%defaults_hash,      my $putresult = &Apache::lonnet::put_dom('configuration',\%defaults_hash,
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             my $version = $r->dir_config('lonVersion');              my $version = &Apache::lonnet::get_server_loncaparev($dom);
             my $mailmsgtext = "Changes made to domain settings in a LON-CAPA installation - domain: $dom (running version: $version) - dns_domain.tab needs to be updated with the following changes, to support legacy 2.4, 2.5 and 2.6 versions of LON-CAPA.\n\n";              my $mailmsgtext = "Changes made to domain settings in a LON-CAPA installation - domain: $dom (running version: $version) - dns_domain.tab needs to be updated with the following changes, to support legacy 2.4, 2.5 and 2.6 versions of LON-CAPA.\n\n";
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
                 my $value = $env{'form.'.$item};                  if ($item eq 'inststatus') {
                 if ($value eq '') {                      if (ref($changes{'inststatus'}) eq 'HASH') {
                     $value = &mt('none');                          if (($changes{'inststatus'}{'inststatustypes'}) || $changes{'inststatus'}{'inststatusorder'}) {
                 } elsif ($item eq 'auth_def') {                              $resulttext .= '<li>'.&mt('Institutional user status types set to:').' ';
                     my %authnames = &authtype_names();                              foreach my $type (@orderedstatus) { 
                     my %shortauth = (                                  $resulttext .= $alltypes{$type}.', ';
                              internal => 'int',                              }
                              krb4 => 'krb4',                              $resulttext =~ s/, $//;
                              krb5 => 'krb5',                              $resulttext .= '</li>';
                              localauth  => 'loc',                          }
                     );                          if ($changes{'inststatus'}{'inststatusguest'}) {
                     $value = $authnames{$shortauth{$value}};                              $resulttext .= '<li>'; 
                               if (@orderedguests) {
                                   $resulttext .= &mt('Types assignable to "non-institutional" usernames set to:').' ';
                                   foreach my $type (@orderedguests) {
                                       $resulttext .= $alltypes{$type}.', ';
                                   }
                                   $resulttext =~ s/, $//;
                               } else {
                                   $resulttext .= &mt('Types assignable to "non-institutional" usernames set to none.');
                               }
                               $resulttext .= '</li>';
                           }
                       }
                   } else {
                       my $value = $env{'form.'.$item};
                       if ($value eq '') {
                           $value = &mt('none');
                       } elsif ($item eq 'auth_def') {
                           my %authnames = &authtype_names();
                           my %shortauth = (
                                             internal   => 'int',
                                             krb4       => 'krb4',
                                             krb5       => 'krb5',
                                             localauth  => 'loc',
                           );
                           $value = $authnames{$shortauth{$value}};
                       } elsif ($item eq 'intauth_switch') {
                           my %optiondesc = &Apache::lonlocal::texthash (
                                               0 => 'No',
                                               1 => 'Yes',
                                               2 => 'Yes, and copy existing passwd file to passwd.bak file',
                                            );
                           if ($value =~ /^(0|1|2)$/) {
                               $value = $optiondesc{$value};
                           } else {
                               $value = &mt('none -- defaults to No');
                           }
                       } elsif ($item eq 'intauth_check') {
                           my %optiondesc = &Apache::lonlocal::texthash (
                                                0 => 'No',
                                                1 => 'Yes, allow login then update passwd file using default cost (if higher)',
                                                2 => 'Yes, disallow login if stored cost is less than domain default',
                                            );
                           if ($value =~ /^(0|1|2)$/) {
                               $value = $optiondesc{$value};
                           } else {
                               $value = &mt('none -- defaults to No');
                           }
                       }
                       $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$item},$value).'</li>';
                       $mailmsgtext .= "$title->{$item} set to $value\n";  
                 }                  }
                 $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$item},$value).'</li>';  
                 $mailmsgtext .= "$title->{$item} set to $value\n";    
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
             $mailmsgtext .= "\n";              $mailmsgtext .= "\n";
             my $cachetime = 24*60*60;              my $cachetime = 24*60*60;
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);              &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
               }
             if ($changes{'auth_def'} || $changes{'auth_arg_def'} || $changes{'lang_def'} || $changes{'datelocale_def'}) {              if ($changes{'auth_def'} || $changes{'auth_arg_def'} || $changes{'lang_def'} || $changes{'datelocale_def'}) {
                 my $sysmail = $r->dir_config('lonSysEMail');                  my $notify = 1;
                 &Apache::lonmsg::sendemail($sysmail,"LON-CAPA Domain Settings Change - $dom",$mailmsgtext);                  if (ref($domconfig{'contacts'}) eq 'HASH') {
                       if ($domconfig{'contacts'}{'reportupdates'} == 0) {
                           $notify = 0;
                       }
                   }
                   if ($notify) {
                       &Apache::lonmsg::sendemail('installrecord@loncapa.org',
                                                  "LON-CAPA Domain Settings Change - $dom",
                                                  $mailmsgtext);
                   }
             }              }
         } else {          } else {
             $resulttext = &mt('No changes made to default authentication/language/timezone settings');              $resulttext = &mt('No changes made to default authentication/language/timezone settings');
Line 7194  sub modify_defaults { Line 12470  sub modify_defaults {
 }  }
   
 sub modify_scantron {  sub modify_scantron {
     my ($r,$dom,$confname,%domconfig) = @_;      my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
     my ($resulttext,%confhash,%changes,$errors);      my ($resulttext,%confhash,%changes,$errors);
     my $custom = 'custom.tab';      my $custom = 'custom.tab';
     my $default = 'default.tab';      my $default = 'default.tab';
Line 7255  sub modify_scantron { Line 12531  sub modify_scantron {
                 }                  }
                 $resulttext .= '</ul>';                  $resulttext .= '</ul>';
                 &Apache::loncommon::devalidate_domconfig_cache($dom);                  &Apache::loncommon::devalidate_domconfig_cache($dom);
                   if (ref($lastactref) eq 'HASH') {
                       $lastactref->{'domainconfig'} = 1;
                   }
             } else {              } else {
                 $resulttext = &mt('No changes made to bubblesheet format file');                  $resulttext = &mt('No changes made to bubblesheet format file');
             }              }
Line 7273  sub modify_scantron { Line 12552  sub modify_scantron {
 }  }
   
 sub modify_coursecategories {  sub modify_coursecategories {
     my ($dom,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,%deletions,%reorderings,%needreordering,%adds,%changes,$errors,      my ($resulttext,%deletions,%reorderings,%needreordering,%adds,%changes,$errors,
         $cathash);          $cathash);
     my @deletecategory = &Apache::loncommon::get_env_multiple('form.deletecategory');      my @deletecategory = &Apache::loncommon::get_env_multiple('form.deletecategory');
       my @catitems = ('unauth','auth');
       my @cattypes = ('std','domonly','codesrch','none');
     if (ref($domconfig{'coursecategories'}) eq 'HASH') {      if (ref($domconfig{'coursecategories'}) eq 'HASH') {
         $cathash = $domconfig{'coursecategories'}{'cats'};          $cathash = $domconfig{'coursecategories'}{'cats'};
         if ($domconfig{'coursecategories'}{'togglecats'} ne $env{'form.togglecats'}) {          if ($domconfig{'coursecategories'}{'togglecats'} ne $env{'form.togglecats'}) {
Line 7294  sub modify_coursecategories { Line 12575  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) {
               if (grep(/^\Q$env{'form.coursecat_'.$item}\E$/,@cattypes)) {
                   if ($domconfig{'coursecategories'}{$item} ne $env{'form.coursecat_'.$item}) {
                       $changes{$item} = 1;
                       $domconfig{'coursecategories'}{$item} = $env{'form.coursecat_'.$item};
                   }
               }
         }          }
     } else {      } else {
         $changes{'togglecats'} = 1;          $changes{'togglecats'} = 1;
         $changes{'categorize'} = 1;          $changes{'categorize'} = 1;
         $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) {
               if ($env{'form.coursecat_'.$item} ne 'std') {
                   $changes{$item} = 1;
               }
               if (grep(/^\Q$env{'form.coursecat_'.$item}\E$/,@cattypes)) {
                   $domconfig{'coursecategories'}{$item} = $env{'form.coursecat_'.$item};
               }
           }
     }      }
     if (ref($cathash) eq 'HASH') {      if (ref($cathash) eq 'HASH') {
         if (($domconfig{'coursecategories'}{'cats'}{'instcode::0'} ne '')  && ($env{'form.instcode'} == 0)) {          if (($domconfig{'coursecategories'}{'cats'}{'instcode::0'} ne '')  && ($env{'form.instcode'} == 0)) {
Line 7314  sub modify_coursecategories { Line 12624  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 7376  sub modify_coursecategories { Line 12689  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 7428  sub modify_coursecategories { Line 12755  sub modify_coursecategories {
                          dom  => 'set in Domain ("Modify Course/Community")',                           dom  => 'set in Domain ("Modify Course/Community")',
                          crs  => 'set in Course ("Course Configuration")',                           crs  => 'set in Course ("Course Configuration")',
                          comm => 'set in Community ("Community Configuration")',                           comm => 'set in Community ("Community Configuration")',
                            none     => 'No catalog',
                            std      => 'Standard catalog',
                            domonly  => 'Domain-only catalog',
                            codesrch => 'Code search form',
                         );                          );
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             if ($changes{'togglecats'}) {              if ($changes{'togglecats'}) {
Line 7442  sub modify_coursecategories { Line 12773  sub modify_coursecategories {
             if ($changes{'categorizecomm'}) {              if ($changes{'categorizecomm'}) {
                 $resulttext .= '<li>'.&mt("$title{'categorizecomm'} $level{$env{'form.categorizecomm'}}").'</li>';                  $resulttext .= '<li>'.&mt("$title{'categorizecomm'} $level{$env{'form.categorizecomm'}}").'</li>';
             }              }
               if ($changes{'unauth'}) {
                   $resulttext .= '<li>'.&mt('Catalog type for unauthenticated users set to "'.$level{$env{'form.coursecat_unauth'}}.'"').'</li>';
               }
               if ($changes{'auth'}) {
                   $resulttext .= '<li>'.&mt('Catalog type for authenticated users set to "'.$level{$env{'form.coursecat_auth'}}.'"').'</li>';
               }
             if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {              if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {
                 my $cathash;                  my $cathash;
                 if (ref($domconfig{'coursecategories'}) eq 'HASH') {                  if (ref($domconfig{'coursecategories'}) eq 'HASH') {
Line 7486  sub modify_coursecategories { Line 12823  sub modify_coursecategories {
                 }                  }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
               if ($changes{'unauth'} || $changes{'auth'}) {
                   my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
                   if ($changes{'auth'}) {
                       $domdefaults{'catauth'} = $domconfig{'coursecategories'}{'auth'};
                   }
                   if ($changes{'unauth'}) {
                       $domdefaults{'catunauth'} = $domconfig{'coursecategories'}{'unauth'};
                   }
                   my $cachetime = 24*60*60;
                   &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
                   if (ref($lastactref) eq 'HASH') {
                       $lastactref->{'domdefaults'} = 1;
                   }
               }
         } else {          } else {
             $resulttext = '<span class="LC_error">'.              $resulttext = '<span class="LC_error">'.
                           &mt('An error occurred: [_1]',$putresult).'</span>';                            &mt('An error occurred: [_1]',$putresult).'</span>';
Line 7621  sub modify_serverstatuses { Line 12972  sub modify_serverstatuses {
 }  }
   
 sub modify_helpsettings {  sub modify_helpsettings {
     my ($r,$dom,$confname,%domconfig) = @_;      my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
     my ($resulttext,$errors,%changes,%helphash);      my ($resulttext,$errors,%changes,%helphash);
     my %defaultchecked = ('submitbugs' => 'on');      my %defaultchecked = ('submitbugs' => 'on');
     my @offon = ('off','on');      my @offon = ('off','on');
     my @toggles = ('submitbugs');      my @toggles = ('submitbugs');
       my %current = ('submitbugs' => '',
                      'adhoc'      => {},
                     );
     if (ref($domconfig{'helpsettings'}) eq 'HASH') {      if (ref($domconfig{'helpsettings'}) eq 'HASH') {
         foreach my $item (@toggles) {          %current = %{$domconfig{'helpsettings'}};
             if ($defaultchecked{$item} eq 'on') {       }
                 if ($domconfig{'helpsettings'}{$item} eq '') {      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
                     if ($env{'form.'.$item} eq '0') {      foreach my $item (@toggles) {
                         $changes{$item} = 1;          if ($defaultchecked{$item} eq 'on') { 
                     }              if ($current{$item} eq '') {
                 } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {                  if ($env{'form.'.$item} eq '0') {
                     $changes{$item} = 1;                      $changes{$item} = 1;
                 }                  }
             } elsif ($defaultchecked{$item} eq 'off') {              } elsif ($current{$item} ne $env{'form.'.$item}) {
                 if ($domconfig{'helpsettings'}{$item} eq '') {                  $changes{$item} = 1;
                     if ($env{'form.'.$item} eq '1') {              }
                         $changes{$item} = 1;          } elsif ($defaultchecked{$item} eq 'off') {
                     }              if ($current{$item} eq '') {
                 } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {                  if ($env{'form.'.$item} eq '1') {
                     $changes{$item} = 1;                      $changes{$item} = 1;
                 }                  }
     }              } elsif ($current{$item} ne $env{'form.'.$item}) {
             if (($env{'form.'.$item} eq '0') || ($env{'form.'.$item} eq '1')) {                  $changes{$item} = 1;
                 $helphash{'helpsettings'}{$item} = $env{'form.'.$item};              }
           }
           if (($env{'form.'.$item} eq '0') || ($env{'form.'.$item} eq '1')) {
               $helphash{'helpsettings'}{$item} = $env{'form.'.$item};
           }
       }
       my $maxnum = $env{'form.helproles_maxnum'};
       my $confname = $dom.'-domainconfig';
       my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');
       my (@allpos,%newsettings,%changedprivs,$newrole);
       my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
       my @accesstypes = ('all','dh','da','none','status','inc','exc');
       my %domhelpdesk = &Apache::lonnet::get_active_domroles($dom,['dh','da']);
       my %lt = &Apache::lonlocal::texthash(
                       s      => 'system',
                       d      => 'domain',
                       order  => 'Display order',
                       access => 'Role usage',
                       all    => 'All with domain helpdesk or helpdesk assistant role',
                       dh     => 'All with domain helpdesk role',
                       da     => 'All with domain helpdesk assistant role',
                       none   => 'None',
                       status => 'Determined based on institutional status',
                       inc    => 'Include all, but exclude specific personnel',
                       exc    => 'Exclude all, but include specific personnel',
       );
       for (my $num=0; $num<=$maxnum; $num++) {
           my ($prefix,$identifier,$rolename,%curr);
           if ($num == $maxnum) {
               next unless ($env{'form.newcusthelp'} == $maxnum);
               $identifier = 'custhelp'.$num;
               $prefix = 'helproles_'.$num;
               $rolename = $env{'form.custhelpname'.$num};
               $rolename=~s/[^A-Za-z0-9]//gs;
               next if ($rolename eq '');
               next if (exists($existing{'rolesdef_'.$rolename}));
               my %newprivs = &Apache::lonuserutils::custom_role_update($rolename,$identifier);
               my $result = &Apache::lonnet::definerole($rolename,$newprivs{'s'},$newprivs{'d'},
                                                        $newprivs{'c'},$confname,$dom);
               if ($result ne 'ok') {
                   $errors .= '<li><span class="LC_error">'.
                              &mt('An error occurred storing the new custom role: [_1]',
                              $result).'</span></li>';
                   next;
               } else {
                   $changedprivs{$rolename} = \%newprivs;
                   $newrole = $rolename;
               }
           } else {
               $prefix = 'helproles_'.$num;
               $rolename = $env{'form.'.$prefix};
               next if ($rolename eq '');
               next unless (exists($existing{'rolesdef_'.$rolename}));
               $identifier = 'custhelp'.$num;
               my %newprivs = &Apache::lonuserutils::custom_role_update($rolename,$identifier);
               my %currprivs;
               ($currprivs{'s'},$currprivs{'d'},$currprivs{'c'}) =
                   split(/\_/,$existing{'rolesdef_'.$rolename});
               foreach my $level ('c','d','s') {
                   if ($newprivs{$level} ne $currprivs{$level}) {
                       my $result = &Apache::lonnet::definerole($rolename,$newprivs{'s'},$newprivs{'d'},
                                                                $newprivs{'c'},$confname,$dom);
                       if ($result ne 'ok') {
                           $errors .= '<li><span class="LC_error">'.
                                      &mt('An error occurred storing privileges for existing role [_1]: [_2]',
                                          $rolename,$result).'</span></li>';
                       } else {
                           $changedprivs{$rolename} = \%newprivs;
                       }
                       last;
                   }
               }
               if (ref($current{'adhoc'}) eq 'HASH') {
                   if (ref($current{'adhoc'}{$rolename}) eq 'HASH') {
                       %curr = %{$current{'adhoc'}{$rolename}};
                   }
               }
           }
           my $newpos = $env{'form.'.$prefix.'_pos'};
           $newpos =~ s/\D+//g;
           $allpos[$newpos] = $rolename;
           my $newdesc = $env{'form.'.$prefix.'_desc'};
           $helphash{'helpsettings'}{'adhoc'}{$rolename}{'desc'} = $newdesc;
           if ($curr{'desc'}) {
               if ($curr{'desc'} ne $newdesc) {
                   $changes{'customrole'}{$rolename}{'desc'} = 1;
                   $newsettings{$rolename}{'desc'} = $newdesc;
               }
           } elsif ($newdesc ne '') {
               $changes{'customrole'}{$rolename}{'desc'} = 1;
               $newsettings{$rolename}{'desc'} = $newdesc;
           }
           my $access = $env{'form.'.$prefix.'_access'};
           if (grep(/^\Q$access\E$/,@accesstypes)) {
               $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'} = $access;
               if ($access eq 'status') {
                   my @statuses = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_status');
                   if (scalar(@statuses) == 0) {
                       $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'} = 'none';
                   } else {
                       my (@shownstatus,$numtypes);
                       $helphash{'helpsettings'}{'adhoc'}{$rolename}{$access} = [];
                       if (ref($types) eq 'ARRAY') {
                           $numtypes = scalar(@{$types});
                           foreach my $type (sort(@statuses)) {
                               if ($type eq 'default') {
                                   push(@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}},$type);
                               } elsif (grep(/^\Q$type\E$/,@{$types})) {
                                   push(@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}},$type);
                                   push(@shownstatus,$usertypes->{$type});
                               }
                           }
                       }
                       if (grep(/^default$/,@statuses)) {
                           push(@shownstatus,$othertitle);
                       }
                       if (scalar(@shownstatus) == 1+$numtypes) {
                           $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'} = 'all';
                           delete($helphash{'helpsettings'}{'adhoc'}{$rolename}{'status'});
                       } else {
                           $newsettings{$rolename}{'status'} = join(' '.&mt('or').' ',@shownstatus);
                           if (ref($curr{'status'}) eq 'ARRAY') {
                               my @diffs = &Apache::loncommon::compare_arrays($helphash{'helpsettings'}{'adhoc'}{$rolename}{$access},$curr{$access});
                               if (@diffs) {
                                   $changes{'customrole'}{$rolename}{$access} = 1;
                               }
                           } elsif (@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}}) {
                               $changes{'customrole'}{$rolename}{$access} = 1;
                           }
                       }
                   }
               } elsif (($access eq 'inc') || ($access eq 'exc')) {
                   my @personnel = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_staff_'.$access);
                   my @newspecstaff;
                   $helphash{'helpsettings'}{'adhoc'}{$rolename}{$access} = [];
                   foreach my $person (sort(@personnel)) {
                       if ($domhelpdesk{$person}) {
                           push(@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}},$person);
                       }
                   }
                   if (ref($curr{$access}) eq 'ARRAY') {
                       my @diffs = &Apache::loncommon::compare_arrays($helphash{'helpsettings'}{'adhoc'}{$rolename}{$access},$curr{$access});
                       if (@diffs) {
                           $changes{'customrole'}{$rolename}{$access} = 1;
                       }
                   } elsif (@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}}) {
                       $changes{'customrole'}{$rolename}{$access} = 1;
                   }
                   foreach my $person (@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}}) {
                       my ($uname,$udom) = split(/:/,$person);
                           push(@newspecstaff,&Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$udom,'lastname'),$uname,$udom));
                   }
                   $newsettings{$rolename}{$access} = join(', ',sort(@newspecstaff));
               }
           } else {
               $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'}= 'all';
           }
           unless ($curr{'access'} eq $access) {
               $changes{'customrole'}{$rolename}{'access'} = 1;
               $newsettings{$rolename}{'access'} = $lt{$helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'}};
           }
       }
       if (@allpos > 0) {
           my $idx = 0;
           foreach my $rolename (@allpos) {
               if ($rolename ne '') {
                   $helphash{'helpsettings'}{'adhoc'}{$rolename}{'order'} = $idx;
                   if (ref($current{'adhoc'}) eq 'HASH') {
                       if (ref($current{'adhoc'}{$rolename}) eq 'HASH') {
                           if ($current{'adhoc'}{$rolename}{'order'} ne $idx) {
                               $changes{'customrole'}{$rolename}{'order'} = 1;
                               $newsettings{$rolename}{'order'} = $idx+1;
                           }
                       }
                   }
                   $idx ++;
             }              }
         }          }
     }      }
Line 7654  sub modify_helpsettings { Line 13183  sub modify_helpsettings {
     if (keys(%changes) > 0) {      if (keys(%changes) > 0) {
         $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom);          $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom);
         if ($putresult eq 'ok') {          if ($putresult eq 'ok') {
             $resulttext = &mt('Changes made:').'<ul>';              if (ref($helphash{'helpsettings'}) eq 'HASH') {
                   $domdefaults{'submitbugs'} = $helphash{'helpsettings'}{'submitbugs'};
                   if (ref($helphash{'helpsettings'}{'adhoc'}) eq 'HASH') {
                       $domdefaults{'adhocroles'} = $helphash{'helpsettings'}{'adhoc'};
                   }
               }
               my $cachetime = 24*60*60;
               &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
               }
           } else {
               $errors .= '<li><span class="LC_error">'.
                          &mt('An error occurred storing the settings: [_1]',
                              $putresult).'</span></li>';
           }
       }
       if ((keys(%changes) && ($putresult eq 'ok')) || (keys(%changedprivs))) {
           $resulttext = &mt('Changes made:').'<ul>';
           my (%shownprivs,@levelorder);
           @levelorder = ('c','d','s');
           if ((keys(%changes)) && ($putresult eq 'ok')) {
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
                 if ($item eq 'submitbugs') {                  if ($item eq 'submitbugs') {
                     $resulttext .= '<li>'.&mt('Display link to: [_1] set to "'.$offon[$env{'form.'.$item}].'".',                      $resulttext .= '<li>'.&mt('Display link to: [_1] set to "'.$offon[$env{'form.'.$item}].'".',
                                               &Apache::loncommon::modal_link('http://bugs.loncapa.org',                                                &Apache::loncommon::modal_link('http://bugs.loncapa.org',
                                               &mt('LON-CAPA bug tracker'),600,500)).'</li>';                                                &mt('LON-CAPA bug tracker'),600,500)).'</li>';
                   } elsif ($item eq 'customrole') {
                       if (ref($changes{'customrole'}) eq 'HASH') {
                           my @keyorder = ('order','desc','access','status','exc','inc');
                           my %keytext = &Apache::lonlocal::texthash(
                                                                      order  => 'Order',
                                                                      desc   => 'Role description',
                                                                      access => 'Role usage',
                                                                      status => 'Allowed institutional types',
                                                                      exc    => 'Allowed personnel',
                                                                      inc    => 'Disallowed personnel',
                           );
                           foreach my $role (sort(keys(%{$changes{'customrole'}}))) {
                               if (ref($changes{'customrole'}{$role}) eq 'HASH') {
                                   if ($role eq $newrole) {
                                       $resulttext .= '<li>'.&mt('New custom role added: [_1]',
                                                                 $role).'<ul>';
                                   } else {
                                       $resulttext .= '<li>'.&mt('Existing custom role modified: [_1]',
                                                                 $role).'<ul>';
                                   }
                                   foreach my $key (@keyorder) {
                                       if ($changes{'customrole'}{$role}{$key}) {
                                           $resulttext .= '<li>'.&mt("[_1] set to: [_2]",
                                                                     $keytext{$key},$newsettings{$role}{$key}).
                                                          '</li>';
                                       }
                                   }
                                   if (ref($changedprivs{$role}) eq 'HASH') {
                                       $shownprivs{$role} = 1;
                                       $resulttext .= '<li>'.&mt('Privileges set to :').'<ul>';
                                       foreach my $level (@levelorder) {
                                           foreach my $item (split(/\:/,$changedprivs{$role}{$level})) {
                                               next if ($item eq '');
                                               my ($priv) = split(/\&/,$item,2);
                                               if (&Apache::lonnet::plaintext($priv)) {
                                                   $resulttext .= '<li>'.&Apache::lonnet::plaintext($priv);
                                                   unless ($level eq 'c') {
                                                       $resulttext .= ' ('.$lt{$level}.')';
                                                   }
                                                   $resulttext .= '</li>';
                                               }
                                           }
                                       }
                                       $resulttext .= '</ul>';
                                   }
                                   $resulttext .= '</ul></li>';
                               }
                           }
                       }
                 }                  }
             }              }
             $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;
 }  }
   
 sub modify_coursedefaults {  sub modify_coursedefaults {
     my ($dom,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,$errors,%changes,%defaultshash);      my ($resulttext,$errors,%changes,%defaultshash);
     my %defaultchecked = ('canuse_pdfforms' => 'off');      my %defaultchecked = (
     my @offon = ('off','on');                             'canuse_pdfforms' => 'off',
     my @toggles = ('canuse_pdfforms');                             'uselcmath'       => 'on',
                              'usejsme'         => 'on'
                            );
       my @toggles = ('canuse_pdfforms','uselcmath','usejsme');
       my @numbers = ('anonsurvey_threshold','uploadquota_official','uploadquota_unofficial',
                      'uploadquota_community','uploadquota_textbook','uploadquota_placement',
                      'mysqltables_official','mysqltables_unofficial','mysqltables_community',
                      'mysqltables_textbook','mysqltables_placement');
       my @types = ('official','unofficial','community','textbook','placement');
       my %staticdefaults = (
                              anonsurvey_threshold => 10,
                              uploadquota          => 500,
                              postsubmit           => 60,
                              mysqltables          => 172800,
                            );
   
     $defaultshash{'coursedefaults'} = {};      $defaultshash{'coursedefaults'} = {};
   
Line 7698  sub modify_coursedefaults { Line 13331  sub modify_coursedefaults {
                 if (($domconfig{'coursedefaults'}{$item} eq '') &&                  if (($domconfig{'coursedefaults'}{$item} eq '') &&
                     ($env{'form.'.$item} eq '0')) {                      ($env{'form.'.$item} eq '0')) {
                     $changes{$item} = 1;                      $changes{$item} = 1;
                 } elsif ($domconfig{'coursdefaults'}{$item} ne $env{'form.'.$item}) {                  } elsif ($domconfig{'coursedefaults'}{$item} ne $env{'form.'.$item}) {
                     $changes{$item} = 1;                      $changes{$item} = 1;
                 }                  }
             } elsif ($defaultchecked{$item} eq 'off') {              } elsif ($defaultchecked{$item} eq 'off') {
Line 7711  sub modify_coursedefaults { Line 13344  sub modify_coursedefaults {
             }              }
             $defaultshash{'coursedefaults'}{$item} = $env{'form.'.$item};              $defaultshash{'coursedefaults'}{$item} = $env{'form.'.$item};
         }          }
         my $currdefresponder = $domconfig{'coursedefaults'}{'anonsurvey_threshold'};          foreach my $item (@numbers) {
         my $newdefresponder = $env{'form.anonsurvey_threshold'};              my ($currdef,$newdef);
         $newdefresponder =~ s/\D//g;              $newdef = $env{'form.'.$item};
         if ($newdefresponder eq '' || $newdefresponder < 1) {              if ($item eq 'anonsurvey_threshold') {
             $newdefresponder = 1;                  $currdef = $domconfig{'coursedefaults'}{$item};
         }                  $newdef =~ s/\D//g;
         $defaultshash{'coursedefaults'}{'anonsurvey_threshold'} = $newdefresponder;                  if ($newdef eq '' || $newdef < 1) {
         if ($currdefresponder ne $newdefresponder) {                      $newdef = 1;
             unless ($currdefresponder eq '' && $newdefresponder == 10) {                  }
                 $changes{'anonsurvey_threshold'} = 1;                  $defaultshash{'coursedefaults'}{$item} = $newdef;
               } else {
                   my ($setting,$type) = ($item =~ /^(uploadquota|mysqltables)_(\w+)$/);
                   if (ref($domconfig{'coursedefaults'}{$setting}) eq 'HASH') {
                       $currdef = $domconfig{'coursedefaults'}{$setting}{$type};
                   }
                   $newdef =~ s/[^\w.\-]//g;
                   $defaultshash{'coursedefaults'}{$setting}{$type} = $newdef;
               }
               if ($currdef ne $newdef) {
                   my $staticdef;
                   if ($item eq 'anonsurvey_threshold') {
                       unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) {
                           $changes{$item} = 1;
                       }
                   } elsif ($item =~ /^(uploadquota|mysqltables)_/) {
                       my $setting = $1;
                       unless (($currdef eq '') && ($newdef == $staticdefaults{$setting})) {
                           $changes{$setting} = 1;
                       }
                   }
               }
           }
           my $currclone = $domconfig{'coursedefaults'}{'canclone'};
           my @currclonecode;
           if (ref($currclone) eq 'HASH') {
               if (ref($currclone->{'instcode'}) eq 'ARRAY') {
                   @currclonecode = @{$currclone->{'instcode'}};
               }
           }
           my $newclone;
           if ($env{'form.canclone'} =~ /^(none|domain|instcode)$/) {
               $newclone = $env{'form.canclone'};
           }
           if ($newclone eq 'instcode') {
               my @newcodes = &Apache::loncommon::get_env_multiple('form.clonecode');
               my (%codedefaults,@code_order,@clonecode);
               &Apache::lonnet::auto_instcode_defaults($dom,\%codedefaults,
                                                       \@code_order);
               foreach my $item (@code_order) {
                   if (grep(/^\Q$item\E$/,@newcodes)) {
                       push(@clonecode,$item);
                   }
               }
               if (@clonecode) {
                   $defaultshash{'coursedefaults'}{'canclone'} = { $newclone => \@clonecode };
                   my @diffs = &Apache::loncommon::compare_arrays(\@currclonecode,\@clonecode);
                   if (@diffs) {
                       $changes{'canclone'} = 1;
                   }
               } else {
                   $newclone eq '';
               }
           } elsif ($newclone ne '') {
               $defaultshash{'coursedefaults'}{'canclone'} = $newclone;
           }
           if ($newclone ne $currclone) {
               $changes{'canclone'} = 1;
           }
           my %credits;
           foreach my $type (@types) {
               unless ($type eq 'community') {
                   $credits{$type} = $env{'form.'.$type.'_credits'};
                   $credits{$type} =~ s/[^\d.]+//g;
               }
           }
           if ((ref($domconfig{'coursedefaults'}{'coursecredits'}) ne 'HASH') &&
               ($env{'form.coursecredits'} eq '1')) {
               $changes{'coursecredits'} = 1;
               foreach my $type (keys(%credits)) {
                   $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type};
               }
           } else {
               if ($env{'form.coursecredits'} eq '1') {
                   foreach my $type (@types) {
                       unless ($type eq 'community') {
                           if ($domconfig{'coursedefaults'}{'coursecredits'}{$type} ne $credits{$type}) {
                               $changes{'coursecredits'} = 1;
                           }
                           $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type};
                       }
                   }
               } elsif (ref($domconfig{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
                   foreach my $type (@types) {
                       unless ($type eq 'community') {
                           if ($domconfig{'coursedefaults'}{'coursecredits'}{$type}) {
                               $changes{'coursecredits'} = 1;
                               last;
                           }
                       }
                   }
               }
           }
           if ($env{'form.postsubmit'} eq '1') {
               $defaultshash{'coursedefaults'}{'postsubmit'}{'client'} = 'on';
               my %currtimeout;
               if (ref($domconfig{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
                   if ($domconfig{'coursedefaults'}{'postsubmit'}{'client'} eq 'off') {
                       $changes{'postsubmit'} = 1;
                   }
                   if (ref($domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {
                       %currtimeout = %{$domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}};
                   }
               } else {
                   $changes{'postsubmit'} = 1;
               }
               foreach my $type (@types) {
                   my $timeout = $env{'form.'.$type.'_timeout'};
                   $timeout =~ s/\D//g;
                   if ($timeout == $staticdefaults{'postsubmit'}) {
                       $timeout = '';
                   } elsif (($timeout eq '') || ($timeout =~ /^0+$/)) {
                       $timeout = '0';
                   }
                   unless ($timeout eq '') {
                       $defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}{$type} = $timeout;
                   }
                   if (exists($currtimeout{$type})) {
                       if ($timeout ne $currtimeout{$type}) {
                           $changes{'postsubmit'} = 1;
                       }
                   } elsif ($timeout ne '') {
                       $changes{'postsubmit'} = 1;
                   }
               }
           } else {
               $defaultshash{'coursedefaults'}{'postsubmit'}{'client'} = 'off';
               if (ref($domconfig{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
                   if ($domconfig{'coursedefaults'}{'postsubmit'}{'client'} eq 'on') {
                       $changes{'postsubmit'} = 1;
                   }
               } else {
                   $changes{'postsubmit'} = 1;
             }              }
         }          }
     }      }
Line 7728  sub modify_coursedefaults { Line 13493  sub modify_coursedefaults {
                                              $dom);                                               $dom);
     if ($putresult eq 'ok') {      if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {          if (keys(%changes) > 0) {
             if ($changes{'canuse_pdfforms'}) {              my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
                 my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);              if (($changes{'canuse_pdfforms'}) || ($changes{'uploadquota'}) || ($changes{'postsubmit'}) ||
                 $domdefaults{'canuse_pdfforms'}=$defaultshash{'coursedefaults'}{'canuse_pdfforms'};                  ($changes{'coursecredits'}) || ($changes{'uselcmath'}) || ($changes{'usejsme'}) ||
                   ($changes{'canclone'}) || ($changes{'mysqltables'})) {
                   foreach my $item ('canuse_pdfforms','uselcmath','usejsme') { 
                       if ($changes{$item}) {
                           $domdefaults{$item}=$defaultshash{'coursedefaults'}{$item};
                       }
                   }
                   if ($changes{'coursecredits'}) {
                       if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
                           foreach my $type (keys(%{$defaultshash{'coursedefaults'}{'coursecredits'}})) {
                               $domdefaults{$type.'credits'} =
                                   $defaultshash{'coursedefaults'}{'coursecredits'}{$type};
                           }
                       }
                   }
                   if ($changes{'postsubmit'}) {
                       if (ref($defaultshash{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
                           $domdefaults{'postsubmit'} = $defaultshash{'coursedefaults'}{'postsubmit'}{'client'};
                           if (ref($defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {
                               foreach my $type (keys(%{$defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}})) {
                                   $domdefaults{$type.'postsubtimeout'} =
                                       $defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}{$type};
                               }
                           }
                       }
                   }
                   if ($changes{'uploadquota'}) {
                       if (ref($defaultshash{'coursedefaults'}{'uploadquota'}) eq 'HASH') {
                           foreach my $type (@types) {
                               $domdefaults{$type.'quota'}=$defaultshash{'coursedefaults'}{'uploadquota'}{$type};
                           }
                       }
                   }
                   if ($changes{'canclone'}) {
                       if (ref($defaultshash{'coursedefaults'}{'canclone'}) eq 'HASH') {
                           if (ref($defaultshash{'coursedefaults'}{'canclone'}{'instcode'}) eq 'ARRAY') {
                               my @clonecodes = @{$defaultshash{'coursedefaults'}{'canclone'}{'instcode'}};
                               if (@clonecodes) {
                                   $domdefaults{'canclone'} = join('+',@clonecodes);
                               }
                           }
                       } else {
                           $domdefaults{'canclone'}=$defaultshash{'coursedefaults'}{'canclone'};
                       }
                   }
                 my $cachetime = 24*60*60;                  my $cachetime = 24*60*60;
                 &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);                  &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
                   if (ref($lastactref) eq 'HASH') {
                       $lastactref->{'domdefaults'} = 1;
                   }
             }              }
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             foreach my $item (sort(keys(%changes))) {              foreach my $item (sort(keys(%changes))) {
Line 7742  sub modify_coursedefaults { Line 13554  sub modify_coursedefaults {
                     } else {                      } else {
                         $resulttext .= '<li>'.&mt('Course/Community users can create/upload PDF forms set to "off"').'</li>';                          $resulttext .= '<li>'.&mt('Course/Community users can create/upload PDF forms set to "off"').'</li>';
                     }                      }
                   } elsif ($item eq 'uselcmath') {
                       if ($env{'form.'.$item} eq '1') {
                           $resulttext .= '<li>'.&mt('Math preview uses LON-CAPA previewer (javascript), if supported by browser.').'</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('Math preview uses DragMath (Java), if supported by client OS.').'</li>';
                       }
                   } elsif ($item eq 'usejsme') {
                       if ($env{'form.'.$item} eq '1') {
                           $resulttext .= '<li>'.&mt('Molecule editor uses JSME (HTML5), if supported by browser.').'</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('Molecule editor uses JME (Java), if supported by client OS.').'</li>';
                       }
                 } elsif ($item eq 'anonsurvey_threshold') {                  } elsif ($item eq 'anonsurvey_threshold') {
                         $resulttext .= '<li>'.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'</li>';                      $resulttext .= '<li>'.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'</li>';
                   } elsif ($item eq 'uploadquota') {
                       if (ref($defaultshash{'coursedefaults'}{'uploadquota'}) eq 'HASH') {
                           $resulttext .= '<li>'.&mt('Default quota for content uploaded to a course/community via Course Editor set as follows:').'<ul>'.
                                          '<li>'.&mt('Official courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'official'}.'</b>').'</li>'.
                                          '<li>'.&mt('Unofficial courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'unofficial'}.'</b>').'</li>'.
                                          '<li>'.&mt('Textbook courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'textbook'}.'</b>').'</li>'.
                                          '<li>'.&mt('Placement tests: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'placement'}.'</b>').'</li>'. 
                                          '<li>'.&mt('Communities: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'community'}.'</b>').'</li>'.
                                          '</ul>'.
                                          '</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('Default quota for content uploaded via Course Editor remains default: [_1] MB',$staticdefaults{'uploadquota'}).'</li>';
                       }
                   } elsif ($item eq 'mysqltables') {
                       if (ref($defaultshash{'coursedefaults'}{'mysqltables'}) eq 'HASH') {
                           $resulttext .= '<li>'.&mt('Lifetime of "Temporary" MySQL tables (student performance data) on homeserver').'<ul>'.
                                          '<li>'.&mt('Official courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'official'}.'</b>').'</li>'.
                                          '<li>'.&mt('Unofficial courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'unofficial'}.'</b>').'</li>'.
                                          '<li>'.&mt('Textbook courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'textbook'}.'</b>').'</li>'.
                                          '<li>'.&mt('Placement tests: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'placement'}.'</b>').'</li>'.
                                          '<li>'.&mt('Communities: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'community'}.'</b>').'</li>'.
                                          '</ul>'.
                                          '</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('Lifetime of "Temporary" MySQL tables (student performance data) on homeserver remains default: [_1] s',$staticdefaults{'uploadquota'}).'</li>';
                       }
                   } elsif ($item eq 'postsubmit') {
                       if ($domdefaults{'postsubmit'} eq 'off') {
                           $resulttext .= '<li>'.&mt('Submit button(s) remain enabled on page after student makes submission.');
                       } else {
                           $resulttext .= '<li>'.&mt('Submit button(s) disabled on page after student makes submission').'; ';
                           if (ref($defaultshash{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
                               $resulttext .= &mt('durations:').'<ul>';
                               foreach my $type (@types) {
                                   $resulttext .= '<li>';
                                   my $timeout;
                                   if (ref($defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {
                                       $timeout = $defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}{$type};
                                   }
                                   my $display;
                                   if ($timeout eq '0') {
                                       $display = &mt('unlimited');
                                   } elsif ($timeout eq '') {
                                       $display = &mt('[quant,_1,second] (default)',$staticdefaults{'postsubmit'});
                                   } else {
                                       $display = &mt('[quant,_1,second]',$timeout);
                                   }
                                   if ($type eq 'community') {
                                       $resulttext .= &mt('Communities');
                                   } elsif ($type eq 'official') {
                                       $resulttext .= &mt('Official courses');
                                   } elsif ($type eq 'unofficial') {
                                       $resulttext .= &mt('Unofficial courses');
                                   } elsif ($type eq 'textbook') {
                                       $resulttext .= &mt('Textbook courses');
                                   } elsif ($type eq 'placement') {
                                       $resulttext .= &mt('Placement tests');
                                   }
                                   $resulttext .= ' -- '.$display.'</li>';
                               }
                               $resulttext .= '</ul>';
                           }
                           $resulttext .= '</li>';
                       }
                   } elsif ($item eq 'coursecredits') {
                       if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
                           if (($domdefaults{'officialcredits'} eq '') &&
                               ($domdefaults{'unofficialcredits'} eq '') &&
                               ($domdefaults{'textbookcredits'} eq '')) {
                               $resulttext .= '<li>'.&mt('Student credits not in use for courses in this domain').'</li>';
                           } else {
                               $resulttext .= '<li>'.&mt('Student credits can be set per course by a Domain Coordinator, with the following defaults applying:').'<ul>'.
                                              '<li>'.&mt('Official courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'official'}).'</li>'.
                                              '<li>'.&mt('Unofficial courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'unofficial'}).'</li>'.
                                              '<li>'.&mt('Textbook courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'textbook'}).'</li>'.
                                              '</ul>'.
                                              '</li>';
                           }
                       } else {
                           $resulttext .= '<li>'.&mt('Student credits not in use for courses in this domain').'</li>';
                       }
                   } elsif ($item eq 'canclone') {
                       if (ref($defaultshash{'coursedefaults'}{'canclone'}) eq 'HASH') {
                           if (ref($defaultshash{'coursedefaults'}{'canclone'}{'instcode'}) eq 'ARRAY') {
                               my $clonecodes = join(' '.&mt('and').' ',@{$defaultshash{'coursedefaults'}{'canclone'}{'instcode'}});
                               $resulttext .= '<li>'.&mt('By default, official courses can be cloned from existing courses with the same: [_1]','<b>'.$clonecodes.'</b>').'</li>';
                           }
                       } elsif ($defaultshash{'coursedefaults'}{'canclone'} eq 'domain') {
                           $resulttext .= '<li>'.&mt('By default, a course requester can clone any course from his/her domain.').'</li>';
                       } else {
                           $resulttext .= '<li>'.&mt('By default, only course owner and coordinators may clone a course.').'</li>';
                       }
                 }                  }
             }              }
             $resulttext .= '</ul>';              $resulttext .= '</ul>';
Line 7757  sub modify_coursedefaults { Line 13673  sub modify_coursedefaults {
     return $resulttext;      return $resulttext;
 }  }
   
   sub modify_selfenrollment {
       my ($dom,$lastactref,%domconfig) = @_;
       my ($resulttext,$errors,%changes,%selfenrollhash,%ordered);
       my @types = ('official','unofficial','community','textbook','placement');
       my %titles = &tool_titles();
       my %descs = &Apache::lonuserutils::selfenroll_default_descs();
       ($ordered{'admin'},my $titlesref) = &Apache::lonuserutils::get_selfenroll_titles();
       $ordered{'default'} = ['types','registered','approval','limit'];
   
       my (%roles,%shown,%toplevel);
       $roles{'0'} = &Apache::lonnet::plaintext('dc');
   
       if (ref($domconfig{'selfenrollment'}) ne 'HASH') {
           if ($domconfig{'selfenrollment'} eq '') {
               $domconfig{'selfenrollment'} = {};
           }
       }
       %toplevel = (
                     admin      => 'Configuration Rights',
                     default    => 'Default settings',
                     validation => 'Validation of self-enrollment requests',
                   );
       my ($itemsref,$namesref,$fieldsref) = &Apache::lonuserutils::selfenroll_validation_types();
   
       if (ref($ordered{'admin'}) eq 'ARRAY') {
           foreach my $item (@{$ordered{'admin'}}) {
               foreach my $type (@types) {
                   if ($env{'form.selfenrolladmin_'.$item.'_'.$type}) {
                       $selfenrollhash{'admin'}{$type}{$item} = 1;
                   } else {
                       $selfenrollhash{'admin'}{$type}{$item} = 0;
                   }
                   if (ref($domconfig{'selfenrollment'}{'admin'}) eq 'HASH') {
                       if (ref($domconfig{'selfenrollment'}{'admin'}{$type}) eq 'HASH') {
                           if ($selfenrollhash{'admin'}{$type}{$item} ne
                               $domconfig{'selfenrollment'}{'admin'}{$type}{$item})  {
                               push(@{$changes{'admin'}{$type}},$item);
                           }
                       } else {
                           if (!$selfenrollhash{'admin'}{$type}{$item}) {
                               push(@{$changes{'admin'}{$type}},$item);
                           }
                       }
                   } elsif (!$selfenrollhash{'admin'}{$type}{$item}) {
                       push(@{$changes{'admin'}{$type}},$item);
                   }
               }
           }
       }
   
       foreach my $item (@{$ordered{'default'}}) {
           foreach my $type (@types) {
               my $value = $env{'form.selfenrolldefault_'.$item.'_'.$type};
               if ($item eq 'types') {
                   unless (($value eq 'all') || ($value eq 'dom')) {
                       $value = '';
                   }
               } elsif ($item eq 'registered') {
                   unless ($value eq '1') {
                       $value = 0;
                   }
               } elsif ($item eq 'approval') {
                   unless ($value =~ /^[012]$/) {
                       $value = 0;
                   }
               } else {
                   unless (($value eq 'allstudents') || ($value eq 'selfenrolled')) {
                       $value = 'none';
                   }
               }
               $selfenrollhash{'default'}{$type}{$item} = $value;
               if (ref($domconfig{'selfenrollment'}{'default'}) eq 'HASH') {
                   if (ref($domconfig{'selfenrollment'}{'default'}{$type}) eq 'HASH') {
                       if ($selfenrollhash{'default'}{$type}{$item} ne
                            $domconfig{'selfenrollment'}{'default'}{$type}{$item})  {
                            push(@{$changes{'default'}{$type}},$item);
                       }
                   } else {
                       push(@{$changes{'default'}{$type}},$item);
                   }
               } else {
                   push(@{$changes{'default'}{$type}},$item);
               }
               if ($item eq 'limit') {
                   if (($value eq 'allstudents') || ($value eq 'selfenrolled')) {
                       $env{'form.selfenrolldefault_cap_'.$type} =~ s/\D//g;
                       if ($env{'form.selfenrolldefault_cap_'.$type} ne '') {
                           $selfenrollhash{'default'}{$type}{'cap'} = $env{'form.selfenrolldefault_cap_'.$type};
                       }
                   } else {
                       $selfenrollhash{'default'}{$type}{'cap'} = '';
                   }
                   if (ref($domconfig{'selfenrollment'}{'default'}{$type}) eq 'HASH') {
                       if ($selfenrollhash{'default'}{$type}{'cap'} ne
                            $domconfig{'selfenrollment'}{'admin'}{$type}{'cap'})  {
                            push(@{$changes{'default'}{$type}},'cap');
                       }
                   } elsif ($selfenrollhash{'default'}{$type}{'cap'} ne '') {
                       push(@{$changes{'default'}{$type}},'cap');
                   }
               }
           }
       }
   
       foreach my $item (@{$itemsref}) {
           if ($item eq 'fields') {
               my @changed;
               @{$selfenrollhash{'validation'}{$item}} = &Apache::loncommon::get_env_multiple('form.selfenroll_validation_'.$item);
               if (@{$selfenrollhash{'validation'}{$item}} > 0) {
                   @{$selfenrollhash{'validation'}{$item}} = sort(@{$selfenrollhash{'validation'}{$item}});
               }
               if (ref($domconfig{'selfenrollment'}{'validation'}) eq 'HASH') {
                   if (ref($domconfig{'selfenrollment'}{'validation'}{$item}) eq 'ARRAY') {
                       @changed = &Apache::loncommon::compare_arrays($selfenrollhash{'validation'}{$item},
                                                                     $domconfig{'selfenrollment'}{'validation'}{$item});
                   } else {
                       @changed = @{$selfenrollhash{'validation'}{$item}};
                   }
               } else {
                   @changed = @{$selfenrollhash{'validation'}{$item}};
               }
               if (@changed) {
                   if ($selfenrollhash{'validation'}{$item}) { 
                       $changes{'validation'}{$item} = join(', ',@{$selfenrollhash{'validation'}{$item}});
                   } else {
                       $changes{'validation'}{$item} = &mt('None');
                   }
               }
           } else {
               $selfenrollhash{'validation'}{$item} = $env{'form.selfenroll_validation_'.$item};
               if ($item eq 'markup') {
                  if ($env{'form.selfenroll_validation_'.$item}) {
                      $env{'form.selfenroll_validation_'.$item} =~ s/[\n\r\f]+/\s/gs;
                  }
               }
               if (ref($domconfig{'selfenrollment'}{'validation'}) eq 'HASH') {
                   if ($domconfig{'selfenrollment'}{'validation'}{$item} ne $selfenrollhash{'validation'}{$item}) {
                       $changes{'validation'}{$item} = $selfenrollhash{'validation'}{$item};
                   }
               }
           }
       }
   
       my $putresult = &Apache::lonnet::put_dom('configuration',{'selfenrollment' => \%selfenrollhash},
                                                $dom);
       if ($putresult eq 'ok') {
           if (keys(%changes) > 0) {
               my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
               $resulttext = &mt('Changes made:').'<ul>';
               foreach my $key ('admin','default','validation') {
                   if (ref($changes{$key}) eq 'HASH') {
                       $resulttext .= '<li>'.$toplevel{$key}.'<ul>';
                       if ($key eq 'validation') {
                           foreach my $item (@{$itemsref}) {
                               if (exists($changes{$key}{$item})) {
                                   if ($item eq 'markup') {
                                       $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$namesref->{$item},
                                                                 '<br /><pre>'.$changes{$key}{$item}.'</pre>').'</li>';
                                   } else {  
                                       $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$namesref->{$item},
                                                                 '<b>'.$changes{$key}{$item}.'</b>').'</li>';
                                   }
                               }
                           }
                       } else {
                           foreach my $type (@types) {
                               if ($type eq 'community') {
                                   $roles{'1'} = &mt('Community personnel');
                               } else {
                                   $roles{'1'} = &mt('Course personnel');
                               }
                               if (ref($changes{$key}{$type}) eq 'ARRAY') {
                                   if (ref($selfenrollhash{$key}{$type}) eq 'HASH') {
                                       if ($key eq 'admin') {
                                           my @mgrdc = ();
                                           if (ref($ordered{$key}) eq 'ARRAY') {
                                               foreach my $item (@{$ordered{'admin'}}) {
                                                   if (ref($selfenrollhash{$key}{$type}) eq 'HASH') { 
                                                       if ($selfenrollhash{$key}{$type}{$item} eq '0') {
                                                           push(@mgrdc,$item);
                                                       }
                                                   }
                                               }
                                               if (@mgrdc) {
                                                   $domdefaults{$type.'selfenrolladmdc'} = join(',',@mgrdc);
                                               } else {
                                                   delete($domdefaults{$type.'selfenrolladmdc'});
                                               }
                                           }
                                       } else {
                                           if (ref($ordered{$key}) eq 'ARRAY') {
                                               foreach my $item (@{$ordered{$key}}) {
                                                   if (grep(/^\Q$item\E$/,@{$changes{$key}{$type}})) {
                                                       $domdefaults{$type.'selfenroll'.$item} =
                                                           $selfenrollhash{$key}{$type}{$item};
                                                   }
                                               }
                                           }
                                       }
                                   }
                                   $resulttext .= '<li>'.$titles{$type}.'<ul>';
                                   foreach my $item (@{$ordered{$key}}) {
                                       if (grep(/^\Q$item\E$/,@{$changes{$key}{$type}})) {
                                           $resulttext .= '<li>';
                                           if ($key eq 'admin') {
                                               $resulttext .= &mt('[_1] -- management by: [_2]',$titlesref->{$item},
                                                                  '<b>'.$roles{$selfenrollhash{'admin'}{$type}{$item}}.'</b>');
                                           } else {
                                               $resulttext .= &mt('[_1] set to: [_2]',$titlesref->{$item},
                                                                  '<b>'.$descs{$item}{$selfenrollhash{'default'}{$type}{$item}}.'</b>');
                                           }
                                           $resulttext .= '</li>';
                                       }
                                   }
                                   $resulttext .= '</ul></li>';
                               }
                           }
                           $resulttext .= '</ul></li>'; 
                       }
                   }
                   if ((exists($changes{'admin'})) || (exists($changes{'default'}))) {
                       my $cachetime = 24*60*60;
                       &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
                       if (ref($lastactref) eq 'HASH') {
                           $lastactref->{'domdefaults'} = 1;
                       }
                   }
               }
               $resulttext .= '</ul>';
           } else {
               $resulttext = &mt('No changes made to self-enrollment settings');
           }
       } else {
           $resulttext = '<span class="LC_error">'.
               &mt('An error occurred: [_1]',$putresult).'</span>';
       }
       return $resulttext;
   }
   
 sub modify_usersessions {  sub modify_usersessions {
     my ($dom,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my @hostingtypes = ('version','excludedomain','includedomain');      my @hostingtypes = ('version','excludedomain','includedomain');
     my @offloadtypes = ('primary','default');      my @offloadtypes = ('primary','default');
     my %types = (      my %types = (
Line 7768  sub modify_usersessions { Line 13923  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) {
         $defaultshash{'usersessions'}{$prefix} = {};          $defaultshash{'usersessions'}{$prefix} = {};
     }      }
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);      my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
     my $resulttext;      my $resulttext;
     my %iphost = &Apache::lonnet::get_iphost();      my %iphost = &Apache::lonnet::get_iphost();
     foreach my $prefix (@prefixes) {      foreach my $prefix (@prefixes) {
Line 7923  sub modify_usersessions { Line 14078  sub modify_usersessions {
             $changes{'spares'}{$lonhost} = \%spareschg;              $changes{'spares'}{$lonhost} = \%spareschg;
         }          }
     }      }
       $defaultshash{'usersessions'}{'offloadnow'} = {};
       my @offloadnow = &Apache::loncommon::get_env_multiple('form.offloadnow');
       my @okoffload;
       if (@offloadnow) {
           foreach my $server (@offloadnow) {
               if (&Apache::lonnet::hostname($server) ne '') {
                   unless (grep(/^\Q$server\E$/,@okoffload)) {
                       push(@okoffload,$server);
                   }
               }
           }
           if (@okoffload) {
               foreach my $lonhost (@okoffload) {
                   $defaultshash{'usersessions'}{'offloadnow'}{$lonhost} = 1;
               }
           }
       }
     if (ref($domconfig{'usersessions'}) eq 'HASH') {      if (ref($domconfig{'usersessions'}) eq 'HASH') {
         if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') {          if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') {
             if (ref($changes{'spares'}) eq 'HASH') {              if (ref($changes{'spares'}) eq 'HASH') {
Line 7934  sub modify_usersessions { Line 14105  sub modify_usersessions {
         } else {          } else {
             $savespares = 1;              $savespares = 1;
         }          }
           if (ref($domconfig{'usersessions'}{'offloadnow'}) eq 'HASH') {
               foreach my $lonhost (keys(%{$domconfig{'usersessions'}{'offloadnow'}})) {
                   unless ($defaultshash{'usersessions'}{'offloadnow'}{$lonhost}) {
                       $changes{'offloadnow'} = 1;
                       last;
                   }
               }
               unless ($changes{'offloadnow'}) {
                   foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{'offloadnow'}})) {
                       unless ($domconfig{'usersessions'}{'offloadnow'}{$lonhost}) {
                           $changes{'offloadnow'} = 1;
                           last;
                       }
                   }
               }
           } elsif (@okoffload) {
               $changes{'offloadnow'} = 1;
           }
       } elsif (@okoffload) {
           $changes{'offloadnow'} = 1;
     }      }
   
     my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');      my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');
     if ((keys(%changes) > 0) || ($savespares)) {      if ((keys(%changes) > 0) || ($savespares)) {
         my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,          my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
Line 7948  sub modify_usersessions { Line 14138  sub modify_usersessions {
                 if (ref($defaultshash{'usersessions'}{'hosted'}) eq 'HASH') {                  if (ref($defaultshash{'usersessions'}{'hosted'}) eq 'HASH') {
                     $domdefaults{'hostedsessions'} = $defaultshash{'usersessions'}{'hosted'};                      $domdefaults{'hostedsessions'} = $defaultshash{'usersessions'}{'hosted'};
                 }                  }
                   if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
                       $domdefaults{'offloadnow'} = $defaultshash{'usersessions'}{'offloadnow'};
                   }
             }              }
             my $cachetime = 24*60*60;              my $cachetime = 24*60*60;
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);              &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               &Apache::lonnet::do_cache_new('usersessions',$dom,$defaultshash{'usersessions'},3600);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
                   $lastactref->{'usersessions'} = 1;
               }
             if (keys(%changes) > 0) {              if (keys(%changes) > 0) {
                 my %lt = &usersession_titles();                  my %lt = &usersession_titles();
                 $resulttext = &mt('Changes made:').'<ul>';                  $resulttext = &mt('Changes made:').'<ul>';
Line 7962  sub modify_usersessions { Line 14160  sub modify_usersessions {
                                 foreach my $lonhost (sort(keys(%{$changes{$prefix}}))) {                                  foreach my $lonhost (sort(keys(%{$changes{$prefix}}))) {
                                     $resulttext .= '<li><b>'.$lonhost.'</b> ';                                      $resulttext .= '<li><b>'.$lonhost.'</b> ';
                                     my $lonhostdom = &Apache::lonnet::host_domain($lonhost);                                      my $lonhostdom = &Apache::lonnet::host_domain($lonhost);
                                     &Apache::lonnet::remote_devalidate_cache($lonhost,'spares',$lonhostdom);                                      my $cachekey = &escape('spares').':'.&escape($lonhostdom);
                                       &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
                                     if (ref($changes{$prefix}{$lonhost}) eq 'HASH') {                                      if (ref($changes{$prefix}{$lonhost}) eq 'HASH') {
                                         foreach my $type (@{$types{$prefix}}) {                                          foreach my $type (@{$types{$prefix}}) {
                                             if ($changes{$prefix}{$lonhost}{$type}) {                                              if ($changes{$prefix}{$lonhost}{$type}) {
Line 8012  sub modify_usersessions { Line 14211  sub modify_usersessions {
                         $resulttext .= '</ul>';                          $resulttext .= '</ul>';
                     }                      }
                 }                  }
                   if ($changes{'offloadnow'}) {
                       if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
                           if (keys(%{$defaultshash{'usersessions'}{'offloadnow'}}) > 0) {
                               $resulttext .= '<li>'.&mt('Switch active users on next access, for server(s):').'<ul>';
                               foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadnow'}}))) {
                                   $resulttext .= '<li>'.$lonhost.'</li>';
                               }
                               $resulttext .= '</ul>';
                           } else {
                               $resulttext .= '<li>'.&mt('No servers now set to switch active users on next access.');
                           }
                       } else {
                           $resulttext .= '<li>'.&mt('No servers now set to switch active users on next access.').'</li>';
                       }
                   }
                   $resulttext .= '</ul>';
               } else {
                   $resulttext = $nochgmsg;
               }
           } else {
               $resulttext = '<span class="LC_error">'.
                             &mt('An error occurred: [_1]',$putresult).'</span>';
           }
       } else {
           $resulttext = $nochgmsg;
       }
       return $resulttext;
   }
   
   sub modify_ssl {
       my ($dom,$lastactref,%domconfig) = @_;
       my (%by_ip,%by_location,@intdoms,@instdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
       my @locations = sort(keys(%by_location));
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my (%defaultshash,%changes);
       my $action = 'ssl';
       my @prefixes = ('connto','connfrom','replication');
       foreach my $prefix (@prefixes) {
           $defaultshash{$action}{$prefix} = {};
       }
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
       my $resulttext;
       my %iphost = &Apache::lonnet::get_iphost();
       my @reptypes = ('certreq','nocertreq');
       my @connecttypes = ('dom','intdom','other');
       my %types = (
                     connto      => \@connecttypes,
                     connfrom    => \@connecttypes,
                     replication => \@reptypes,
                   );
       foreach my $prefix (sort(keys(%types))) {
           foreach my $type (@{$types{$prefix}}) {
               if (($prefix eq 'connto') || ($prefix eq 'connfrom')) {
                   my $value = 'yes';
                   if ($env{'form.'.$prefix.'_'.$type} =~ /^(no|req)$/) {
                       $value = $env{'form.'.$prefix.'_'.$type};
                   }
                   if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
                       if ($domconfig{$action}{$prefix}{$type} ne '') {
                           if ($value ne $domconfig{$action}{$prefix}{$type}) {
                               $changes{$prefix}{$type} = 1;
                           }
                           $defaultshash{$action}{$prefix}{$type} = $value;
                       } else {
                           $defaultshash{$action}{$prefix}{$type} = $value;
                           $changes{$prefix}{$type} = 1;
                       }
                   } else {
                       $defaultshash{$action}{$prefix}{$type} = $value;
                       $changes{$prefix}{$type} = 1;
                   }
                   if (($type eq 'dom') && (keys(%servers) == 1)) {
                       delete($changes{$prefix}{$type});
                   } elsif (($type eq 'intdom') && (@instdoms == 1)) {
                       delete($changes{$prefix}{$type});
                   } elsif (($type eq 'other') && (keys(%by_location) == 0)) { 
                       delete($changes{$prefix}{$type});
                   }
               } elsif ($prefix eq 'replication') {
                   if (@locations > 0) {
                       my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
                       my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
                       my @okvals;
                       foreach my $val (@vals) {
                           if ($val =~ /:/) {
                               my @items = split(/:/,$val);
                               foreach my $item (@items) {
                                   if (ref($by_location{$item}) eq 'ARRAY') {
                                       push(@okvals,$item);
                                   }
                               }
                           } else {
                               if (ref($by_location{$val}) eq 'ARRAY') {
                                   push(@okvals,$val);
                               }
                           }
                       }
                       @okvals = sort(@okvals);
                       if (ref($domconfig{$action}) eq 'HASH') {
                           if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
                               if (ref($domconfig{$action}{$prefix}{$type}) eq 'ARRAY') {
                                   if ($inuse == 0) {
                                       $changes{$prefix}{$type} = 1;
                                   } else {
                                       $defaultshash{$action}{$prefix}{$type} = \@okvals;
                                       my @changed = &Apache::loncommon::compare_arrays($domconfig{$action}{$prefix}{$type},$defaultshash{$action}{$prefix}{$type});
                                       if (@changed > 0) {
                                           $changes{$prefix}{$type} = 1;
                                       }
                                   }
                               } else {
                                   if ($inuse == 1) {
                                       $defaultshash{$action}{$prefix}{$type} = \@okvals;
                                       $changes{$prefix}{$type} = 1;
                                   }
                               }
                           } else {
                               if ($inuse == 1) {
                                   $defaultshash{$action}{$prefix}{$type} = \@okvals;
                                   $changes{$prefix}{$type} = 1;
                               }
                           }
                       } else {
                           if ($inuse == 1) {
                               $defaultshash{$action}{$prefix}{$type} = \@okvals;
                               $changes{$prefix}{$type} = 1;
                           }
                       }
                   }
               }
           }
       }
       my $nochgmsg = &mt('No changes made to LON-CAPA SSL settings');
       if (keys(%changes) > 0) {
           my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                                    $dom);
           if ($putresult eq 'ok') {
               if (ref($defaultshash{$action}) eq 'HASH') {
                   if (ref($defaultshash{$action}{'replication'}) eq 'HASH') {
                       $domdefaults{'replication'} = $defaultshash{$action}{'replication'};
                   }
                   if (ref($defaultshash{$action}{'connto'}) eq 'HASH') {
                       $domdefaults{'connto'} = $domconfig{$action}{'connto'};
                   }
                   if (ref($defaultshash{$action}{'connfrom'}) eq 'HASH') {
                       $domdefaults{'connfrom'} = $domconfig{$action}{'connfrom'};
                   }
               }
               my $cachetime = 24*60*60;
               &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
               }
               if (keys(%changes) > 0) {
                   my %titles = &ssl_titles();
                   $resulttext = &mt('Changes made:').'<ul>';
                   foreach my $prefix (@prefixes) {
                       if (ref($changes{$prefix}) eq 'HASH') {
                           $resulttext .= '<li>'.$titles{$prefix}.'<ul>';
                           foreach my $type (@{$types{$prefix}}) {
                               if (defined($changes{$prefix}{$type})) {
                                   my $newvalue;
                                   if (ref($defaultshash{$action}) eq 'HASH') {
                                       if (ref($defaultshash{$action}{$prefix})) {
                                           if (($prefix eq 'connto') || ($prefix eq 'connfrom')) {
                                               $newvalue = $titles{$defaultshash{$action}{$prefix}{$type}};
                                           } elsif (ref($defaultshash{$action}{$prefix}{$type}) eq 'ARRAY') {
                                               if (@{$defaultshash{$action}{$prefix}{$type}} > 0) {
                                                   $newvalue = join(', ',@{$defaultshash{$action}{$prefix}{$type}});
                                               }
                                           }
                                       }
                                       if ($newvalue eq '') {
                                           $resulttext .= '<li>'.&mt('[_1] set to: none',$titles{$type}).'</li>';
                                       } else {
                                           $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$titles{$type},$newvalue).'</li>';
                                       }
                                   }
                               }
                           }
                           $resulttext .= '</ul>';
                       }
                   }
               } else {
                   $resulttext = $nochgmsg;
               }
           } else {
               $resulttext = '<span class="LC_error">'.
                             &mt('An error occurred: [_1]',$putresult).'</span>';
           }
       } else {
           $resulttext = $nochgmsg;
       }
       return $resulttext;
   }
   
   sub modify_trust {
       my ($dom,$lastactref,%domconfig) = @_;
       my (%by_ip,%by_location,@intdoms,@instdoms);
       &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
       my @locations = sort(keys(%by_location));
       my @prefixes = qw(content shared enroll othcoau coaurem domroles catalog reqcrs msg);
       my @types = ('exc','inc');
       my (%defaultshash,%changes);
       foreach my $prefix (@prefixes) {
           $defaultshash{'trust'}{$prefix} = {};
       }
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
       my $resulttext;
       foreach my $prefix (@prefixes) {
           foreach my $type (@types) {
               my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
               my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
               my @okvals;
               foreach my $val (@vals) {
                   if ($val =~ /:/) {
                       my @items = split(/:/,$val);
                       foreach my $item (@items) {
                           if (ref($by_location{$item}) eq 'ARRAY') {
                               push(@okvals,$item);
                           }
                       }
                   } else {
                       if (ref($by_location{$val}) eq 'ARRAY') {
                           push(@okvals,$val);
                       }
                   }
               }
               @okvals = sort(@okvals);
               if (ref($domconfig{'trust'}) eq 'HASH') {
                   if (ref($domconfig{'trust'}{$prefix}) eq 'HASH') {
                       if (ref($domconfig{'trust'}{$prefix}{$type}) eq 'ARRAY') {
                           if ($inuse == 0) {
                               $changes{$prefix}{$type} = 1;
                           } else {
                               $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                               my @changed = &Apache::loncommon::compare_arrays($domconfig{'trust'}{$prefix}{$type},$defaultshash{'trust'}{$prefix}{$type});
                               if (@changed > 0) {
                                   $changes{$prefix}{$type} = 1;
                               }
                           }
                       } else {
                           if ($inuse == 1) {
                               $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                               $changes{$prefix}{$type} = 1;
                           }
                       }
                   } else {
                       if ($inuse == 1) {
                           $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                           $changes{$prefix}{$type} = 1;
                       }
                   }
               } else {
                   if ($inuse == 1) {
                       $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
                       $changes{$prefix}{$type} = 1;
                   }
               }
           }
       }
       my $nochgmsg = &mt('No changes made to trust settings.');
       if (keys(%changes) > 0) {
           my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                                    $dom);
           if ($putresult eq 'ok') {
               if (ref($defaultshash{'trust'}) eq 'HASH') {
                   foreach my $prefix (@prefixes) {
                       if (ref($defaultshash{'trust'}{$prefix}) eq 'HASH') {
                           $domdefaults{'trust'.$prefix} = $defaultshash{'trust'}{$prefix};
                       }
                   }
               }
               my $cachetime = 24*60*60;
               &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
               if (ref($lastactref) eq 'HASH') {
                   $lastactref->{'domdefaults'} = 1;
               }
               if (keys(%changes) > 0) {
                   my %lt = &trust_titles();
                   $resulttext = &mt('Changes made:').'<ul>';
                   foreach my $prefix (@prefixes) {
                       if (ref($changes{$prefix}) eq 'HASH') {
                           $resulttext .= '<li>'.$lt{$prefix}.'<ul>';
                           foreach my $type (@types) {
                               if (defined($changes{$prefix}{$type})) {
                                   my $newvalue;
                                   if (ref($defaultshash{'trust'}) eq 'HASH') {
                                       if (ref($defaultshash{'trust'}{$prefix})) {
                                           if (ref($defaultshash{'trust'}{$prefix}{$type}) eq 'ARRAY') {
                                               if (@{$defaultshash{'trust'}{$prefix}{$type}} > 0) {
                                                   $newvalue = join(', ',@{$defaultshash{'trust'}{$prefix}{$type}});
                                               }
                                           }
                                       }
                                   }
                                   if ($newvalue eq '') {
                                       $resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';
                                   } else {
                                       $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';
                                   }
                               }
                           }
                           $resulttext .= '</ul>';
                       }
                   }
                 $resulttext .= '</ul>';                  $resulttext .= '</ul>';
             } else {              } else {
                 $resulttext = $nochgmsg;                  $resulttext = $nochgmsg;
Line 8033  sub modify_loadbalancing { Line 14539  sub modify_loadbalancing {
     my ($othertitle,$usertypes,$types) =      my ($othertitle,$usertypes,$types) =
         &Apache::loncommon::sorted_inst_types($dom);          &Apache::loncommon::sorted_inst_types($dom);
     my %servers = &Apache::lonnet::internet_dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my %libraryservers = &Apache::lonnet::get_servers($dom,'library');
     my @sparestypes = ('primary','default');      my @sparestypes = ('primary','default');
     my %typetitles = &sparestype_titles();      my %typetitles = &sparestype_titles();
     my $resulttext;      my $resulttext;
     if (keys(%servers) > 1) {      my (%currbalancer,%currtargets,%currrules,%existing);
         my ($currbalancer,$currtargets,$currrules);      if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
         if (ref($domconfig{'loadbalancing'}) eq 'HASH') {          %existing = %{$domconfig{'loadbalancing'}};
             $currbalancer = $domconfig{'loadbalancing'}{'lonhost'};      }
             $currtargets = $domconfig{'loadbalancing'}{'targets'};      &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
             $currrules = $domconfig{'loadbalancing'}{'rules'};                                \%currtargets,\%currrules);
         } else {      my ($saveloadbalancing,%defaultshash,%changes);
             ($currbalancer,$currtargets) =       my ($alltypes,$othertypes,$titles) =
                 &Apache::lonnet::get_lonbalancer_config(\%servers);          &loadbalancing_titles($dom,$intdom,$usertypes,$types);
         }      my %ruletitles = &offloadtype_text();
         my ($saveloadbalancing,%defaultshash,%changes);      my @deletions = &Apache::loncommon::get_env_multiple('form.loadbalancing_delete');
         my ($alltypes,$othertypes,$titles) =      for (my $i=0; $i<$env{'form.loadbalancing_total'}; $i++) {
             &loadbalancing_titles($dom,$intdom,$usertypes,$types);          my $balancer = $env{'form.loadbalancing_lonhost_'.$i};
         my %ruletitles = &offloadtype_text();          if ($balancer eq '') {
         my $balancer = $env{'form.loadbalancing_lonhost'};              next;
         if (!$servers{$balancer}) {          }
             undef($balancer);          if (!exists($servers{$balancer})) {
         }              if (exists($currbalancer{$balancer})) {
         if ($currbalancer ne $balancer) {                  push(@{$changes{'delete'}},$balancer);
             $changes{'lonhost'} = 1;  
         }  
         $defaultshash{'loadbalancing'}{'lonhost'} = $balancer;  
         if ($balancer ne '') {  
             unless (ref($domconfig{'loadbalancing'}) eq 'HASH') {  
                 $saveloadbalancing = 1;  
             }              }
             foreach my $sparetype (@sparestypes) {              next;
                 my @targets = &Apache::loncommon::get_env_multiple('form.loadbalancing_target_'.$sparetype);          }
                 my @offloadto;          if ((@deletions > 0) && (grep(/^\Q$i\E$/,@deletions))) {
                 foreach my $target (@targets) {              push(@{$changes{'delete'}},$balancer);
                     if (($servers{$target}) && ($target ne $balancer)) {              next;
                         if ($sparetype eq 'default') {          }
                             if (ref($defaultshash{'loadbalancing'}{'targets'}{'primary'}) eq 'ARRAY') {          if (!exists($currbalancer{$balancer})) {
                                 next if (grep(/^\Q$target\E$/,@{$defaultshash{'loadbalancing'}{'targets'}{'primary'}}));              push(@{$changes{'add'}},$balancer);
                             }          }
                         }          $defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'} = [];
                         unless(grep(/^\Q$target\E$/,@offloadto)) {          $defaultshash{'loadbalancing'}{$balancer}{'targets'}{'default'} = [];
                             push(@offloadto,$target);          $defaultshash{'loadbalancing'}{$balancer}{'rules'} = {};
           unless (ref($domconfig{'loadbalancing'}) eq 'HASH') {
               $saveloadbalancing = 1;
           }
           foreach my $sparetype (@sparestypes) {
               my @targets = &Apache::loncommon::get_env_multiple('form.loadbalancing_target_'.$i.'_'.$sparetype);
               my @offloadto;
               foreach my $target (@targets) {
                   if (($servers{$target}) && ($target ne $balancer)) {
                       if ($sparetype eq 'default') {
                           if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'}) eq 'ARRAY') {
                               next if (grep(/^\Q$target\E$/,@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'}}));
                         }                          }
                     }                      }
                     $defaultshash{'loadbalancing'}{'targets'}{$sparetype} = \@offloadto;                      unless(grep(/^\Q$target\E$/,@offloadto)) {
                           push(@offloadto,$target);
                       }
                 }                  }
             }              }
         } else {              if ($env{'form.loadbalancing_target_'.$i.'_hosthere'} eq $sparetype) {
             foreach my $sparetype (@sparestypes) {                  unless(grep(/^\Q$balancer\E$/,@offloadto)) {
                 $defaultshash{'loadbalancing'}{'targets'}{$sparetype} = [];                      push(@offloadto,$balancer);
                   }
             }              }
               $defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto;
         }          }
         if (ref($currtargets) eq 'HASH') {          if (ref($currtargets{$balancer}) eq 'HASH') {
             foreach my $sparetype (@sparestypes) {              foreach my $sparetype (@sparestypes) {
                 if (ref($currtargets->{$sparetype}) eq 'ARRAY') {                  if (ref($currtargets{$balancer}{$sparetype}) eq 'ARRAY') {
                     my @targetdiffs = &Apache::loncommon::compare_arrays($currtargets->{$sparetype},$defaultshash{'loadbalancing'}{'targets'}{$sparetype});                      my @targetdiffs = &Apache::loncommon::compare_arrays($currtargets{$balancer}{$sparetype},$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype});
                     if (@targetdiffs > 0) {                      if (@targetdiffs > 0) {
                         $changes{'targets'} = 1;                          $changes{'curr'}{$balancer}{'targets'} = 1;
                     }                      }
                 } elsif (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') {                  } elsif (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
                     if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) {                      if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {
                         $changes{'targets'} = 1;                          $changes{'curr'}{$balancer}{'targets'} = 1;
                     }                      }
                 }                  }
             }              }
         } else {          } else {
             foreach my $sparetype (@sparestypes) {              if (ref($defaultshash{'loadbalancing'}{$balancer}) eq 'HASH') {
                 if (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') {                  foreach my $sparetype (@sparestypes) {
                     if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) {                      if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
                         $changes{'targets'} = 1;                            if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {
                               $changes{'curr'}{$balancer}{'targets'} = 1;
                           }
                     }                      }
                 }                  }
             }                }
         }          }
         my $ishomedom;          my $ishomedom;
         if ($balancer ne '') {          if (&Apache::lonnet::host_domain($balancer) eq $dom) {
             if (&Apache::lonnet::host_domain($balancer) eq $dom) {              $ishomedom = 1;
                 $ishomedom = 1;  
             }  
         }          }
         if (ref($alltypes) eq 'ARRAY') {          if (ref($alltypes) eq 'ARRAY') {
             foreach my $type (@{$alltypes}) {              foreach my $type (@{$alltypes}) {
                 my $rule;                  my $rule;
                 if ($balancer ne '') {                  unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) &&
                     unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) &&   
                          (!$ishomedom)) {                           (!$ishomedom)) {
                         $rule = $env{'form.loadbalancing_rules_'.$type};                      $rule = $env{'form.loadbalancing_rules_'.$i.'_'.$type};
                     }                  }
                     if ($rule eq 'specific') {                  if ($rule eq 'specific') {
                         $rule = $env{'form.loadbalancing_singleserver_'.$type};                      my $specifiedhost = $env{'form.loadbalancing_singleserver_'.$i.'_'.$type};
                       if (exists($servers{$specifiedhost})) {
                           $rule = $specifiedhost;
                     }                      }
                 }                  }
                 $defaultshash{'loadbalancing'}{'rules'}{$type} = $rule;                  $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type} = $rule;
                 if (ref($currrules) eq 'HASH') {                  if (ref($currrules{$balancer}) eq 'HASH') {
                     if ($rule ne $currrules->{$type}) {                      if ($rule ne $currrules{$balancer}{$type}) {
                         $changes{'rules'}{$type} = 1;                          $changes{'curr'}{$balancer}{'rules'}{$type} = 1;
                     }                      }
                 } elsif ($rule ne '') {                  } elsif ($rule ne '') {
                     $changes{'rules'}{$type} = 1;                      $changes{'curr'}{$balancer}{'rules'}{$type} = 1;
                 }                  }
             }              }
         }          }
         my $nochgmsg = &mt('No changes made to Load Balancer settings.');      }
         if ((keys(%changes) > 0) || ($saveloadbalancing)) {      my $nochgmsg = &mt('No changes made to Load Balancer settings.');
             my $putresult = &Apache::lonnet::put_dom('configuration',      if ((keys(%changes) > 0) || ($saveloadbalancing)) {
                                                      \%defaultshash,$dom);          unless (ref($defaultshash{'loadbalancing'}) eq 'HASH') {
             if ($putresult eq 'ok') {              $defaultshash{'loadbalancing'} = {};
                 if (keys(%changes) > 0) {          }
                     if ($changes{'lonhost'}) {          my $putresult = &Apache::lonnet::put_dom('configuration',
                         if ($currbalancer ne '') {                                                   \%defaultshash,$dom);
                             &Apache::lonnet::remote_devalidate_cache($currbalancer,'loadbalancing',$dom);          if ($putresult eq 'ok') {
                         }              if (keys(%changes) > 0) {
                         if ($balancer eq '') {                  my %toupdate;
                             $resulttext .= '<li>'.&mt('Load Balancing with dedicated server discontinued').'</li>';                   if (ref($changes{'delete'}) eq 'ARRAY') {
                         } else {                      foreach my $balancer (sort(@{$changes{'delete'}})) {
                             &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom);                          $resulttext .= '<li>'.&mt('Load Balancing discontinued for: [_1]',$balancer).'</li>';
                             $resulttext .= '<li>'.&mt('Dedicated Load Balancer server set to [_1]',$balancer);                          $toupdate{$balancer} = 1;
                         }                      }
                     } else {                  }
                         &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom);                  if (ref($changes{'add'}) eq 'ARRAY') {
                     }                      foreach my $balancer (sort(@{$changes{'add'}})) {
                     if (($changes{'targets'}) && ($balancer ne '')) {                          $resulttext .= '<li>'.&mt('Load Balancing enabled for: [_1]',$balancer);
                         my %offloadstr;                          $toupdate{$balancer} = 1;
                         foreach my $sparetype (@sparestypes) {                      }
                             if (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') {                  }
                                 if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) {                  if (ref($changes{'curr'}) eq 'HASH') {
                                     $offloadstr{$sparetype} = join(', ',@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}});                      foreach my $balancer (sort(keys(%{$changes{'curr'}}))) {
                           $toupdate{$balancer} = 1;
                           if (ref($changes{'curr'}{$balancer}) eq 'HASH') {
                               if ($changes{'curr'}{$balancer}{'targets'}) {
                                   my %offloadstr;
                                   foreach my $sparetype (@sparestypes) {
                                       if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
                                           if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {
                                               $offloadstr{$sparetype} = join(', ',@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}});
                                           }
                                       }
                                   }
                                   if (keys(%offloadstr) == 0) {
                                       $resulttext .= '<li>'.&mt("Servers to which Load Balance server offloads set to 'None', by default").'</li>';
                                   } else {
                                       my $showoffload;
                                       foreach my $sparetype (@sparestypes) {
                                           $showoffload .= '<i>'.$typetitles{$sparetype}.'</i>:&nbsp;';
                                           if (defined($offloadstr{$sparetype})) {
                                               $showoffload .= $offloadstr{$sparetype};
                                           } else {
                                               $showoffload .= &mt('None');
                                           }
                                           $showoffload .= ('&nbsp;'x3);
                                       }
                                       $resulttext .= '<li>'.&mt('By default, Load Balancer: [_1] set to offload to - [_2]',$balancer,$showoffload).'</li>';
                                 }                                  }
                             }                              }
                         }                          }
                         if (keys(%offloadstr) == 0) {                          if (ref($changes{'curr'}{$balancer}{'rules'}) eq 'HASH') {
                             $resulttext .= '<li>'.&mt("Servers to which Load Balance server offloads set to 'None', by default").'</li>';                              if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) {
                         } else {                                  foreach my $type (@{$alltypes}) {
                             my $showoffload;                                      if ($changes{'curr'}{$balancer}{'rules'}{$type}) {
                             foreach my $sparetype (@sparestypes) {                                          my $rule = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type};
                                 $showoffload .= '<i>'.$typetitles{$sparetype}.'</i>:&nbsp;';                                          my $balancetext;
                                 if (defined($offloadstr{$sparetype})) {                                          if ($rule eq '') {
                                     $showoffload .= $offloadstr{$sparetype};                                              $balancetext =  $ruletitles{'default'};
                                 } else {                                          } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer') ||
                                     $showoffload .= &mt('None');                                                   ($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) {
                                               if (($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) {
                                                   foreach my $sparetype (@sparestypes) {
                                                       if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
                                                           map { $toupdate{$_} = 1; } (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}});
                                                       }
                                                   }
                                                   foreach my $item (@{$alltypes}) {
                                                       next if ($item =~  /^_LC_ipchange/);
                                                       my $hasrule = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$item};
                                                       if ($hasrule eq 'homeserver') {
                                                           map { $toupdate{$_} = 1; } (keys(%libraryservers));
                                                       } else {
                                                           unless (($hasrule eq 'default') || ($hasrule eq 'none') || ($hasrule eq 'externalbalancer')) {
                                                               if ($servers{$hasrule}) {
                                                                   $toupdate{$hasrule} = 1;
                                                               }
                                                           }
                                                       }
                                                   }
                                                   if (($rule eq 'balancer') || ($rule eq 'offloadedto')) {
                                                       $balancetext =  $ruletitles{$rule};
                                                   } else {
                                                       my $receiver = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type};
                                                       $balancetext = $ruletitles{'particular'}.' '.$receiver;
                                                       if ($receiver) {
                                                           $toupdate{$receiver};
                                                       }
                                                   }
                                               } else {
                                                   $balancetext =  $ruletitles{$rule};
                                               }
                                           } else {
                                               $balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type});
                                           }
                                           $resulttext .= '<li>'.&mt('Load Balancer: [_1] -- balancing for [_2] set to - "[_3]"',$balancer,$titles->{$type},$balancetext).'</li>';
                                       }
                                 }                                  }
                                 $showoffload .= ('&nbsp;'x3);  
                             }                              }
                             $resulttext .= '<li>'.&mt('By default, Load Balancer server set to offload to: [_1]',$showoffload).'</li>';  
                         }                          }
                     }                          if (keys(%toupdate)) {
                     if ((ref($changes{'rules'}) eq 'HASH') && ($balancer ne '')) {                              my %thismachine;
                         if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) {                              my $updatedhere;
                             foreach my $type (@{$alltypes}) {                              my $cachetime = 60*60*24;
                                 if ($changes{'rules'}{$type}) {                              map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
                                     my $rule = $defaultshash{'loadbalancing'}{'rules'}{$type};                              foreach my $lonhost (keys(%toupdate)) {
                                     my $balancetext;                                  if ($thismachine{$lonhost}) {
                                     if ($rule eq '') {                                      unless ($updatedhere) {
                                         $balancetext =  $ruletitles{'default'};                                          &Apache::lonnet::do_cache_new('loadbalancing',$dom,
                                     } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer')) {                                                                        $defaultshash{'loadbalancing'},
                                         $balancetext =  $ruletitles{$rule};                                                                        $cachetime);
                                     } else {                                          $updatedhere = 1;
                                         $balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{'rules'}{$type});  
                                     }                                      }
                                     $resulttext .= '<li>'.&mt('Load Balancing for [_1] set to: [_2]',$titles->{$type},$balancetext).'</li>';                                       } else {
                                       my $cachekey = &escape('loadbalancing').':'.&escape($dom);
                                       &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
                                 }                                  }
                             }                              }
                         }                          }
                     }                      }
                     if ($resulttext ne '') {                  }
                         $resulttext = &mt('Changes made:').'<ul>'.$resulttext.'</ul>';                  if ($resulttext ne '') {
                     } else {                      $resulttext = &mt('Changes made:').'<ul>'.$resulttext.'</ul>';
                         $resulttext = $nochgmsg;  
                     }  
                 } else {                  } else {
                     $resulttext = $nochgmsg;                      $resulttext = $nochgmsg;
                     if ($balancer ne '') {  
                         &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom);  
                     }  
                 }                  }
             } else {              } else {
                 $resulttext = '<span class="LC_error">'.                  $resulttext = $nochgmsg;
                               &mt('An error occurred: [_1]',$putresult).'</span>';  
             }              }
         } else {          } else {
             $resulttext = $nochgmsg;              $resulttext = '<span class="LC_error">'.
                             &mt('An error occurred: [_1]',$putresult).'</span>';
         }          }
     } else {      } else {
         $resulttext =  &mt('Load Balancing unavailable as this domain only has one server.');          $resulttext = $nochgmsg;
     }      }
     return $resulttext;      return $resulttext;
 }  }
Line 8254  sub recurse_cat_deletes { Line 14826  sub recurse_cat_deletes {
                 delete($coursecategories->{$subitem});                  delete($coursecategories->{$subitem});
                 $deletions->{$subitem} = 1;                  $deletions->{$subitem} = 1;
                 &recurse_cat_deletes($subitem,$coursecategories,$deletions);                  &recurse_cat_deletes($subitem,$coursecategories,$deletions);
             }                }
         }          }
     }      }
     return;      return;
 }  }
   
 sub get_active_dcs {  sub active_dc_picker {
     my ($dom) = @_;      my ($dom,$numinrow,$inputtype,$name,%currhash) = @_;
     my %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc']);      my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);
     my %domcoords;      my @domcoord = keys(%domcoords);
     my $numdcs = 0;      if (keys(%currhash)) {
     my $now = time;          foreach my $dc (keys(%currhash)) {
     foreach my $server (keys(%dompersonnel)) {              unless (exists($domcoords{$dc})) {
         foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {                  push(@domcoord,$dc);
             my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user);  
             my ($end,$start) = split(':',$dompersonnel{$server}{$user});  
             if (($end eq '') || ($end == 0) || ($end > $now)) {  
                 if ($start <= $now) {  
                     $domcoords{$uname.':'.$udom} = $dompersonnel{$server}{$user};  
                 }  
             }              }
         }          }
     }      }
     return %domcoords;      @domcoord = sort(@domcoord);
 }      my $numdcs = scalar(@domcoord);
       my $rows = 0;
 sub active_dc_picker {      my $table;
     my ($dom,$curr_dc) = @_;  
     my %domcoords = &get_active_dcs($dom);   
     my @dcs = sort(keys(%domcoords));  
     my $numdcs = scalar(@dcs);   
     my $datatable;  
     my $numinrow = 2;  
     if ($numdcs > 1) {      if ($numdcs > 1) {
         $datatable = '<table>';          $table = '<table>';
         for (my $i=0; $i<@dcs; $i++) {          for (my $i=0; $i<@domcoord; $i++) {
             my $rem = $i%($numinrow);              my $rem = $i%($numinrow);
             if ($rem == 0) {              if ($rem == 0) {
                 if ($i > 0) {                  if ($i > 0) {
                     $datatable .= '</tr>';                      $table .= '</tr>';
                 }                  }
                 $datatable .= '<tr>';                  $table .= '<tr>';
                   $rows ++;
             }              }
             my $check = ' ';              my $check = '';
             if ($curr_dc eq '') {              if ($inputtype eq 'radio') {
                 if (!$i) {                   if (keys(%currhash) == 0) {
                     $check = ' checked="checked" ';                      if (!$i) {
                           $check = ' checked="checked"';
                       }
                   } elsif (exists($currhash{$domcoord[$i]})) {
                       $check = ' checked="checked"';
                   }
               } else {
                   if (exists($currhash{$domcoord[$i]})) {
                       $check = ' checked="checked"';
                 }                  }
             } elsif ($dcs[$i] eq $curr_dc) {  
                 $check = ' checked="checked" ';  
             }              }
             if ($i == @dcs - 1) {              if ($i == @domcoord - 1) {
                 my $colsleft = $numinrow - $rem;                  my $colsleft = $numinrow - $rem;
                 if ($colsleft > 1) {                  if ($colsleft > 1) {
                     $datatable .= '<td colspan="'.$colsleft.'">';                      $table .= '<td class="LC_left_item" colspan="'.$colsleft.'">';
                 } else {                  } else {
                     $datatable .= '<td>';                      $table .= '<td class="LC_left_item">';
                 }                  }
             } else {              } else {
                 $datatable .= '<td>';                  $table .= '<td class="LC_left_item">';
             }              }
             my ($dcname,$dcdom) = split(':',$dcs[$i]);              my ($dcname,$dcdom) = split(':',$domcoord[$i]);
             $datatable .= '<span class="LC_nobreak"><label>'.              my $user = &Apache::loncommon::plainname($dcname,$dcdom);
                           '<input type="radio" name="autocreate_xmldc"'.              $table .= '<span class="LC_nobreak"><label>'.
                           ' value="'.$dcs[$i].'"'.$check.'/>'.                        '<input type="'.$inputtype.'" name="'.$name.'"'.
                           &Apache::loncommon::plainname($dcname,$dcdom).                        ' value="'.$domcoord[$i].'"'.$check.' />'.$user;
                           '</label></span></td>';              if ($user ne $dcname.':'.$dcdom) {
                   $table .=  ' ('.$dcname.':'.$dcdom.')';
               }
               $table .= '</label></span></td>';
           }
           $table .= '</tr></table>';
       } elsif ($numdcs == 1) {
           my ($dcname,$dcdom) = split(':',$domcoord[0]);
           my $user = &Apache::loncommon::plainname($dcname,$dcdom);
           if ($inputtype eq 'radio') {
               $table = '<input type="hidden" name="'.$name.'" value="'.$domcoord[0].'" />'.$user;
               if ($user ne $dcname.':'.$dcdom) {
                   $table .=  ' ('.$dcname.':'.$dcdom.')';
               }
           } else {
               my $check;
               if (exists($currhash{$domcoord[0]})) {
                   $check = ' checked="checked"';
               }
               $table = '<span class="LC_nobreak"><label>'.
                        '<input type="checkbox" name="'.$name.'" '.
                        'value="'.$domcoord[0].'"'.$check.' />'.$user;
               if ($user ne $dcname.':'.$dcdom) {
                   $table .=  ' ('.$dcname.':'.$dcdom.')';
               }
               $table .= '</label></span>';
               $rows ++;
         }          }
         $datatable .= '</tr></table>';  
     } elsif (@dcs) {  
         $datatable .= '<input type="hidden" name="autocreate_dc" value="'.  
                       $dcs[0].'" />';  
     }      }
     return ($numdcs,$datatable);      return ($numdcs,$table,$rows);
 }  }
   
 sub usersession_titles {  sub usersession_titles {
Line 8371  sub count_servers { Line 14960  sub count_servers {
 }  }
   
 sub lonbalance_targets_js {  sub lonbalance_targets_js {
     my ($dom,$types,$servers) = @_;      my ($dom,$types,$servers,$settings) = @_;
     my $select = &mt('Select');      my $select = &mt('Select');
     my ($alltargets,$allishome,$allinsttypes,@alltypes);      my ($alltargets,$allishome,$allinsttypes,@alltypes);
     if (ref($servers) eq 'HASH') {      if (ref($servers) eq 'HASH') {
Line 8393  sub lonbalance_targets_js { Line 14982  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);
       if (ref($settings) eq 'HASH') {
           %existing = %{$settings};
       }
       &get_loadbalancers_config($servers,\%existing,\%currbalancer,
                                 \%currtargets,\%currrules);
       my $balancers = join("','",sort(keys(%currbalancer)));
     return <<"END";      return <<"END";
   
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
   
 function toggleTargets() {  currBalancers = new Array('$balancers');
     var balancer = document.display.loadbalancing_lonhost.options[document.display.loadbalancing_lonhost.selectedIndex].value;  
   function toggleTargets(balnum) {
       var lonhostitem = document.getElementById('loadbalancing_lonhost_'+balnum);
       var prevhostitem = document.getElementById('loadbalancing_prevlonhost_'+balnum);
       var balancer = lonhostitem.options[lonhostitem.selectedIndex].value;
       var prevbalancer = prevhostitem.value;
       var baltotal = document.getElementById('loadbalancing_total').value;
       prevhostitem.value = balancer;
       if (prevbalancer != '') {
           var prevIdx = currBalancers.indexOf(prevbalancer);
           if (prevIdx != -1) {
               currBalancers.splice(prevIdx,1);
           }
       }
     if (balancer == '') {      if (balancer == '') {
         hideSpares();          hideSpares(balnum);
     } else {      } else {
           var currIdx = currBalancers.indexOf(balancer);
           if (currIdx == -1) {
               currBalancers.push(balancer);
           }
         var homedoms = new Array('$allishome');          var homedoms = new Array('$allishome');
         var ishomedom = homedoms[document.display.loadbalancing_lonhost.selectedIndex];          var ishomedom = homedoms[lonhostitem.selectedIndex];
         showSpares(balancer,ishomedom);          showSpares(balancer,ishomedom,balnum);
     }      }
       balancerChange(balnum,baltotal,'change',prevbalancer,balancer);
     return;      return;
 }  }
   
 function showSpares(balancer,ishomedom) {  function showSpares(balancer,ishomedom,balnum) {
     var alltargets = new Array('$alltargets');      var alltargets = new Array('$alltargets');
     var insttypes = new Array('$allinsttypes');      var insttypes = new Array('$allinsttypes');
     var offloadtypes = new Array('primary','default');      var offloadtypes = new Array('primary','default');
   
     document.getElementById('loadbalancing_targets').style.display='block';      document.getElementById('loadbalancing_targets_'+balnum).style.display='block';
     document.getElementById('loadbalancing_disabled').style.display='none';      document.getElementById('loadbalancing_disabled_'+balnum).style.display='none';
     
     for (var i=0; i<offloadtypes.length; i++) {      for (var i=0; i<offloadtypes.length; i++) {
         var count = 0;          var count = 0;
         for (var j=0; j<alltargets.length; j++) {          for (var j=0; j<alltargets.length; j++) {
             if (alltargets[j] != balancer) {              if (alltargets[j] != balancer) {
                 document.getElementById('loadbalancing_target_'+offloadtypes[i]+'_'+count).value = alltargets[j];                  var item = document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+count);
                 document.getElementById('loadbalancing_targettxt_'+offloadtypes[i]+'_'+count).style.textAlign='left';                  item.value = alltargets[j];
                 document.getElementById('loadbalancing_targettxt_'+offloadtypes[i]+'_'+count).style.textFace='normal';                  item.style.textAlign='left';
                 document.getElementById('loadbalancing_targettxt_'+offloadtypes[i]+'_'+count).innerHTML = alltargets[j];                  item.style.textFace='normal';
                   document.getElementById('loadbalancing_targettxt_'+balnum+'_'+offloadtypes[i]+'_'+count).innerHTML = alltargets[j];
                   if (currBalancers.indexOf(alltargets[j]) == -1) {
                       item.disabled = '';
                   } else {
                       item.disabled = 'disabled';
                       item.checked = false;
                   }
                 count ++;                  count ++;
             }              }
         }          }
Line 8433  function showSpares(balancer,ishomedom) Line 15054  function showSpares(balancer,ishomedom)
     for (var k=0; k<insttypes.length; k++) {      for (var k=0; k<insttypes.length; k++) {
         if ((insttypes[k] == '_LC_external') || (insttypes[k] == '_LC_internetdom')) {          if ((insttypes[k] == '_LC_external') || (insttypes[k] == '_LC_internetdom')) {
             if (ishomedom == 1) {              if (ishomedom == 1) {
                 document.getElementById('balanceruletitle_'+insttypes[k]).style.display='block';                  document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='block';
                 document.getElementById('balancerule_'+insttypes[k]).style.display='block';                  document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='block';
             } else {              } else {
                 document.getElementById('balanceruletitle_'+insttypes[k]).style.display='none';                  document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='none';
                 document.getElementById('balancerule_'+insttypes[k]).style.display='none';                  document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='none';
   
             }              }
         } else {          } else {
             document.getElementById('balanceruletitle_'+insttypes[k]).style.display='block';              document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='block';
             document.getElementById('balancerule_'+insttypes[k]).style.display='block';              document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='block';
         }          }
         if ((insttypes[k] != '_LC_external') &&           if ((insttypes[k] != '_LC_external') && 
             ((insttypes[k] != '_LC_internetdom') ||              ((insttypes[k] != '_LC_internetdom') ||
              ((insttypes[k] == '_LC_internetdom') && (ishomedom == 1)))) {               ((insttypes[k] == '_LC_internetdom') && (ishomedom == 1)))) {
             document.getElementById('loadbalancing_singleserver_'+insttypes[k]).options[0] = new Option("","",true,true);              var item = document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]);
               item.options.length = 0;
               item.options[0] = new Option("","",true,true);
               var idx = 0;
             for (var m=0; m<alltargets.length; m++) {              for (var m=0; m<alltargets.length; m++) {
                 var idx = m+1;                  if ((currBalancers.indexOf(alltargets[m]) == -1) && (alltargets[m] != balancer)) {
                 if (alltargets[m] != balancer) {                      idx ++;
                     document.getElementById('loadbalancing_singleserver_'+insttypes[k]).options[idx] = new Option(alltargets[m],alltargets[m],false,false);                      item.options[idx] = new Option(alltargets[m],alltargets[m],false,false);
                 }                  }
             }              }
         }          }
Line 8459  function showSpares(balancer,ishomedom) Line 15082  function showSpares(balancer,ishomedom)
     return;      return;
 }  }
   
 function hideSpares() {  function hideSpares(balnum) {
     var alltargets = new Array('$alltargets');      var alltargets = new Array('$alltargets');
     var insttypes = new Array('$allinsttypes');      var insttypes = new Array('$allinsttypes');
     var offloadtypes = new Array('primary','default');      var offloadtypes = new Array('primary','default');
   
     document.getElementById('loadbalancing_targets').style.display='none';      document.getElementById('loadbalancing_targets_'+balnum).style.display='none';
     document.getElementById('loadbalancing_disabled').style.display='block';      document.getElementById('loadbalancing_disabled_'+balnum).style.display='block';
   
     var total = alltargets.length - 1;      var total = alltargets.length - 1;
     for (var i=0; i<offloadtypes; i++) {      for (var i=0; i<offloadtypes; i++) {
         for (var j=0; j<total; j++) {          for (var j=0; j<total; j++) {
            document.getElementById('loadbalancing_target_'+offloadtypes[i]+'_'+j).checked = false;             document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+j).checked = false;
            document.getElementById('loadbalancing_target_'+offloadtypes[i]+'_'+j).value = '';             document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+j).value = '';
            document.getElementById('loadbalancing_targettxt_'+offloadtypes[i]+'_'+j).innerHTML = '';             document.getElementById('loadbalancing_targettxt_'+balnum+'_'+offloadtypes[i]+'_'+j).innerHTML = '';
         }          }
     }      }
     for (var k=0; k<insttypes.length; k++) {      for (var k=0; k<insttypes.length; k++) {
         document.getElementById('balanceruletitle_'+insttypes[k]).style.display='none';          document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='none';
         document.getElementById('balancerule_'+insttypes[k]).style.display='none';          document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='none';
         if (insttypes[k] != '_LC_external') {          if (insttypes[k] != '_LC_external') {
             document.getElementById('loadbalancing_singleserver_'+insttypes[k]).length = 0;              document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]).length = 0;
             document.getElementById('loadbalancing_singleserver_'+insttypes[k]).options[0] = new Option("","",true,true);              document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]).options[0] = new Option("","",true,true);
         }          }
     }      }
     return;      return;
 }  }
   
 function checkOffloads(item,type) {  function checkOffloads(item,balnum,type) {
     var alltargets = new Array('$alltargets');      var alltargets = new Array('$alltargets');
     var offloadtypes = new Array('primary','default');      var offloadtypes = new Array('primary','default');
     if (item.checked) {      if (item.checked) {
Line 8498  function checkOffloads(item,type) { Line 15121  function checkOffloads(item,type) {
             other = offloadtypes[0];              other = offloadtypes[0];
         }          }
         for (var i=0; i<total; i++) {          for (var i=0; i<total; i++) {
             var server = document.getElementById('loadbalancing_target_'+other+'_'+i).value;              var server = document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).value;
             if (server == item.value) {              if (server == item.value) {
                 if (document.getElementById('loadbalancing_target_'+other+'_'+i).checked) {                  if (document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).checked) {
                     document.getElementById('loadbalancing_target_'+other+'_'+i).checked = false;                      document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).checked = false;
                 }                  }
             }              }
         }          }
Line 8509  function checkOffloads(item,type) { Line 15132  function checkOffloads(item,type) {
     return;      return;
 }  }
   
 function singleServerToggle(type) {  function singleServerToggle(balnum,type) {
     var offloadtoSelIdx = document.getElementById('loadbalancing_singleserver_'+type).selectedIndex;      var offloadtoSelIdx = document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).selectedIndex;
     if (offloadtoSelIdx == 0) {      if (offloadtoSelIdx == 0) {
         document.getElementById('loadbalancing_rules_'+type+'_0').checked = true;          document.getElementById('loadbalancing_rules_'+balnum+'_'+type+'_0').checked = true;
         document.getElementById('loadbalancing_singleserver_'+type).options[0].text = '';          document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '';
   
     } else {      } else {
         document.getElementById('loadbalancing_rules_'+type+'_2').checked = true;          document.getElementById('loadbalancing_rules_'+balnum+'_'+type+'_2').checked = true;
         document.getElementById('loadbalancing_singleserver_'+type).options[0].text = '$select';          document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '$select';
     }      }
     return;      return;
 }  }
   
 function balanceruleChange(formname,type) {  function balanceruleChange(formname,balnum,type) {
     if (type == '_LC_external') {      if (type == '_LC_external') {
         return;           return;
     }      }
     var typesRules = getIndicesByName(formname,'loadbalancing_rules_'+type);      var typesRules = getIndicesByName(formname,'loadbalancing_rules_'+balnum+'_'+type);
     for (var i=0; i<typesRules.length; i++) {      for (var i=0; i<typesRules.length; i++) {
         if (formname.elements[typesRules[i]].checked) {          if (formname.elements[typesRules[i]].checked) {
             if (formname.elements[typesRules[i]].value != 'specific') {              if (formname.elements[typesRules[i]].value != 'specific') {
                 document.getElementById('loadbalancing_singleserver_'+type).selectedIndex = 0;                  document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).selectedIndex = 0;
                 document.getElementById('loadbalancing_singleserver_'+type).options[0].text = '';                  document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '';
             } else {              } else {
                 document.getElementById('loadbalancing_singleserver_'+type).options[0].text = '$select';                  document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '$select';
               }
           }
       }
       return;
   }
   
   function balancerDeleteChange(balnum) {
       var hostitem = document.getElementById('loadbalancing_lonhost_'+balnum);
       var baltotal = document.getElementById('loadbalancing_total').value;
       var addtarget;
       var removetarget;
       var action = 'delete';
       if (document.getElementById('loadbalancing_delete_'+balnum)) {
           var lonhost = hostitem.value;
           var currIdx = currBalancers.indexOf(lonhost);
           if (document.getElementById('loadbalancing_delete_'+balnum).checked) {
               if (currIdx != -1) {
                   currBalancers.splice(currIdx,1);
               }
               addtarget = lonhost;
           } else {
               if (currIdx == -1) {
                   currBalancers.push(lonhost);
               }
               removetarget = lonhost;
               action = 'undelete';
           }
           balancerChange(balnum,baltotal,action,addtarget,removetarget);
       }
       return;
   }
   
   function balancerChange(balnum,baltotal,action,addtarget,removetarget) {
       if (baltotal > 1) {
           var offloadtypes = new Array('primary','default');
           var alltargets = new Array('$alltargets');
           var insttypes = new Array('$allinsttypes');
           for (var i=0; i<baltotal; i++) {
               if (i != balnum) {
                   for (var j=0; j<offloadtypes.length; j++) {
                       var total = alltargets.length - 1;
                       for (var k=0; k<total; k++) {
                           var serveritem = document.getElementById('loadbalancing_target_'+i+'_'+offloadtypes[j]+'_'+k);
                           var server = serveritem.value;
                           if ((action == 'delete') || (action == 'change' && addtarget != ''))  {
                               if (server == addtarget) {
                                   serveritem.disabled = '';
                               }
                           }
                           if ((action == 'undelete') || (action == 'change' && removetarget != '')) {
                               if (server == removetarget) {
                                   serveritem.disabled = 'disabled';
                                   serveritem.checked = false;
                               }
                           }
                       }
                   }
                   for (var j=0; j<insttypes.length; j++) {
                       if (insttypes[j] != '_LC_external') {
                           if (document.getElementById('loadbalancing_singleserver_'+i+'_'+insttypes[j])) {
                               var singleserver = document.getElementById('loadbalancing_singleserver_'+i+'_'+insttypes[j]);
                               var currSel = singleserver.selectedIndex;
                               var currVal = singleserver.options[currSel].value;
                               if ((action == 'delete') || (action == 'change' && addtarget != '')) {
                                   var numoptions = singleserver.options.length;
                                   var needsnew = 1;
                                   for (var k=0; k<numoptions; k++) {
                                       if (singleserver.options[k] == addtarget) {
                                           needsnew = 0;
                                           break;
                                       }
                                   }
                                   if (needsnew == 1) {
                                       singleserver.options[numoptions] = new Option(addtarget,addtarget,false,false);
                                   }
                               }
                               if ((action == 'undelete') || (action == 'change' && removetarget != '')) {
                                   singleserver.options.length = 0;
                                   if ((currVal) && (currVal != removetarget)) {
                                       singleserver.options[0] = new Option("","",false,false);
                                   } else {
                                       singleserver.options[0] = new Option("","",true,true);
                                   }
                                   var idx = 0;
                                   for (var m=0; m<alltargets.length; m++) {
                                       if (currBalancers.indexOf(alltargets[m]) == -1) {
                                           idx ++;
                                           if (currVal == alltargets[m]) {
                                               singleserver.options[idx] = new Option(alltargets[m],alltargets[m],true,true);
                                           } else {
                                               singleserver.options[idx] = new Option(alltargets[m],alltargets[m],false,false);
                                           }
                                       }
                                   }
                               }
                           }
                       }
                   }
             }              }
         }          }
     }      }
Line 8677  function updateCaptcha(caller,context) { Line 15398  function updateCaptcha(caller,context) {
     var pubitem;      var pubitem;
     var privtext;      var privtext;
     var pubtext;      var pubtext;
       var versionitem;
       var versiontext;
     if (document.getElementById(context+'_recaptchapub')) {      if (document.getElementById(context+'_recaptchapub')) {
         pubitem = document.getElementById(context+'_recaptchapub');          pubitem = document.getElementById(context+'_recaptchapub');
     } else {      } else {
Line 8697  function updateCaptcha(caller,context) { Line 15420  function updateCaptcha(caller,context) {
     } else {      } else {
         return;          return;
     }      }
       if (document.getElementById(context+'_recaptchaversion')) {
           versionitem = document.getElementById(context+'_recaptchaversion');
       } else {
           return;
       }
       if (document.getElementById(context+'_recaptchavertxt')) {
           versiontext = document.getElementById(context+'_recaptchavertxt');
       } else {
           return;
       }
     if (caller.checked) {      if (caller.checked) {
         if (caller.value == 'recaptcha') {          if (caller.value == 'recaptcha') {
             pubitem.type = 'text';              pubitem.type = 'text';
Line 8705  function updateCaptcha(caller,context) { Line 15438  function updateCaptcha(caller,context) {
             privitem.size = '40';              privitem.size = '40';
             pubtext.innerHTML = "$lt{'pub'}";              pubtext.innerHTML = "$lt{'pub'}";
             privtext.innerHTML = "$lt{'priv'}";              privtext.innerHTML = "$lt{'priv'}";
               versionitem.type = 'text';
               versionitem.size = '3';
               versiontext.innerHTML = "$lt{'ver'}";
         } else {          } else {
             pubitem.type = 'hidden';              pubitem.type = 'hidden';
             privitem.type = 'hidden';              privitem.type = 'hidden';
               versionitem.type = 'hidden';
             pubtext.innerHTML = '';              pubtext.innerHTML = '';
             privtext.innerHTML = '';              privtext.innerHTML = '';
               versiontext.innerHTML = '';
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   END
   
   }
   
   sub toggle_display_js {
       return <<"END";
   
   <script type="text/javascript">
   // <![CDATA[
   
   function toggleDisplay(domForm,caller) {
       if (document.getElementById(caller)) {
           var divitem = document.getElementById(caller);
           var optionsElement = domForm.coursecredits;
           var checkval = 1;
           var dispval = 'block';
           var selfcreateRegExp = /^cancreate_emailverified/;
           if (caller == 'emailoptions') {
               optionsElement = domForm.cancreate_email; 
           }
           if (caller == 'studentsubmission') {
               optionsElement = domForm.postsubmit;
           }
           if (caller == 'cloneinstcode') {
               optionsElement = domForm.canclone;
               checkval = 'instcode';
           }
           if (selfcreateRegExp.test(caller)) {
               optionsElement = domForm.elements[caller];
               checkval = 'other';
               dispval = 'inline'
           }
           if (optionsElement.length) {
               var currval;
               for (var i=0; i<optionsElement.length; i++) {
                   if (optionsElement[i].checked) {
                      currval = optionsElement[i].value;
                   }
               }
               if (currval == checkval) {
                   divitem.style.display = dispval;
               } else {
                   divitem.style.display = 'none';
               }
         }          }
     }      }
     return;      return;
Line 8729  sub captcha_phrases { Line 15519  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)',
     );      );
 }  }
   
   sub devalidate_remote_domconfs {
       my ($dom,$cachekeys) = @_;
       return unless (ref($cachekeys) eq 'HASH');
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my %thismachine;
       map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
       my @posscached = ('domainconfig','domdefaults','ltitools','usersessions','directorysrch');
       if (keys(%servers)) {
           foreach my $server (keys(%servers)) {
               next if ($thismachine{$server});
               my @cached;
               foreach my $name (@posscached) {
                   if ($cachekeys->{$name}) {
                       push(@cached,&escape($name).':'.&escape($dom));
                   }
               }
               if (@cached) {
                   &Apache::lonnet::remote_devalidate_cache($server,\@cached);
               }
           }
       }
       return;
   }
   
 1;  1;

Removed from v.1.160.6.6  
changed lines
  Added in v.1.303


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