Diff for /loncom/interface/domainprefs.pm between versions 1.146 and 1.165

version 1.146, 2011/08/01 19:46:49 version 1.165, 2012/08/25 04:34:44
Line 86  $dom,$settings,$rowtotal,$action. Line 86  $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 (either quotas   number of rows displayed on the page, and $action is the context (quotas,  
 or requestcourses).  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
 about default quota sizes for portfolio spaces for the different types of   about default quota sizes for portfolio spaces for the different types of 
Line 171  use Locale::Language; Line 171  use Locale::Language;
 use DateTime::TimeZone;  use DateTime::TimeZone;
 use DateTime::Locale;  use DateTime::Locale;
   
   my $registered_cleanup;
   my $modified_urls;
   
 sub handler {  sub handler {
     my $r=shift;      my $r=shift;
     if ($r->header_only) {      if ($r->header_only) {
Line 190  sub handler { Line 193  sub handler {
         "/adm/domainprefs:mau:0:0:Cannot modify domain settings";          "/adm/domainprefs:mau:0:0:Cannot modify domain settings";
         return HTTP_NOT_ACCEPTABLE;          return HTTP_NOT_ACCEPTABLE;
     }      }
   
       $registered_cleanup=0;
       @{$modified_urls}=();
   
     &Apache::lonhtmlcommon::clear_breadcrumbs();      &Apache::lonhtmlcommon::clear_breadcrumbs();
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                                             ['phase','actions']);                                              ['phase','actions']);
Line 197  sub handler { Line 204  sub handler {
     if ( exists($env{'form.phase'}) ) {      if ( exists($env{'form.phase'}) ) {
         $phase = $env{'form.phase'};          $phase = $env{'form.phase'};
     }      }
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
     my %domconfig =      my %domconfig =
       &Apache::lonnet::get_dom('configuration',['login','rolecolors',        &Apache::lonnet::get_dom('configuration',['login','rolecolors',
                 'quotas','autoenroll','autoupdate','autocreate',                  'quotas','autoenroll','autoupdate','autocreate',
                 'directorysrch','usercreation','usermodification',                  'directorysrch','usercreation','usermodification',
                 'contacts','defaults','scantron','coursecategories',                  'contacts','defaults','scantron','coursecategories',
                 'serverstatuses','requestcourses','helpsettings',                  'serverstatuses','requestcourses','helpsettings',
                 'coursedefaults','usersessions'],$dom);                  'coursedefaults','usersessions','loadbalancing',
                   'requestauthor'],$dom);
     my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',      my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
                        'autoupdate','autocreate','directorysrch','contacts',                         'autoupdate','autocreate','directorysrch','contacts',
                        'usercreation','usermodification','scantron',                         'usercreation','usermodification','scantron',
                        'requestcourses','coursecategories','serverstatuses','helpsettings',                         'requestcourses','requestauthor','coursecategories',
                          'serverstatuses','helpsettings',
                        'coursedefaults','usersessions');                         'coursedefaults','usersessions');
       if (keys(%servers) > 1) {
           push(@prefs_order,'loadbalancing');
       }
     my %prefs = (      my %prefs = (
         'rolecolors' =>          'rolecolors' =>
                    { text => 'Default color schemes',                     { text => 'Default color schemes',
Line 236  sub handler { Line 249  sub handler {
                                   col2 => 'Value'}],                                    col2 => 'Value'}],
                     },                      },
         'quotas' =>           'quotas' => 
                     { text => 'User blogs, personal information pages, portfolios',                      { text => 'Blogs, personal web pages, webDAV, portfolios',
                       help => 'Domain_Configuration_Quotas',                        help => 'Domain_Configuration_Quotas',
                       header => [{col1 => 'User affiliation',                        header => [{col1 => 'User affiliation',
                                   col2 => 'Available tools',                                    col2 => 'Available tools',
Line 312  sub handler { Line 325  sub handler {
                              {col1 => 'Setting',                               {col1 => 'Setting',
                               col2 => 'Value'}],                                col2 => 'Value'}],
                  },                   },
           'requestauthor' =>
                    {text => 'Request authoring space',
                     help => 'Domain_Configuration_Request_Author',
                     header => [{col1 => 'User affiliation',
                                 col2 => 'Availability/Processing of requests',},
                                {col1 => 'Setting',
                                 col2 => 'Value'}],
                    },
         'coursecategories' =>          'coursecategories' =>
                   { text => 'Cataloging of courses/communities',                    { text => 'Cataloging of courses/communities',
                     help => 'Domain_Configuration_Cataloging_Courses',                      help => 'Domain_Configuration_Cataloging_Courses',
Line 361  sub handler { Line 382  sub handler {
                              {col1 => "Hosting domain's own users elsewhere",                               {col1 => "Hosting domain's own users elsewhere",
                               col2 => 'Rules'}],                                col2 => 'Rules'}],
                  },                   },
            'loadbalancing' =>
                    {text  => 'Dedicated Load Balancer',
                     help  => 'Domain_Configuration_Load_Balancing',
                     header => [{col1 => 'Server',
                                 col2 => 'Default destinations',
                                 col3 => 'User affliation',
                                 col4 => 'Overrides'},
                               ],
                    },
     );      );
     my %servers = &dom_servers($dom);  
     if (keys(%servers) > 1) {      if (keys(%servers) > 1) {
         $prefs{'login'}  = { text   => 'Log-in page options',          $prefs{'login'}  = { text   => 'Log-in page options',
                              help   => 'Domain_Configuration_Login_Page',                               help   => 'Domain_Configuration_Login_Page',
Line 381  sub handler { Line 410  sub handler {
     if ($phase eq 'process') {      if ($phase eq 'process') {
         &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,\@roles);          &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,\@roles);
     } elsif ($phase eq 'display') {      } elsif ($phase eq 'display') {
         &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname);          my $js = &recaptcha_js();
           if (keys(%servers) > 1) {
               my ($othertitle,$usertypes,$types) =
                   &Apache::loncommon::sorted_inst_types($dom);
               $js = &lonbalance_targets_js($dom,$types,\%servers).
                     &new_spares_js().
                     &common_domprefs_js().
                     &Apache::loncommon::javascript_array_indexof();
           }
           &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);
     } else {      } else {
         if (keys(%domconfig) == 0) {          if (keys(%domconfig) == 0) {
             my $primarylibserv = &Apache::lonnet::domain($dom,'primary');              my $primarylibserv = &Apache::lonnet::domain($dom,'primary');
Line 459  sub process_changes { Line 497  sub process_changes {
         $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($dom,$action,%domconfig);
       } elsif ($action eq 'requestauthor') {
           $output = &modify_quotas($dom,$action,%domconfig);
     } elsif ($action eq 'helpsettings') {      } elsif ($action eq 'helpsettings') {
         $output = &modify_helpsettings($r,$dom,$confname,%domconfig);          $output = &modify_helpsettings($r,$dom,$confname,%domconfig);
     } elsif ($action eq 'coursedefaults') {      } elsif ($action eq 'coursedefaults') {
         $output = &modify_coursedefaults($dom,%domconfig);          $output = &modify_coursedefaults($dom,%domconfig);
     } elsif ($action eq 'usersessions') {      } elsif ($action eq 'usersessions') {
         $output = &modify_usersessions($dom,%domconfig);          $output = &modify_usersessions($dom,%domconfig);
       } elsif ($action eq 'loadbalancing') {
           $output = &modify_loadbalancing($dom,%domconfig);
     }      }
     return $output;      return $output;
 }  }
Line 519  sub print_config_box { Line 561  sub print_config_box {
             $colspan = ' colspan="2"';              $colspan = ' colspan="2"';
         } elsif ($action eq 'requestcourses') {          } elsif ($action eq 'requestcourses') {
             $output .= &print_quotas($dom,$settings,\$rowtotal,$action);              $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
           } elsif ($action eq 'requestauthor') {
               $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
         } elsif ($action eq 'helpsettings') {          } elsif ($action eq 'helpsettings') {
             $output .= &print_helpsettings('top',$dom,$confname,$settings,\$rowtotal);              $output .= &print_helpsettings('top',$dom,$confname,$settings,\$rowtotal);
         } elsif ($action eq 'usersessions') {          } elsif ($action eq 'usersessions') {
Line 585  sub print_config_box { Line 629  sub print_config_box {
         } elsif ($action eq 'login') {          } elsif ($action eq 'login') {
             $output .= &print_login('bottom',$dom,$confname,$phase,$settings,\$rowtotal);              $output .= &print_login('bottom',$dom,$confname,$phase,$settings,\$rowtotal);
         } elsif ($action eq 'requestcourses') {          } elsif ($action eq 'requestcourses') {
             $output .= &print_courserequestmail($dom,$settings,\$rowtotal);              $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);
           } elsif ($action eq 'requestauthor') {
               $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);
         } elsif ($action eq 'helpsettings') {          } elsif ($action eq 'helpsettings') {
             $output .= &print_helpsettings('bottom',$dom,$confname,$settings,\$rowtotal);              $output .= &print_helpsettings('bottom',$dom,$confname,$settings,\$rowtotal);
         } elsif ($action eq 'usersessions') {          } elsif ($action eq 'usersessions') {
Line 661  sub print_config_box { Line 707  sub print_config_box {
         }          }
         $output .= '</td>';          $output .= '</td>';
         if ($item->{'header'}->[0]->{'col3'}) {          if ($item->{'header'}->[0]->{'col3'}) {
             $output .= '<td class="LC_right_item" valign="top">'.              if (defined($item->{'header'}->[0]->{'col4'})) {
                        &mt($item->{'header'}->[0]->{'col3'});                  $output .= '<td class="LC_left_item" valign="top">'.
                               &mt($item->{'header'}->[0]->{'col3'});
               } else {
                   $output .= '<td class="LC_right_item" valign="top">'.
                              &mt($item->{'header'}->[0]->{'col3'});
               }
             if ($action eq 'serverstatuses') {              if ($action eq 'serverstatuses') {
                 $output .= '<br />(<tt>'.&mt('IP1,IP2 etc.').'</tt>)';                  $output .= '<br />(<tt>'.&mt('IP1,IP2 etc.').'</tt>)';
             }              }
             $output .= '</td>';              $output .= '</td>';
         }          }
           if ($item->{'header'}->[0]->{'col4'}) {
               $output .= '<td class="LC_right_item" valign="top">'.
                          &mt($item->{'header'}->[0]->{'col4'});
           }
         $output .= '</tr>';          $output .= '</tr>';
         $rowtotal ++;          $rowtotal ++;
         if ($action eq 'login') {          if ($action eq 'login') {
Line 691  sub print_config_box { Line 746  sub print_config_box {
             $output .= &print_serverstatuses($dom,$settings,\$rowtotal);              $output .= &print_serverstatuses($dom,$settings,\$rowtotal);
         } elsif ($action eq 'helpsettings') {          } elsif ($action eq 'helpsettings') {
             $output .= &print_helpsettings('top',$dom,$confname,$settings,\$rowtotal);              $output .= &print_helpsettings('top',$dom,$confname,$settings,\$rowtotal);
           } elsif ($action eq 'loadbalancing') {
               $output .= &print_loadbalancing($dom,$settings,\$rowtotal);
         }          }
     }      }
     $output .= '      $output .= '
Line 707  sub print_login { Line 764  sub print_login {
     my %choices = &login_choices();      my %choices = &login_choices();
   
     if ($position eq 'top') {      if ($position eq 'top') {
         my %servers = &dom_servers($dom);          my %servers = &Apache::lonnet::internet_dom_servers($dom);
         my $choice = $choices{'disallowlogin'};          my $choice = $choices{'disallowlogin'};
         $css_class = ' class="LC_odd_row"';          $css_class = ' class="LC_odd_row"';
         $datatable .= '<tr'.$css_class.'><td>'.$choice.'</td>'.          $datatable .= '<tr'.$css_class.'><td>'.$choice.'</td>'.
Line 1017  sub print_rolecolors { Line 1074  sub print_rolecolors {
 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) = @_;
       my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
     my $css_class = $itemcount%2?' class="LC_odd_row"':'';      my $css_class = $itemcount%2?' class="LC_odd_row"':'';
     my $datatable = '<tr'.$css_class.'>'.      my $datatable = '<tr'.$css_class.'>'.
         '<td>'.$choices->{'font'}.'</td>';          '<td>'.$choices->{'font'}.'</td>';
Line 1094  sub display_color_options { Line 1152  sub display_color_options {
                 $showfile = $imgfile;                  $showfile = $imgfile;
                 my $imgdir = $1;                  my $imgdir = $1;
                 my $filename = $2;                  my $filename = $2;
                 if (-e "/home/httpd/html/$imgdir/tn-".$filename) {                  if (-e "$londocroot/$imgdir/tn-".$filename) {
                     $showfile = "/$imgdir/tn-".$filename;                      $showfile = "/$imgdir/tn-".$filename;
                 } else {                  } else {
                     my $input = "/home/httpd/html".$imgfile;                      my $input = $londocroot.$imgfile;
                     my $output = '/home/httpd/html/'.$imgdir.'/tn-'.$filename;                      my $output = "$londocroot/$imgdir/tn-".$filename;
                     if (!-e $output) {                      if (!-e $output) {
                         my ($width,$height) = &thumb_dimensions();                          my ($width,$height) = &thumb_dimensions();
                         my ($fullwidth,$fullheight) = &check_dimensions($input);                          my ($fullwidth,$fullheight) = &check_dimensions($input);
Line 1106  sub display_color_options { Line 1164  sub display_color_options {
                             if ($fullwidth > $width && $fullheight > $height) {                               if ($fullwidth > $width && $fullheight > $height) { 
                                 my $size = $width.'x'.$height;                                  my $size = $width.'x'.$height;
                                 system("convert -sample $size $input $output");                                  system("convert -sample $size $input $output");
                                 $showfile = '/'.$imgdir.'/tn-'.$filename;                                  $showfile = "/$imgdir/tn-".$filename;
                             }                              }
                         }                          }
                     }                      }
Line 1334  sub print_quotas { Line 1392  sub print_quotas {
         @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();
       } elsif ($context eq 'requestauthor') {
           @usertools = ('author');
           @options = ('norequest','approval','automatic');
           %titles = &authorrequest_titles(); 
     } else {      } else {
         @usertools = ('aboutme','blog','portfolio');          @usertools = ('aboutme','blog','webdav','portfolio');
         %titles = &tool_titles();          %titles = &tool_titles();
     }      }
     if (ref($types) eq 'ARRAY') {      if (ref($types) eq 'ARRAY') {
         foreach my $type (@{$types}) {          foreach my $type (@{$types}) {
             my $currdefquota;              my $currdefquota;
             unless ($context eq 'requestcourses') {              unless (($context eq 'requestcourses') ||
                       ($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}; 
Line 1411  sub print_quotas { Line 1474  sub print_quotas {
                                 $cell{$item} .= $titles{'unlimited'};                                  $cell{$item} .= $titles{'unlimited'};
                             }                              }
                         }                          }
                       } elsif ($context eq 'requestauthor') {
                           my $curroption;
                           if (ref($settings) eq 'HASH') {
                               $curroption = $settings->{$type};
                           }
                           if (!$curroption) {
                               $curroption = 'norequest';
                           }
                           foreach my $option (@options) {
                               my $val = $option;
                               if ($option eq 'norequest') {
                                   $val = 0;
                               }
                               my $checked = '';
                               if ($option eq $curroption) {
                                   $checked = ' checked="checked"';
                               }
                               $datatable .= '<span class="LC_nobreak"><label>'.
                                     '<input type="radio" name="authorreq_'.$type.
                                     '" value="'.$val.'"'.$checked.' />'.
                                     $titles{$option}.'</label></span>&nbsp; ';
                           }
                     } else {                      } else {
                         my $checked = 'checked="checked" ';                          my $checked = 'checked="checked" ';
                         if (ref($settings) eq 'HASH') {                          if (ref($settings) eq 'HASH') {
Line 1436  sub print_quotas { Line 1521  sub print_quotas {
                     $datatable .= '</tr></table>';                      $datatable .= '</tr></table>';
                 }                  }
                 $datatable .= '</td>';                  $datatable .= '</td>';
                 unless ($context eq 'requestcourses') {                  unless (($context eq 'requestcourses') ||
                           ($context eq 'requestauthor')) {
                     $datatable .=                       $datatable .= 
                               '<td class="LC_right_item"><span class="LC_nobreak">'.                                '<td class="LC_right_item"><span class="LC_nobreak">'.
                               '<input type="text" name="quota_'.$type.                                '<input type="text" name="quota_'.$type.
Line 1447  sub print_quotas { Line 1533  sub print_quotas {
             }              }
         }          }
     }      }
     unless ($context eq 'requestcourses') {      unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
         $defaultquota = '20';          $defaultquota = '20';
         if (ref($settings) eq 'HASH') {          if (ref($settings) eq 'HASH') {
             if (ref($settings->{'defaultquota'}) eq 'HASH') {              if (ref($settings->{'defaultquota'}) eq 'HASH') {
Line 1517  sub print_quotas { Line 1603  sub print_quotas {
                     $defcell{$item} .= $titles{'unlimited'};                      $defcell{$item} .= $titles{'unlimited'};
                 }                  }
             }              }
           } elsif ($context eq 'requestauthor') {
               my $curroption;
               if (ref($settings) eq 'HASH') {
                   if (ref($settings->{'requestauthor'}) eq 'HASH') {
                       $curroption = $settings->{'requestauthor'};
                   }
               }
               if (!$curroption) {
                   $curroption = 'norequest';
               }
               foreach my $option (@options) {
                   my $val = $option;
                   if ($option eq 'norequest') {
                       $val = 0;
                   }
                   my $checked = '';
                   if ($option eq $curroption) {
                       $checked = ' checked="checked"';
                   }
                   $datatable .= '<span class="LC_nobreak"><label>'.
                                 '<input type="radio" name="authorreq_default"'.
                                 ' value="'.$val.'"'.$checked.' />'.
                                 $titles{$option}.'</label></span>&nbsp; ';
               }
         } else {          } else {
             my $checked = 'checked="checked" ';              my $checked = 'checked="checked" ';
             if (ref($settings) eq 'HASH') {              if (ref($settings) eq 'HASH') {
Line 1542  sub print_quotas { Line 1652  sub print_quotas {
         $datatable .= '</tr></table>';          $datatable .= '</tr></table>';
     }      }
     $datatable .= '</td>';      $datatable .= '</td>';
     unless ($context eq 'requestcourses') {      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">'.
                       '<input type="text" name="defaultquota" value="'.                        '<input type="text" name="defaultquota" value="'.
                       $defaultquota.'" size="5" /> Mb</span></td>';                        $defaultquota.'" size="5" /> Mb</span></td>';
Line 1620  sub print_quotas { Line 1730  sub print_quotas {
                     $advcell{$item} .= $titles{'unlimited'};                      $advcell{$item} .= $titles{'unlimited'};
                 }                  }
             }              }
           } elsif ($context eq 'requestauthor') {
               my $curroption;
               if (ref($settings) eq 'HASH') {
                   $curroption = $settings->{'_LC_adv'};
               }
               my $checked = '';
               if ($curroption eq '') {
                   $checked = ' checked="checked"';
               }
               $datatable .= '<span class="LC_nobreak"><label>'.
                             '<input type="radio" name="authorreq__LC_adv"'.
                             ' value=""'.$checked.' />'.
                             &mt('No override set').'</label></span>&nbsp; ';
               foreach my $option (@options) {
                   my $val = $option;
                   if ($option eq 'norequest') {
                       $val = 0;
                   }
                   my $checked = '';
                   if ($val eq $curroption) {
                       $checked = ' checked="checked"';
                   }
                   $datatable .= '<span class="LC_nobreak"><label>'.
                                 '<input type="radio" name="crsreq_'.$item.
                                 '__LC_adv" value="'.$val.'"'.$checked.' />'.
                                 $titles{$option}.'</label></span>&nbsp; ';
               }
         } else {          } else {
             my $checked = 'checked="checked" ';              my $checked = 'checked="checked" ';
             if (ref($settings) eq 'HASH') {              if (ref($settings) eq 'HASH') {
Line 1649  sub print_quotas { Line 1786  sub print_quotas {
     return $datatable;      return $datatable;
 }  }
   
 sub print_courserequestmail {  sub print_requestmail {
     my ($dom,$settings,$rowtotal) = @_;      my ($dom,$action,$settings,$rowtotal) = @_;
     my ($now,$datatable,%dompersonnel,@domcoord,@currapproval,$rows);      my ($now,$datatable,%dompersonnel,@domcoord,@currapproval,$rows);
     $now = time;      $now = time;
     $rows = 0;      $rows = 0;
Line 1681  sub print_courserequestmail { Line 1818  sub print_courserequestmail {
     my $numinrow = 4;      my $numinrow = 4;
     my $numdc = @domcoord;      my $numdc = @domcoord;
     my $css_class = 'class="LC_odd_row"';      my $css_class = 'class="LC_odd_row"';
     $datatable = '<tr'.$css_class.'>'.      my $text;
                  ' <td>'.&mt('Receive notification of course requests requiring approval.').      if ($action eq 'requestcourses') {
                  ' </td>'.          $text = &mt('Receive notification of course requests requiring approval');
       } else {
           $text = &mt('Receive notification of authoring space requests requiring approval')
       }
       $datatable = '<tr '.$css_class.'>'.
                    ' <td>'.$text.'</td>'.
                  ' <td class="LC_left_item">';                   ' <td class="LC_left_item">';
     if (@domcoord > 0) {      if (@domcoord > 0) {
         $datatable .= '<table>';          $datatable .= '<table>';
Line 2208  sub print_helpsettings { Line 2350  sub print_helpsettings {
         $datatable .= '</span></td></tr>';          $datatable .= '</span></td></tr>';
                   
      }       }
        
      return $datatable;       return $datatable;
   
 }  }
   
   
Line 2306  sub print_usersessions { Line 2446  sub print_usersessions {
     &build_location_hashes(\@intdoms,\%by_ip,\%by_location);      &build_location_hashes(\@intdoms,\%by_ip,\%by_location);
   
     my @alldoms = &Apache::lonnet::all_domains();      my @alldoms = &Apache::lonnet::all_domains();
     my %uniques = &Apache::lonnet::get_unique_servers(\@alldoms);      my %serverhomes = %Apache::lonnet::serverhomeIDs;
     my %servers = &dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my %altids = &id_for_thisdom(%servers);
     my $itemcount = 1;      my $itemcount = 1;
     if ($position eq 'top') {      if ($position eq 'top') {
         if (keys(%uniques) > 1) {          if (keys(%serverhomes) > 1) {
             my %spareid = &current_offloads_to($dom,$settings,\%servers);              my %spareid = &current_offloads_to($dom,$settings,\%servers);
             $datatable .= &spares_row(\%servers,\%spareid,\%uniques,$rowtotal);              $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$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 this server.');                            &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.');
         }          }
     } else {      } else {
         if (keys(%by_location) == 0) {          if (keys(%by_location) == 0) {
             $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 this institution.');                            &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.');
         } else {          } else {
             my %lt = &usersession_titles();              my %lt = &usersession_titles();
             my $numinrow = 5;              my $numinrow = 5;
Line 2485  sub build_location_hashes { Line 2626  sub build_location_hashes {
 sub current_offloads_to {  sub current_offloads_to {
     my ($dom,$settings,$servers) = @_;      my ($dom,$settings,$servers) = @_;
     my (%spareid,%otherdomconfigs);      my (%spareid,%otherdomconfigs);
     if ((ref($settings) eq 'HASH') && (ref($servers) eq 'HASH')) {      if (ref($servers) eq 'HASH') {
         foreach my $lonhost (sort(keys(%{$servers}))) {          foreach my $lonhost (sort(keys(%{$servers}))) {
             my $gotspares;              my $gotspares;
             if (ref($settings->{'spares'}) eq 'HASH') {              if (ref($settings) eq 'HASH') {
                 if (ref($settings->{'spares'}{$lonhost}) eq 'HASH') {                  if (ref($settings->{'spares'}) eq 'HASH') {
                     $spareid{$lonhost}{'primary'} = $settings->{'spares'}{$lonhost}{'primary'};                      if (ref($settings->{'spares'}{$lonhost}) eq 'HASH') {
                     $spareid{$lonhost}{'default'} = $settings->{'spares'}{$lonhost}{'default'};                          $spareid{$lonhost}{'primary'} = $settings->{'spares'}{$lonhost}{'primary'};
                     $gotspares = 1;                          $spareid{$lonhost}{'default'} = $settings->{'spares'}{$lonhost}{'default'};
                           $gotspares = 1;
                       }
                 }                  }
             }              }
             unless ($gotspares) {              unless ($gotspares) {
Line 2538  sub current_offloads_to { Line 2681  sub current_offloads_to {
                         $spareid{$lonhost}{'primary'} = $Apache::lonnet::spareid{'primary'};                          $spareid{$lonhost}{'primary'} = $Apache::lonnet::spareid{'primary'};
                         $spareid{$lonhost}{'default'} = $Apache::lonnet::spareid{'default'};                          $spareid{$lonhost}{'default'} = $Apache::lonnet::spareid{'default'};
                     } else {                      } else {
                         my %requested;                          my %what = (
                         $requested{'spareid'} = 'HASH';                               spareid => 1,
                         my %returnhash = &Apache::lonnet::get_remote_globals($lonhost,\%requested);                          );
                         my $spareshash = $returnhash{'spareid'};                          my ($result,$returnhash) = 
                         if (ref($spareshash) eq 'HASH') {                              &Apache::lonnet::get_remote_globals($lonhost,\%what);
                             $spareid{$lonhost}{'primary'} = $spareshash->{'primary'};                          if ($result eq 'ok') { 
                             $spareid{$lonhost}{'default'} = $spareshash->{'default'};                              if (ref($returnhash) eq 'HASH') {
                                   if (ref($returnhash->{'spareid'}) eq 'HASH') {
                                       $spareid{$lonhost}{'primary'} = $returnhash->{'spareid'}->{'primary'};
                                       $spareid{$lonhost}{'default'} = $returnhash->{'spareid'}->{'default'};
                                   }
                               }
                         }                          }
                     }                      }
                 }                  }
Line 2555  sub current_offloads_to { Line 2703  sub current_offloads_to {
 }  }
   
 sub spares_row {  sub spares_row {
     my ($servers,$spareid,$uniques,$rowtotal) = @_;      my ($dom,$servers,$spareid,$serverhomes,$altids,$rowtotal) = @_;
     my $css_class;      my $css_class;
     my $numinrow = 4;      my $numinrow = 4;
     my $itemcount = 1;      my $itemcount = 1;
     my $datatable;      my $datatable;
     if ((ref($servers) eq 'HASH') && (ref($spareid) eq 'HASH')) {      my %typetitles = &sparestype_titles();
       if ((ref($servers) eq 'HASH') && (ref($spareid) eq 'HASH') && (ref($altids) eq 'HASH')) {
         foreach my $server (sort(keys(%{$servers}))) {          foreach my $server (sort(keys(%{$servers}))) {
               my $serverhome = &Apache::lonnet::get_server_homeID($servers->{$server});
               my ($othercontrol,$serverdom);
               if ($serverhome ne $server) {
                   $serverdom = &Apache::lonnet::host_domain($serverhome);
                   $othercontrol = &mt('Session offloading controlled by domain: [_1]','<b>'.$serverdom.'</b>');
               } else {
                   $serverdom = &Apache::lonnet::host_domain($server);
                   if ($serverdom ne $dom) {
                       $othercontrol = &mt('Session offloading controlled by domain: [_1]','<b>'.$serverdom.'</b>');
                   }
               }
               next unless (ref($spareid->{$server}) eq 'HASH');
             $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>';                              <span class="LC_nobreak"><b>'.$server.'</b> when busy, offloads to:</span></td>'."\n";
             my (%current,%canselect);              my (%current,%canselect);
             if (ref($spareid->{$server}) eq 'HASH') {              my @choices = 
                 foreach my $type ('primary','default') {                  &possible_newspares($server,$spareid->{$server},$serverhomes,$altids);
               foreach my $type ('primary','default') {
                   if (ref($spareid->{$server}) eq 'HASH') {
                     if (ref($spareid->{$server}{$type}) eq 'ARRAY') {                      if (ref($spareid->{$server}{$type}) eq 'ARRAY') {
                         my @spares = @{$spareid->{$server}{$type}};                          my @spares = @{$spareid->{$server}{$type}};
                         if (@spares > 0) {                          if (@spares > 0) {
                             $current{$type} .= '<table>';                              if ($othercontrol) {
                             for (my $i=0;  $i<@spares; $i++) {                                  $current{$type} = join(', ',@spares);
                                 my $rem = $i%($numinrow);                              } else {
                                 if ($rem == 0) {                                  $current{$type} .= '<table>';
                                     if ($i > 0) {                                  my $numspares = scalar(@spares);
                                         $current{$type} .= '</tr>';                                  for (my $i=0;  $i<@spares; $i++) {
                                       my $rem = $i%($numinrow);
                                       if ($rem == 0) {
                                           if ($i > 0) {
                                               $current{$type} .= '</tr>';
                                           }
                                           $current{$type} .= '<tr>';
                                     }                                      }
                                     $current{$type} .= '<tr>';                                      $current{$type} .= '<td><label><input type="checkbox" name="spare_'.$type.'_'.$server.'" id="spare_'.$type.'_'.$server.'_'.$i.'" checked="checked" value="'.$spareid->{$server}{$type}[$i].'" onclick="updateNewSpares(this.form,'."'$server'".');" />&nbsp;'.
                                                          $spareid->{$server}{$type}[$i].
                                                          '</label></td>'."\n";
                                   }
                                   my $rem = @spares%($numinrow);
                                   my $colsleft = $numinrow - $rem;
                                   if ($colsleft > 1 ) {
                                       $current{$type} .= '<td colspan="'.$colsleft.
                                                          '" class="LC_left_item">'.
                                                          '&nbsp;</td>';
                                   } elsif ($colsleft == 1) {
                                       $current{$type} .= '<td class="LC_left_item">&nbsp;</td>'."\n";
                                 }                                  }
                                 $current{$type} .= '<td><label><input type="checkbox" name="spare_'.$type.'_'.$server.'" checked="checked" value="'.$spareid->{$server}{$type}[$i].'" />&nbsp;'.                                  $current{$type} .= '</tr></table>';
                                                    $spareid->{$server}{$type}[$i].  
                                                    '</label></td>';  
                             }                              }
                             $current{$type} .= '</tr></table>';  
                         }                          }
                     }                      }
                     if ($current{$type} eq '') {                      if ($current{$type} eq '') {
                         $current{$type} = &mt('None specified');                          $current{$type} = &mt('None specified');
                     }                      }
                     $canselect{$type} =                      if ($othercontrol) {
                         &newspare_select($server,$type,$spareid->{$server}{$type},$uniques);                          if ($type eq 'primary') {
                               $canselect{$type} = $othercontrol;
                           }
                       } else {
                           $canselect{$type} = 
                               &mt('Add new [_1]'.$type.'[_2]:','<i>','</i>').'&nbsp;'.
                               '<select name="newspare_'.$type.'_'.$server.'" '.
                               'id="newspare_'.$type.'_'.$server.'" onchange="checkNewSpares('."'$server','$type'".');">'."\n".
                               '<option value="" selected ="selected">'.&mt('Select').'</option>'."\n";
                           if (@choices > 0) {
                               foreach my $lonhost (@choices) {
                                   $canselect{$type} .= '<option value="'.$lonhost.'">'.$lonhost.'</option>'."\n";
                               }
                           }
                           $canselect{$type} .= '</select>'."\n";
                       }
                   } else {
                       $current{$type} = &mt('Could not be determined');
                       if ($type eq 'primary') {
                           $canselect{$type} =  $othercontrol;
                       }
                 }                  }
                   if ($type eq 'default') {
                       $datatable .= '<tr'.$css_class.'>';
                   }
                   $datatable .= '<td><i>'.$typetitles{$type}.'</i></td>'."\n".
                                 '<td>'.$current{$type}.'</td>'."\n".
                                 '<td>'.$canselect{$type}.'</td></tr>'."\n";
             }              }
             $datatable .= '<td><i>'.&mt('primary').'</i><td>'.$current{'primary'}.'</td>'.  
                           '<td>'.&mt('Add new [_1]primary[_2]:','<i>','</i>').'&nbsp;'.  
                           $canselect{'primary'}.'</td></tr>'.  
                           '<tr'.$css_class.'>'.  
                           '<td><i>'.&mt('default').'</i></td>'.  
                           '<td>'.$current{'default'}.'</td>'.  
                           '<td>'.&mt('Add new [_1]default[_2]:','<i>','</i>').'&nbsp;'.  
                           $canselect{'default'}.'</td></tr>';  
             $itemcount ++;              $itemcount ++;
         }          }
     }      }
Line 2610  sub spares_row { Line 2805  sub spares_row {
     return $datatable;      return $datatable;
 }  }
   
 sub newspare_select {  sub possible_newspares {
     my ($server,$type,$currspares,$uniques) = @_;      my ($server,$currspares,$serverhomes,$altids) = @_;
     my $output;      my $serverhostname = &Apache::lonnet::hostname($server);
     if (ref($uniques) eq 'HASH') {      my %excluded;
         if (keys(%{$uniques}) > 1) {      if ($serverhostname ne '') {
             $output = '<select name="newspare_'.$type.'_'.$server.'">'."\n".          %excluded = (
                       '<option value="" selected ="selected">'.&mt('Select').'</option>'."\n";                         $serverhostname => 1,
             foreach my $lonhost (sort(keys(%{$uniques}))) {                      );
                 next if ($lonhost eq $server);      }
                 if (ref($currspares) eq 'ARRAY') {      if (ref($currspares) eq 'HASH') {
                     if (@{$currspares} > 0) {          foreach my $type (keys(%{$currspares})) {
                         next if (grep(/^\Q$lonhost\E$/,@{$currspares}));              if (ref($currspares->{$type}) eq 'ARRAY') {
                   if (@{$currspares->{$type}} > 0) {
                       foreach my $curr (@{$currspares->{$type}}) {
                           my $hostname = &Apache::lonnet::hostname($curr);
                           $excluded{$hostname} = 1;
                       }
                   }
               }
           }
       }
       my @choices;
       if ((ref($serverhomes) eq 'HASH') && (ref($altids) eq 'HASH')) {
           if (keys(%{$serverhomes}) > 1) {
               foreach my $name (sort(keys(%{$serverhomes}))) {
                   unless ($excluded{$name}) {
                       if (exists($altids->{$serverhomes->{$name}})) {
                           push(@choices,$altids->{$serverhomes->{$name}});
                       } else {
                           push(@choices,$serverhomes->{$name});
                       }
                   }
               }
           }
       }
       return sort(@choices);
   }
   
   sub print_loadbalancing {
       my ($dom,$settings,$rowtotal) = @_;
       my $primary_id = &Apache::lonnet::domain($dom,'primary');
       my $intdom = &Apache::lonnet::internet_dom($primary_id);
       my $numinrow = 1;
       my $datatable;
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my ($currbalancer,$currtargets,$currrules);
       if (keys(%servers) > 1) {
           if (ref($settings) eq 'HASH') {
               $currbalancer = $settings->{'lonhost'};
               $currtargets = $settings->{'targets'};
               $currrules = $settings->{'rules'};
           } else {
               ($currbalancer,$currtargets) = 
                   &Apache::lonnet::get_lonbalancer_config(\%servers);
           }
       } else {
           return;
       }
       my ($othertitle,$usertypes,$types) =
           &Apache::loncommon::sorted_inst_types($dom);
       my $rownum = 6;
       if (ref($types) eq 'ARRAY') {
           $rownum += scalar(@{$types});
       }
       my $css_class = ' class="LC_odd_row"';
       my $targets_div_style = 'display: none';
       my $disabled_div_style = 'display: block';
       my $homedom_div_style = 'display: none';
       $datatable = '<tr'.$css_class.'>'.
                    '<td rowspan="'.$rownum.'" valign="top">'.
                    '<p><select name="loadbalancing_lonhost" onchange="toggleTargets();">'."\n".
                    '<option value=""';
       if (($currbalancer eq '') || (!grep(/^\Q$currbalancer\E$/,keys(%servers)))) {
           $datatable .= ' selected="selected"';
       } else {
           $targets_div_style = 'display: block';
           $disabled_div_style = 'display: none';
           if ($dom eq &Apache::lonnet::host_domain($currbalancer)) {
               $homedom_div_style = 'display: block'; 
           }
       }
       $datatable .= '>'.&mt('None').'</option>'."\n";
       foreach my $lonhost (sort(keys(%servers))) {
           my $selected;
           if ($lonhost eq $currbalancer) {
               $selected .= ' selected="selected"';
           }
           $datatable .= '<option value="'.$lonhost.'"'.$selected.'>'.$lonhost.'</option>'."\n";
       }
       $datatable .= '</select></p></td><td rowspan="'.$rownum.'" valign="top">'.
                     '<div id="loadbalancing_disabled" style="'.$disabled_div_style.'">'.&mt('No dedicated Load Balancer').'</div>'."\n".
                     '<div id="loadbalancing_targets" style="'.$targets_div_style.'">'.&mt('Offloads to:').'<br />';
       my ($numspares,@spares) = &count_servers($currbalancer,%servers);
       my @sparestypes = ('primary','default');
       my %typetitles = &sparestype_titles();
       foreach my $sparetype (@sparestypes) {
           my $targettable;
           for (my $i=0; $i<$numspares; $i++) {
               my $checked;
               if (ref($currtargets) eq 'HASH') {
                   if (ref($currtargets->{$sparetype}) eq 'ARRAY') {
                       if (grep(/^\Q$spares[$i]\E$/,@{$currtargets->{$sparetype}})) {
                           $checked = ' checked="checked"';
                     }                      }
                 }                  }
                 $output .= '<option value="'.$lonhost.'">'.$lonhost.'</option>'."\n";  
             }              }
             $output .= '<select>';              my $chkboxval;
               if (($currbalancer ne '') && (grep((/^\Q$currbalancer\E$/,keys(%servers))))) {
                   $chkboxval = $spares[$i];
               }
               $targettable .= '<td><label><input type="checkbox" name="loadbalancing_target_'.$sparetype.'"'.
                         $checked.' value="'.$chkboxval.'" id="loadbalancing_target_'.$sparetype.'_'.$i.'" onclick="checkOffloads('."this,'$sparetype'".');" /><span id="loadbalancing_targettxt_'.$sparetype.'_'.$i.'">&nbsp;'.$chkboxval.
                         '</span></label></td>';
               my $rem = $i%($numinrow);
               if ($rem == 0) {
                   if ($i > 0) {
                       $targettable .= '</tr>';
                   }
                   $targettable .= '<tr>';
               }
           }
           if ($targettable ne '') {
               my $rem = $numspares%($numinrow);
               my $colsleft = $numinrow - $rem;
               if ($colsleft > 1 ) {
                   $targettable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                                   '&nbsp;</td>';
               } elsif ($colsleft == 1) {
                   $targettable .= '<td class="LC_left_item">&nbsp;</td>';
               }
               $datatable .=  '<i>'.$typetitles{$sparetype}.'</i><br />'.
                              '<table><tr>'.$targettable.'</table><br />';
           }
       }
       $datatable .= '</div></td></tr>'.
                     &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 {
       my ($dom,$intdom,$currrules,$othertitle,$usertypes,$types,$servers,
           $currbalancer,$targets_div_style,$homedom_div_style,$css_class) = @_;
       my $output;
       my ($alltypes,$othertypes,$titles) = 
           &loadbalancing_titles($dom,$intdom,$usertypes,$types);
       if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH'))  {
           foreach my $type (@{$alltypes}) {
               my $current;
               if (ref($currrules) eq 'HASH') {
                   $current = $currrules->{$type};
               }
               if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {
                   if ($dom ne &Apache::lonnet::host_domain($currbalancer)) {
                       $current = '';
                   }
               }
               $output .= &loadbalance_rule_row($type,$titles->{$type},$current,
                                                $servers,$currbalancer,$dom,
                                                $targets_div_style,$homedom_div_style,$css_class);
         }          }
     }      }
     return $output;      return $output;
 }  }
   
   sub loadbalancing_titles {
       my ($dom,$intdom,$usertypes,$types) = @_;
       my %othertypes = (
              '_LC_adv'         => &mt('Advanced users from [_1]',$dom),
              '_LC_author'      => &mt('Users from [_1] with author role',$dom),
              '_LC_internetdom' => &mt('Users not from [_1], but from [_2]',$dom,$intdom),
              '_LC_external'    => &mt('Users not from [_1]',$intdom),
                        );
       my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external');
       if (ref($types) eq 'ARRAY') {
           unshift(@alltypes,@{$types},'default');
       }
       my %titles;
       foreach my $type (@alltypes) {
           if ($type =~ /^_LC_/) {
               $titles{$type} = $othertypes{$type};
           } elsif ($type eq 'default') {
               $titles{$type} = &mt('All users from [_1]',$dom);
               if (ref($types) eq 'ARRAY') {
                   if (@{$types} > 0) {
                       $titles{$type} = &mt('Other users from [_1]',$dom);
                   }
               }
           } elsif (ref($usertypes) eq 'HASH') {
               $titles{$type} = $usertypes->{$type};
           }
       }
       return (\@alltypes,\%othertypes,\%titles);
   }
   
   sub loadbalance_rule_row {
       my ($type,$title,$current,$servers,$currbalancer,$dom,$targets_div_style,
           $homedom_div_style,$css_class) = @_;
       my @rulenames = ('default','homeserver');
       my %ruletitles = &offloadtype_text();
       if ($type eq '_LC_external') {
           push(@rulenames,'externalbalancer');
       } else {
           push(@rulenames,'specific');
       }
       push(@rulenames,'none');
       my $style = $targets_div_style;
       if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {
           $style = $homedom_div_style;
       }
       my $output = 
           '<tr'.$css_class.'><td valign="top"><div id="balanceruletitle_'.$type.'" style="'.$style.'">'.$title.'</div></td>'."\n".
           '<td><div id="balancerule_'.$type.'" style="'.$style.'">'."\n";
       for (my $i=0; $i<@rulenames; $i++) {
           my $rule = $rulenames[$i];
           my ($checked,$extra);
           if ($rulenames[$i] eq 'default') {
               $rule = '';
           }
           if ($rulenames[$i] eq 'specific') {
               if (ref($servers) eq 'HASH') {
                   my $default;
                   if (($current ne '') && (exists($servers->{$current}))) {
                       $checked = ' checked="checked"';
                   }
                   unless ($checked) {
                       $default = ' selected="selected"';
                   }
                   $extra = ':&nbsp;<select name="loadbalancing_singleserver_'.$type.
                            '" id="loadbalancing_singleserver_'.$type.
                            '" onchange="singleServerToggle('."'$type'".')">'."\n".
                            '<option value=""'.$default.'></option>'."\n";
                   foreach my $lonhost (sort(keys(%{$servers}))) {
                       next if ($lonhost eq $currbalancer);
                       my $selected;
                       if ($lonhost eq $current) {
                           $selected = ' selected="selected"';
                       }
                       $extra .= '<option value="'.$lonhost.'"'.$selected.'>'.$lonhost.'</option>';
                   }
                   $extra .= '</select>';
               }
           } elsif ($rule eq $current) {
               $checked = ' checked="checked"';
           }
           $output .= '<span class="LC_nobreak"><label>'.
                      '<input type="radio" name="loadbalancing_rules_'.$type.
                      '" id="loadbalancing_rules_'.$type.'_'.$i.'" value="'.
                      $rule.'" onclick="balanceruleChange('."this.form,'$type'".
                      ')"'.$checked.' />&nbsp;'.$ruletitles{$rulenames[$i]}.
                      '</label>'.$extra.'</span><br />'."\n";
       }
       $output .= '</div></td></tr>'."\n";
       return $output;
   }
   
   sub offloadtype_text {
       my %ruletitles = &Apache::lonlocal::texthash (
              'default'          => 'Offloads to default destinations',
              'homeserver'       => "Offloads to user's home server",
              'externalbalancer' => "Offloads to Load Balancer in user's domain",
              'specific'         => 'Offloads to specific server',
              'none'             => 'No offload',
       );
       return %ruletitles;
   }
   
   sub sparestype_titles {
       my %typestitles = &Apache::lonlocal::texthash (
                             'primary' => 'primary',
                             'default' => 'default',
                         );
       return %typestitles;
   }
   
 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',
Line 2651  sub contact_titles { Line 3101  sub contact_titles {
   
 sub tool_titles {  sub tool_titles {
     my %titles = &Apache::lonlocal::texthash (      my %titles = &Apache::lonlocal::texthash (
                      aboutme    => 'Personal Information Page',                       aboutme    => 'Personal web page',
                      blog       => 'Blog',                       blog       => 'Blog',
                        webdav     => 'WebDAV',
                      portfolio  => 'Portfolio',                       portfolio  => 'Portfolio',
                      official   => 'Official courses (with institutional codes)',                       official   => 'Official courses (with institutional codes)',
                      unofficial => 'Unofficial courses',                       unofficial => 'Unofficial courses',
Line 2675  sub courserequest_titles { Line 3126  sub courserequest_titles {
     return %titles;      return %titles;
 }  }
   
   sub authorrequest_titles {
       my %titles = &Apache::lonlocal::texthash (
                                      norequest  => 'Not allowed',
                                      approval   => 'Approval by Dom. Coord.',
                                      automatic  => 'Automatic approval',
                    );
       return %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).',
Line 2804  sub print_usercreation { Line 3264  sub print_usercreation {
         }          }
         my ($othertitle,$usertypes,$types) =          my ($othertitle,$usertypes,$types) =
             &Apache::loncommon::sorted_inst_types($dom);              &Apache::loncommon::sorted_inst_types($dom);
           my $createsettings;
           if (ref($settings) eq 'HASH') {
               $createsettings = $settings->{cancreate};
           }
         if (ref($usertypes) eq 'HASH') {          if (ref($usertypes) eq 'HASH') {
             if (keys(%{$usertypes}) > 0) {              if (keys(%{$usertypes}) > 0) {
                 my $createsettings;  
                 if (ref($settings) eq 'HASH') {  
                     $createsettings = $settings->{cancreate};  
                 }  
                 $datatable .= &insttypes_row($createsettings,$types,$usertypes,                  $datatable .= &insttypes_row($createsettings,$types,$usertypes,
                                              $dom,$numinrow,$othertitle,                                               $dom,$numinrow,$othertitle,
                                              'statustocreate');                                               'statustocreate');
                 $$rowtotal ++;                  $$rowtotal ++;
             }              }
         }          }
           $datatable .= &captcha_choice('cancreate',$createsettings);
     } 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 2867  sub print_usercreation { Line 3328  sub print_usercreation {
     return $datatable;      return $datatable;
 }  }
   
   sub captcha_choice {
       my ($context,$settings) = @_;
       my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext);
       my %lt = &captcha_phrases();
       $keyentry = 'hidden';
       if ($context eq 'cancreate') {
           $rowname = &mt('CAPTCHA validation (e-mail as username)');
       } elsif ($context eq 'help') {
           $rowname =  &mt('CAPTCHA validation');
       }
       if (ref($settings) eq 'HASH') {
           if ($settings->{'captcha'}) {
               $checked{$settings->{'captcha'}} = ' checked="checked"';
           } else {
               $checked{'original'} = ' checked="checked"';
           }
           if ($settings->{'captcha'} eq 'recaptcha') {
               $pubtext = $lt{'pub'};
               $privtext = $lt{'priv'};
               $keyentry = 'text';
           }
           if (ref($settings->{'recaptchakeys'}) eq 'HASH') {
               $currpub = $settings->{'recaptchakeys'}{'public'};
               $currpriv = $settings->{'recaptchakeys'}{'private'};
           }
       } else {
           $checked{'original'} = ' checked="checked"';
       }
       my $output = '<tr class="LC_odd_row">'.
                    '<td class="LC_left_item">'.$rowname.'</td><td class="LC_right_item" colspan="2">'."\n".
                    '<table><tr><td>'."\n";
       foreach my $option ('original','recaptcha','notused') {
           $output .= '<span class="LC_nobreak"><label><input type="radio" name="'.$context.'_captcha" value="'.
                      $option.'" '.$checked{$option}.' onchange="javascript:updateCaptcha('."this,'$context'".');" />'.
                      $lt{$option}.'</label></span>';
           unless ($option eq 'notused') {
               $output .= ('&nbsp;'x2)."\n";
           }
       }
   #
   # Note: If reCAPTCHA is to be used for LON-CAPA servers in a domain, a domain coordinator should visit:
   # https://www.google.com/recaptcha and generate a Public and Private key. For domains with multiple
   # servers a single key pair will be used for all servers, so the internet domain (e.g., yourcollege.edu) 
   # specified for use with the key should be broad enough to accommodate all servers in the LON-CAPA domain.
   #  
       $output .= '</td></tr>'."\n".
                  '<tr><td>'."\n".
                  '<span class="LC_nobreak"><span id="'.$context.'_recaptchapubtxt">'.$pubtext.'</span>&nbsp;'."\n".
                  '<input type="'.$keyentry.'" id="'.$context.'_recaptchapub" name="'.$context.'_recaptchapub" value="'.
                  $currpub.'" size="40" /></span><br />'."\n".
                  '<span class="LC_nobreak"><span id="'.$context.'_recaptchaprivtxt">'.$privtext.'</span>&nbsp;'."\n".
                  '<input type="'.$keyentry.'" id="'.$context.'_recaptchapriv" name="'.$context.'_recaptchapriv" value="'.
                  $currpriv.'" size="40" /></span></td></tr></table>'."\n".
                  '</td></tr>';
       return $output;
   }
   
 sub user_formats_row {  sub user_formats_row {
     my ($type,$settings,$rules,$ruleorder,$numinrow,$rowcount) = @_;      my ($type,$settings,$rules,$ruleorder,$numinrow,$rowcount) = @_;
     my $output;      my $output;
Line 3517  sub print_serverstatuses { Line 4035  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',              'clusterstatus','metadata_keywords','metadata_harvest',
             'takeoffline','takeonline','showenv','toggledebug');              'takeoffline','takeonline','showenv','toggledebug','ping','domconf');
 }  }
   
 sub coursecategories_javascript {  sub coursecategories_javascript {
Line 3831  sub insttypes_row { Line 4349  sub insttypes_row {
     if ($context eq 'cansearch') {      if ($context eq 'cansearch') {
         $showdom = ' ('.$dom.')';          $showdom = ' ('.$dom.')';
     }      }
       my $class = 'LC_left_item';
       if ($context eq 'statustocreate') {
           $class = 'LC_right_item';
       }
     my $output =  '<tr class="LC_odd_row">'.      my $output =  '<tr class="LC_odd_row">'.
                   '<td>'.$lt{$context}.$showdom.                    '<td>'.$lt{$context}.$showdom.
                   '</td><td class="LC_left_item" colspan="2"><table>';                    '</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 3990  sub modify_login { Line 4512  sub modify_login {
                                          \%loginhash);                                           \%loginhash);
     }      }
   
     my %servers = &dom_servers($dom);      my %servers = &Apache::lonnet::internet_dom_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 4585  sub publishlogo { Line 5107  sub publishlogo {
 # See if there is anything left  # See if there is anything left
     unless ($fname) { return ('error: no uploaded file'); }      unless ($fname) { return ('error: no uploaded file'); }
     $fname="$subdir/$fname";      $fname="$subdir/$fname";
     my $filepath='/home/'.$confname.'/public_html';      my $docroot=$r->dir_config('lonDocRoot'); 
       my $filepath="$docroot/priv";
       my $relpath = "$dom/$confname";
     my ($fnamepath,$file,$fetchthumb);      my ($fnamepath,$file,$fetchthumb);
     $file=$fname;      $file=$fname;
     if ($fname=~m|/|) {      if ($fname=~m|/|) {
         ($fnamepath,$file) = ($fname =~ m|^(.*)/([^/]+)$|);          ($fnamepath,$file) = ($fname =~ m|^(.*)/([^/]+)$|);
     }      }
     my @parts=split(/\//,$filepath.'/'.$fnamepath);      my @parts=split(/\//,"$filepath/$relpath/$fnamepath");
     my $count;      my $count;
     for ($count=4;$count<=$#parts;$count++) {      for ($count=5;$count<=$#parts;$count++) {
         $filepath.="/$parts[$count]";          $filepath.="/$parts[$count]";
         if ((-e $filepath)!=1) {          if ((-e $filepath)!=1) {
             mkdir($filepath,02770);              mkdir($filepath,02770);
Line 4640  $env{'user.name'}.':'.$env{'user.domain' Line 5164  $env{'user.name'}.':'.$env{'user.domain'
         close(FH);          close(FH);
         chmod(0660, $source); # Permissions to rw-rw---.          chmod(0660, $source); # Permissions to rw-rw---.
   
         my $docroot=$r->dir_config('lonDocRoot');  
         my $targetdir=$docroot.'/res/'.$dom.'/'.$confname .'/'.$fnamepath;          my $targetdir=$docroot.'/res/'.$dom.'/'.$confname .'/'.$fnamepath;
         my $copyfile=$targetdir.'/'.$file;          my $copyfile=$targetdir.'/'.$file;
   
Line 4663  $env{'user.name'}.':'.$env{'user.domain' Line 5186  $env{'user.name'}.':'.$env{'user.domain'
             if (copy($source,$copyfile)) {              if (copy($source,$copyfile)) {
                 print $logfile "\nCopied original source to ".$copyfile."\n";                  print $logfile "\nCopied original source to ".$copyfile."\n";
                 $output = 'ok';                  $output = 'ok';
                 &write_metadata($dom,$confname,$formname,$targetdir,$file,$logfile);  
                 $logourl = '/res/'.$dom.'/'.$confname.'/'.$fname;                  $logourl = '/res/'.$dom.'/'.$confname.'/'.$fname;
                   push(@{$modified_urls},[$copyfile,$source]);
                   my $metaoutput = 
                       &write_metadata($dom,$confname,$formname,$targetdir,$file,$logfile);
                   unless ($registered_cleanup) {
                       my $handlers = $r->get_handlers('PerlCleanupHandler');
                       $r->set_handlers('PerlCleanupHandler' => [\&notifysubscribed,@{$handlers}]);
                       $registered_cleanup=1;
                   }
             } else {              } else {
                 print $logfile "\nUnable to write ".$copyfile.':'.$!."\n";                  print $logfile "\nUnable to write ".$copyfile.':'.$!."\n";
                 $output = &mt('Failed to copy file to RES space').", $!";                  $output = &mt('Failed to copy file to RES space').", $!";
Line 4682  $env{'user.name'}.':'.$env{'user.domain' Line 5212  $env{'user.name'}.':'.$env{'user.domain'
                             my $copyfile=$targetdir.'/tn-'.$file;                              my $copyfile=$targetdir.'/tn-'.$file;
                             if (copy($outfile,$copyfile)) {                              if (copy($outfile,$copyfile)) {
                                 print $logfile "\nCopied source to ".$copyfile."\n";                                  print $logfile "\nCopied source to ".$copyfile."\n";
                                 &write_metadata($dom,$confname,$formname,                                  my $thumb_metaoutput = 
                                                 $targetdir,'tn-'.$file,$logfile);                                      &write_metadata($dom,$confname,$formname,
                                                       $targetdir,'tn-'.$file,$logfile);
                                   push(@{$modified_urls},[$copyfile,$outfile]);
                                   unless ($registered_cleanup) {
                                       my $handlers = $r->get_handlers('PerlCleanupHandler');
                                       $r->set_handlers('PerlCleanupHandler' => [\&notifysubscribed,@{$handlers}]);
                                       $registered_cleanup=1;
                                   }
                             } else {                              } else {
                                 print $logfile "\nUnable to write ".$copyfile.                                  print $logfile "\nUnable to write ".$copyfile.
                                                ':'.$!."\n";                                                 ':'.$!."\n";
Line 4748  sub write_metadata { Line 5285  sub write_metadata {
     {      {
         print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file;          print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file;
         my $mfh;          my $mfh;
         unless (open($mfh,'>'.$targetdir.'/'.$file.'.meta')) {          if (open($mfh,'>'.$targetdir.'/'.$file.'.meta')) {
               foreach (sort keys %metadatafields) {
                   unless ($_=~/\./) {
                       my $unikey=$_;
                       $unikey=~/^([A-Za-z]+)/;
                       my $tag=$1;
                       $tag=~tr/A-Z/a-z/;
                       print $mfh "\n\<$tag";
                       foreach (split(/\,/,$metadatakeys{$unikey})) {
                           my $value=$metadatafields{$unikey.'.'.$_};
                           $value=~s/\"/\'\'/g;
                           print $mfh ' '.$_.'="'.$value.'"';
                       }
                       print $mfh '>'.
                           &HTML::Entities::encode($metadatafields{$unikey},'<>&"')
                               .'</'.$tag.'>';
                   }
               }
               $output = 'ok';
               print $logfile "\nWrote metadata";
               close($mfh);
           } else {
               print $logfile "\nFailed to open metadata file";
             $output = &mt('Could not write metadata');              $output = &mt('Could not write metadata');
         }          }
         foreach (sort keys %metadatafields) {  
             unless ($_=~/\./) {  
                 my $unikey=$_;  
                 $unikey=~/^([A-Za-z]+)/;  
                 my $tag=$1;  
                 $tag=~tr/A-Z/a-z/;  
                 print $mfh "\n\<$tag";  
                 foreach (split(/\,/,$metadatakeys{$unikey})) {  
                     my $value=$metadatafields{$unikey.'.'.$_};  
                     $value=~s/\"/\'\'/g;  
                     print $mfh ' '.$_.'="'.$value.'"';  
                 }  
                 print $mfh '>'.  
                     &HTML::Entities::encode($metadatafields{$unikey},'<>&"')  
                         .'</'.$tag.'>';  
             }  
         }  
         $output = 'ok';  
         print $logfile "\nWrote metadata";  
         close($mfh);  
     }      }
       return $output;
   }
   
   sub notifysubscribed {
       foreach my $targetsource (@{$modified_urls}){
           next unless (ref($targetsource) eq 'ARRAY');
           my ($target,$source)=@{$targetsource};
           if ($source ne '') {
               if (open(my $logfh,'>>'.$source.'.log')) {
                   print $logfh "\nCleanup phase: Notifications\n";
                   my @subscribed=&subscribed_hosts($target);
                   foreach my $subhost (@subscribed) {
                       print $logfh "\nNotifying host ".$subhost.':';
                       my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);
                       print $logfh $reply;
                   }
                   my @subscribedmeta=&subscribed_hosts("$target.meta");
                   foreach my $subhost (@subscribedmeta) {
                       print $logfh "\nNotifying host for metadata only ".$subhost.':';
                       my $reply=&Apache::lonnet::critical('update:'.$target.'.meta',
                                                           $subhost);
                       print $logfh $reply;
                   }
                   print $logfh "\n============ Done ============\n";
                   close($logfh);
               }
           }
       }
       return OK;
   }
   
   sub subscribed_hosts {
       my ($target) = @_;
       my @subscribed;
       if (open(my $fh,"<$target.subscription")) {
           while (my $subline=<$fh>) {
               if ($subline =~ /^($match_lonid):/) {
                   my $host = $1;
                   if ($host ne $Apache::lonnet::perlvar{'lonHostID'}) {
                       unless (grep(/^\Q$host\E$/,@subscribed)) {
                           push(@subscribed,$host);
                       }
                   }
               }
           }
       }
       return @subscribed;
 }  }
   
 sub check_switchserver {  sub check_switchserver {
Line 4795  sub modify_quotas { Line 5381  sub modify_quotas {
         %limithash,$toolregexp,%conditions,$resulttext,%changes);          %limithash,$toolregexp,%conditions,$resulttext,%changes);
     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') {
Line 4805  sub modify_quotas { Line 5391  sub modify_quotas {
         %titles = &courserequest_titles();          %titles = &courserequest_titles();
         $toolregexp = join('|',@usertools);          $toolregexp = join('|',@usertools);
         %conditions = &courserequest_conditions();          %conditions = &courserequest_conditions();
       } elsif ($context eq 'requestauthor') {
           @usertools = ('author');
           %titles = &authorrequest_titles();
     } else {      } else {
         @usertools = ('aboutme','blog','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);
Line 4822  sub modify_quotas { Line 5411  sub modify_quotas {
                     $confhash{$item}{$type} = $env{$key};                      $confhash{$item}{$type} = $env{$key};
                 }                  }
             }              }
           } elsif ($context eq 'requestauthor') {
               if ($key =~ /^\Qform.authorreq_\E(.+)$/) {
                   $confhash{$1} = $env{$key};
               }
         } else {          } else {
             if ($key =~ /^form\.quota_(.+)$/) {              if ($key =~ /^form\.quota_(.+)$/) {
                 $confhash{'defaultquota'}{$1} = $env{$key};                  $confhash{'defaultquota'}{$1} = $env{$key};
Line 4831  sub modify_quotas { Line 5424  sub modify_quotas {
             }              }
         }          }
     }      }
     if ($context eq 'requestcourses') {      if (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
         my @approvalnotify = &Apache::loncommon::get_env_multiple('form.reqapprovalnotify');          my @approvalnotify = &Apache::loncommon::get_env_multiple('form.reqapprovalnotify');
         @approvalnotify = sort(@approvalnotify);          @approvalnotify = sort(@approvalnotify);
         $confhash{'notify'}{'approval'} = join(',',@approvalnotify);          $confhash{'notify'}{'approval'} = join(',',@approvalnotify);
Line 4867  sub modify_quotas { Line 5460  sub modify_quotas {
                         $confhash{$item}{$type} .= $limithash{$item}{$type};                          $confhash{$item}{$type} .= $limithash{$item}{$type};
                     }                      }
                 }                  }
               } elsif ($context eq 'requestauthor') {
                   $unset = '0';
                   if ($type eq '_LC_adv') {
                       $unset = '';
                   }
             } else {              } else {
                 if (grep(/^\Q$type\E$/,@{$toolshash{$item}})) {                  if (grep(/^\Q$type\E$/,@{$toolshash{$item}})) {
                     $confhash{$item}{$type} = 1;                      $confhash{$item}{$type} = 1;
Line 4875  sub modify_quotas { Line 5473  sub modify_quotas {
                 }                  }
             }              }
             if (ref($domconfig{$action}) eq 'HASH') {              if (ref($domconfig{$action}) eq 'HASH') {
                 if (ref($domconfig{$action}{$item}) eq 'HASH') {                  if ($action eq 'requestauthor') {
                       if ($domconfig{$action}{$type} ne $confhash{$type}) {
                           $changes{$type} = 1;
                       }
                   } elsif (ref($domconfig{$action}{$item}) eq 'HASH') {
                     if ($domconfig{$action}{$item}{$type} ne $confhash{$item}{$type}) {                      if ($domconfig{$action}{$item}{$type} ne $confhash{$item}{$type}) {
                         $changes{$item}{$type} = 1;                          $changes{$item}{$type} = 1;
                     }                      }
Line 4895  sub modify_quotas { Line 5497  sub modify_quotas {
                     if ($confhash{$item}{$type} ne $unset) {                      if ($confhash{$item}{$type} ne $unset) {
                         $changes{$item}{$type} = 1;                          $changes{$item}{$type} = 1;
                     }                      }
                   } elsif ($context eq 'requestauthor') {
                       if ($confhash{$type} ne $unset) {
                           $changes{$type} = 1;
                       }
                 } else {                  } else {
                     if (!$confhash{$item}{$type}) {                      if (!$confhash{$item}{$type}) {
                         $changes{$item}{$type} = 1;                          $changes{$item}{$type} = 1;
Line 4903  sub modify_quotas { Line 5509  sub modify_quotas {
             }              }
         }          }
     }      }
     unless ($context eq 'requestcourses') {      unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
         if (ref($domconfig{'quotas'}) eq 'HASH') {          if (ref($domconfig{'quotas'}) eq 'HASH') {
             if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') {              if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') {
                 foreach my $key (keys(%{$domconfig{'quotas'}{'defaultquota'}})) {                  foreach my $key (keys(%{$domconfig{'quotas'}{'defaultquota'}})) {
Line 4946  sub modify_quotas { Line 5552  sub modify_quotas {
         }          }
     }      }
   
     foreach my $key (keys(%confhash)) {      if ($context eq 'requestauthor') {
         $domdefaults{$key} = $confhash{$key};          $domdefaults{'requestauthor'} = \%confhash;
       } else {
           foreach my $key (keys(%confhash)) {
               $domdefaults{$key} = $confhash{$key};
           }
     }      }
      
     my %quotahash = (      my %quotahash = (
                       $action => { %confhash }                        $action => { %confhash }
                     );                      );
Line 4961  sub modify_quotas { Line 5571  sub modify_quotas {
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);              &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
   
             $resulttext = &mt('Changes made:').'<ul>';              $resulttext = &mt('Changes made:').'<ul>';
             unless ($context eq 'requestcourses') {              unless (($context eq 'requestcourses') || 
                       ($context eq 'requestauthor')) {
                 if (ref($changes{'defaultquota'}) eq 'HASH') {                  if (ref($changes{'defaultquota'}) eq 'HASH') {
                     $resulttext .= '<li>'.&mt('Portfolio default quotas').'<ul>';                      $resulttext .= '<li>'.&mt('Portfolio default quotas').'<ul>';
                     foreach my $type (@{$types},'default') {                      foreach my $type (@{$types},'default') {
Line 4978  sub modify_quotas { Line 5589  sub modify_quotas {
             }              }
             my %newenv;              my %newenv;
             foreach my $item (@usertools) {              foreach my $item (@usertools) {
                 if (ref($changes{$item}) eq 'HASH') {                  my (%haschgs,%inconf);
                   if ($context eq 'requestauthor') {
                       %haschgs = %changes;
                       %inconf = %confhash; 
                   } else {
                       if (ref($changes{$item}) eq 'HASH') {
                           %haschgs = %{$changes{$item}};
                       }
                       if (ref($confhash{$item}) eq 'HASH') {
                           %inconf = %{$confhash{$item}};
                       }
                   }
                   if (keys(%haschgs) > 0) {
                     my $newacc =                       my $newacc = 
                         &Apache::lonnet::usertools_access($env{'user.name'},                          &Apache::lonnet::usertools_access($env{'user.name'},
                                                           $env{'user.domain'},                                                            $env{'user.domain'},
                                                           $item,'reload',$context);                                                            $item,'reload',$context);
                     if ($context eq 'requestcourses') {                      if (($context eq 'requestcourses') || 
                           ($context eq 'requestauthor')) {
                         if ($env{'environment.canrequest.'.$item} ne $newacc) {                          if ($env{'environment.canrequest.'.$item} ne $newacc) {
                             $newenv{'environment.canrequest.'.$item} = $newacc;                              $newenv{'environment.canrequest.'.$item} = $newacc;
                         }                          }
Line 4992  sub modify_quotas { Line 5616  sub modify_quotas {
                             $newenv{'environment.availabletools.'.$item} = $newacc;                              $newenv{'environment.availabletools.'.$item} = $newacc;
                         }                          }
                     }                      }
                     $resulttext .= '<li>'.$titles{$item}.'<ul>';                      unless ($context eq 'requestauthor') {
                           $resulttext .= '<li>'.$titles{$item}.'<ul>';
                       }
                     foreach my $type (@{$types},'default','_LC_adv') {                      foreach my $type (@{$types},'default','_LC_adv') {
                         if ($changes{$item}{$type}) {                          if ($haschgs{$type}) {
                             my $typetitle = $usertypes->{$type};                              my $typetitle = $usertypes->{$type};
                             if ($type eq 'default') {                              if ($type eq 'default') {
                                 $typetitle = $othertitle;                                  $typetitle = $othertitle;
                             } elsif ($type eq '_LC_adv') {                              } elsif ($type eq '_LC_adv') {
                                 $typetitle = 'LON-CAPA Advanced Users';                                   $typetitle = 'LON-CAPA Advanced Users'; 
                             }                              }
                             if ($confhash{$item}{$type}) {                              if ($inconf{$type}) {
                                 if ($context eq 'requestcourses') {                                  if ($context eq 'requestcourses') {
                                     my $cond;                                      my $cond;
                                     if ($confhash{$item}{$type} =~ /^autolimit=(\d*)$/) {                                      if ($inconf{$type} =~ /^autolimit=(\d*)$/) {
                                         if ($1 eq '') {                                          if ($1 eq '') {
                                             $cond = &mt('(Automatic processing of any request).');                                              $cond = &mt('(Automatic processing of any request).');
                                         } else {                                          } else {
                                             $cond = &mt('(Automatic processing of requests up to limit of [quant,_1,request] per user).',$1);                                              $cond = &mt('(Automatic processing of requests up to limit of [quant,_1,request] per user).',$1);
                                         }                                          }
                                     } else {                                       } else { 
                                         $cond = $conditions{$confhash{$item}{$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>';
                                 } else {                                  } else {
Line 5019  sub modify_quotas { Line 5645  sub modify_quotas {
                                 }                                  }
                             } else {                              } else {
                                 if ($type eq '_LC_adv') {                                  if ($type eq '_LC_adv') {
                                     if ($confhash{$item}{$type} eq '0') {                                      if ($inconf{$type} eq '0') {
                                         $resulttext .= '<li>'.&mt('Set to be unavailable to [_1]',$typetitle).'</li>';                                          $resulttext .= '<li>'.&mt('Set to be unavailable to [_1]',$typetitle).'</li>';
                                     } else {                                       } else { 
                                         $resulttext .= '<li>'.&mt('No override set for [_1]',$typetitle).'</li>';                                          $resulttext .= '<li>'.&mt('No override set for [_1]',$typetitle).'</li>';
Line 5030  sub modify_quotas { Line 5656  sub modify_quotas {
                             }                              }
                         }                          }
                     }                      }
                     $resulttext .= '</ul></li>';                      unless ($context eq 'requestauthor') {
                           $resulttext .= '</ul></li>';
                       }
                 }                  }
             }              }
             if ($action eq 'requestcourses') {              if (($action eq 'requestcourses') || ($action eq 'requestauthor')) {
                 if (ref($changes{'notify'}) eq 'HASH') {                  if (ref($changes{'notify'}) eq 'HASH') {
                     if ($changes{'notify'}{'approval'}) {                      if ($changes{'notify'}{'approval'}) {
                         if (ref($confhash{'notify'}) eq 'HASH') {                          if (ref($confhash{'notify'}) eq 'HASH') {
                             if ($confhash{'notify'}{'approval'}) {                              if ($confhash{'notify'}{'approval'}) {
                                 $resulttext .= '<li>'.&mt('Notification of requests requiring approval will be sent to: ').$confhash{'notify'}{'approval'}.'</li>';                                  $resulttext .= '<li>'.&mt('Notification of requests requiring approval will be sent to: ').$confhash{'notify'}{'approval'}.'</li>';
                             } else {                              } else {
                                 $resulttext .= '<li>'.&mt('No Domain Coordinators will receive notification of course requests requiring approval.').'</li>';                                  $resulttext .= '<li>'.&mt('No Domain Coordinators will receive notification of requests requiring approval.').'</li>';
                             }                              }
                         }                          }
                     }                      }
Line 5053  sub modify_quotas { Line 5681  sub modify_quotas {
         } else {          } else {
             if ($context eq 'requestcourses') {              if ($context eq 'requestcourses') {
                 $resulttext = &mt('No changes made to rights to request creation of courses.');                  $resulttext = &mt('No changes made to rights to request creation of courses.');
               } elsif ($context eq 'requestauthor') {
                   $resulttext = &mt('No changes made to rights to request author space.');
             } else {              } else {
                 $resulttext = &mt('No changes made to availability of personal information pages, blogs, portfolios or default quotas');                  $resulttext = &mt('No changes made to availability of personal information pages, blogs, portfolios or default quotas');
             }              }
Line 5747  sub modify_usercreation { Line 6377  sub modify_usercreation {
         }          }
         push(@contexts,'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 (($item eq 'selfcreate') || ($item eq 'statustocreate')) {
Line 5929  sub modify_usercreation { Line 6560  sub modify_usercreation {
                 my %lt = &usercreation_types();                  my %lt = &usercreation_types();
                 foreach my $type (@{$changes{'cancreate'}}) {                  foreach my $type (@{$changes{'cancreate'}}) {
                     my $chgtext;                      my $chgtext;
                     unless ($type eq 'statustocreate') {                      unless (($type eq 'statustocreate') || ($type eq 'captcha') || ($type eq 'recaptchakeys')) {
                         $chgtext = $lt{$type}.', ';                          $chgtext = $lt{$type}.', ';
                     }                      }
                     if ($type eq 'selfcreate') {                      if ($type eq 'selfcreate') {
Line 5988  sub modify_usercreation { Line 6619  sub modify_usercreation {
                                 }                                  }
                             }                              }
                         }                          }
                       } elsif ($type eq 'captcha') {
                           if ($cancreate{$type} eq 'notused') {
                               $chgtext .= &mt('No CAPTCHA validation in use for self-creation screen.');
                           } else {
                               my %captchas = &captcha_phrases();
                               if ($captchas{$cancreate{$type}}) {
                                   $chgtext .= &mt("Validation for self-creation screen set to $captchas{$cancreate{$type}}.");
                               } else {
                                   $chgtext .= &mt('Validation for self-creation screen set to unknown type.'); 
                               }
                           }
                       } elsif ($type eq 'recaptchakeys') {
                           my ($privkey,$pubkey);
                           if (ref($cancreate{$type}) eq 'HASH') {
                               $pubkey = $cancreate{$type}{'public'};
                               $privkey = $cancreate{$type}{'private'};
                           }
                           $chgtext .= &mt('ReCAPTCHA keys changes').'<ul>';
                           if (!$pubkey) {
                               $chgtext .= '<li>'.&mt('Public key deleted').'</li>';
                           } else {
                               $chgtext .= '<li>'.&mt('Public key set to [_1]',$pubkey).'</li>';
                           }
                           if (!$privkey) {
                               $chgtext .= '<li>'.&mt('Private key deleted').'</li>';
                           } else {
                               $chgtext .= '<li>'.&mt('Private key set to [_1]',$pubkey).'</li>';
                           }
                           $chgtext .= '</ul>';
                     } else {                      } else {
                         if ($cancreate{$type} eq 'none') {                          if ($cancreate{$type} eq 'none') {
                             $chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.');                              $chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.');
Line 6087  sub modify_usercreation { Line 6747  sub modify_usercreation {
     return $resulttext;      return $resulttext;
 }  }
   
   sub process_captcha {
       my ($container,$changes,$newsettings,$current) = @_;
       return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH') || (ref($current) eq 'HASH'));
       $newsettings->{'captcha'} = $env{'form.'.$container.'_captcha'};
       unless ($newsettings->{'captcha'} eq 'recaptcha' || $newsettings->{'captcha'} eq 'notused') {
           $newsettings->{'captcha'} = 'original';
       }
       if ($current->{'captcha'} ne $newsettings->{'captcha'}) {
           if (ref($changes->{'cancreate'}) eq 'ARRAY') {
               push(@{$changes->{'cancreate'}},'captcha');
           } elsif (!defined($changes->{'cancreate'})) {
               $changes->{'cancreate'} = ['captcha'];
           }
       }
       my ($newpub,$newpriv,$currpub,$currpriv);
       if ($newsettings->{'captcha'} eq 'recaptcha') {
           $newpub = $env{'form.'.$container.'_recaptchapub'};
           $newpriv = $env{'form.'.$container.'_recaptchapriv'};
       }
       $newsettings->{'recaptchakeys'} = {
                                            public  => $newpub,
                                            private => $newpriv,
                                         };
       if (ref($current->{'recaptchakeys'}) eq 'HASH') {
           $currpub = $current->{'recaptchakeys'}{'public'};
           $currpriv = $current->{'recaptchakeys'}{'private'};
       }
       if (($newpub ne $currpub) || ($newpriv ne $currpriv)) {
           if (ref($changes->{'cancreate'}) eq 'ARRAY') {
               push(@{$changes->{'cancreate'}},'recaptchakeys');
           } elsif (!defined($changes->{'cancreate'})) {
               $changes->{'cancreate'} = ['recaptchakeys'];
           }
       }
       return;
   }
   
 sub modify_usermodification {  sub modify_usermodification {
     my ($dom,%domconfig) = @_;      my ($dom,%domconfig) = @_;
     my ($resulttext,%curr_usermodification,%changes);      my ($resulttext,%curr_usermodification,%changes);
Line 7061  sub modify_usersessions { Line 7758  sub modify_usersessions {
     }      }
   
     my @alldoms = &Apache::lonnet::all_domains();      my @alldoms = &Apache::lonnet::all_domains();
     my %uniques = &Apache::lonnet::get_unique_servers(\@alldoms);      my %servers = &Apache::lonnet::internet_dom_servers($dom);
     my %servers = &dom_servers($dom);  
     my %spareid = &current_offloads_to($dom,$domconfig{'usersessions'},\%servers);      my %spareid = &current_offloads_to($dom,$domconfig{'usersessions'},\%servers);
     my $savespares;      my $savespares;
   
     foreach my $lonhost (sort(keys(%servers))) {      foreach my $lonhost (sort(keys(%servers))) {
         my $serverhomeID =          my $serverhomeID =
             &Apache::lonnet::get_server_homeID($servers{$lonhost});              &Apache::lonnet::get_server_homeID($servers{$lonhost});
           my $serverhostname = &Apache::lonnet::hostname($lonhost);
         $defaultshash{'usersessions'}{'spares'}{$lonhost} = {};          $defaultshash{'usersessions'}{'spares'}{$lonhost} = {};
         my %spareschg;          my %spareschg;
         foreach my $type (@{$types{'spares'}}) {          foreach my $type (@{$types{'spares'}}) {
             my @okspares;              my @okspares;
             my @checked = &Apache::loncommon::get_env_multiple('form.spare_'.$type.'_'.$lonhost);              my @checked = &Apache::loncommon::get_env_multiple('form.spare_'.$type.'_'.$lonhost);
             foreach my $server (@checked) {              foreach my $server (@checked) {
                 unless (($server eq $lonhost) || ($server eq $serverhomeID)) {                  if (&Apache::lonnet::hostname($server) ne '') {
                     if ($uniques{$server}) {                      unless (&Apache::lonnet::hostname($server) eq $serverhostname) {
                         push(@okspares,$server);                          unless (grep(/^\Q$server\E$/,@okspares)) {
                               push(@okspares,$server);
                           }
                     }                      }
                 }                  }
             }              }
             my $new = $env{'form.newspare_'.$type.'_'.$lonhost};              my $new = $env{'form.newspare_'.$type.'_'.$lonhost};
             my $newspare;              my $newspare;
             if (($new ne '') && ($uniques{$new})) {              if (($new ne '') && (&Apache::lonnet::hostname($new))) {
                 unless (($new eq $lonhost) || ($new eq $serverhomeID)) {                  unless (&Apache::lonnet::hostname($new) eq $serverhostname) {
                     $newspare = $new;                      $newspare = $new;
                     $spareschg{$type} = 1;  
                 }  
             }  
             if (ref($spareid{$lonhost}) eq 'HASH') {  
                 if (ref($spareid{$lonhost}{$type}) eq 'ARRAY') {  
                     my @diffs = &Apache::loncommon::compare_arrays($domconfig{'usersessions'}{'spares'}{$lonhost}{$type},\@okspares);  
                     if (@diffs > 0) {  
                         $spareschg{$type} = 1;  
                     } elsif ($new ne '') {  
                         $spareschg{$type} = 1;  
                     }  
                 }                  }
             }              }
             my @spares;              my @spares;
Line 7106  sub modify_usersessions { Line 7794  sub modify_usersessions {
                 @spares = sort(@okspares);                  @spares = sort(@okspares);
             }              }
             $defaultshash{'usersessions'}{'spares'}{$lonhost}{$type} = \@spares;              $defaultshash{'usersessions'}{'spares'}{$lonhost}{$type} = \@spares;
               if (ref($spareid{$lonhost}) eq 'HASH') {
                   if (ref($spareid{$lonhost}{$type}) eq 'ARRAY') {
                       my @diffs = &Apache::loncommon::compare_arrays($spareid{$lonhost}{$type},\@spares);
                       if (@diffs > 0) {
                           $spareschg{$type} = 1;
                       }
                   }
               }
         }          }
         if (keys(%spareschg) > 0) {          if (keys(%spareschg) > 0) {
             $changes{'spares'}{$lonhost} = \%spareschg;              $changes{'spares'}{$lonhost} = \%spareschg;
Line 7124  sub modify_usersessions { Line 7820  sub modify_usersessions {
         }          }
     }      }
   
     if (keys(%changes) > 0) {      my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');
       if ((keys(%changes) > 0) || ($savespares)) {
         my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,          my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                                  $dom);                                                   $dom);
         if ($putresult eq 'ok') {          if ($putresult eq 'ok') {
Line 7138  sub modify_usersessions { Line 7835  sub modify_usersessions {
             }              }
             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);
             my %lt = &usersession_titles();              if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';                  my %lt = &usersession_titles();
             foreach my $prefix (@prefixes) {                  $resulttext = &mt('Changes made:').'<ul>';
                 if (ref($changes{$prefix}) eq 'HASH') {                  foreach my $prefix (@prefixes) {
                     $resulttext .= '<li>'.$lt{$prefix}.'<ul>';                      if (ref($changes{$prefix}) eq 'HASH') {
                     if ($prefix eq 'spares') {                          $resulttext .= '<li>'.$lt{$prefix}.'<ul>';
                         if (ref($changes{$prefix}) eq 'HASH') {                          if ($prefix eq 'spares') {
                             foreach my $lonhost (sort(keys(%{$changes{$prefix}}))) {                              if (ref($changes{$prefix}) eq 'HASH') {
                                 $resulttext .= '<li><b>'.$lonhost.'</b> ';                                  foreach my $lonhost (sort(keys(%{$changes{$prefix}}))) {
                                 if (ref($changes{$prefix}{$lonhost}) eq 'HASH') {                                      $resulttext .= '<li><b>'.$lonhost.'</b> ';
                                     foreach my $type (@{$types{$prefix}}) {                                      my $lonhostdom = &Apache::lonnet::host_domain($lonhost);
                                         if ($changes{$prefix}{$lonhost}{$type}) {                                      &Apache::lonnet::remote_devalidate_cache($lonhost,'spares',$lonhostdom);
                                             my $offloadto = &mt('None');                                      if (ref($changes{$prefix}{$lonhost}) eq 'HASH') {
                                             if (ref($defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}) eq 'ARRAY') {                                          foreach my $type (@{$types{$prefix}}) {
                                                 if (@{$defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}} > 0) {                                                 if ($changes{$prefix}{$lonhost}{$type}) {
                                                     $offloadto = join(', ',@{$defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}});                                                  my $offloadto = &mt('None');
                                                   if (ref($defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}) eq 'ARRAY') {
                                                       if (@{$defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}} > 0) {   
                                                           $offloadto = join(', ',@{$defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}});
                                                       }
                                                 }                                                  }
                                                   $resulttext .= &mt('[_1] set to: [_2].','<i>'.$lt{$type}.'</i>',$offloadto).('&nbsp;'x3);
                                             }                                              }
                                             $resulttext .= &mt('[_1] set to: [_2]','<i>'.$lt{'type'}.'</i>',$offloadto).('&nbsp;'x3);  
                                         }                                          }
                                     }                                      }
                                       $resulttext .= '</li>';
                                 }                                  }
                                 $resulttext .= '</li>';  
                             }                              }
                         }                          } else {
                     } else {                              foreach my $type (@{$types{$prefix}}) {
                         foreach my $type (@{$types{$prefix}}) {                                  if (defined($changes{$prefix}{$type})) {
                             if (defined($changes{$prefix}{$type})) {                                      my $newvalue;
                                 my $newvalue;                                      if (ref($defaultshash{'usersessions'}) eq 'HASH') {
                                 if (ref($defaultshash{'usersessions'}) eq 'HASH') {                                          if (ref($defaultshash{'usersessions'}{$prefix})) {
                                     if (ref($defaultshash{'usersessions'}{$prefix})) {                                              if ($type eq 'version') {
                                         if ($type eq 'version') {                                                  $newvalue = $defaultshash{'usersessions'}{$prefix}{$type};
                                             $newvalue = $defaultshash{'usersessions'}{$prefix}{$type};                                              } elsif (ref($defaultshash{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {
                                         } elsif (ref($defaultshash{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {                                                  if (@{$defaultshash{'usersessions'}{$prefix}{$type}} > 0) {
                                             if (@{$defaultshash{'usersessions'}{$prefix}{$type}} > 0) {                                                      $newvalue = join(', ',@{$defaultshash{'usersessions'}{$prefix}{$type}});
                                                 $newvalue = join(', ',@{$defaultshash{'usersessions'}{$prefix}{$type}});                                                  }
                                             }                                              }
                                         }                                          }
                                     }                                      }
                                 }                                      if ($newvalue eq '') {
                                 if ($newvalue eq '') {                                          if ($type eq 'version') {
                                     if ($type eq 'version') {                                              $resulttext .= '<li>'.&mt('[_1] set to: off',$lt{$type}).'</li>';
                                         $resulttext .= '<li>'.&mt('[_1] set to: off',$lt{$type}).'</li>';                                          } else {
                                               $resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';
                                           }
                                     } else {                                      } else {
                                         $resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';                                          if ($type eq 'version') {
                                     }                                              $newvalue .= ' '.&mt('(or later)'); 
                                 } else {                                          }
                                     if ($type eq 'version') {                                          $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';
                                         $newvalue .= ' '.&mt('(or later)');   
                                     }                                      }
                                     $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';  
                                 }                                  }
                             }                              }
                         }                          }
                           $resulttext .= '</ul>';
                     }                      }
                     $resulttext .= '</ul>';  
                 }                  }
                   $resulttext .= '</ul>';
               } else {
                   $resulttext = $nochgmsg;
             }              }
             $resulttext .= '</ul>';  
         } else {          } else {
             $resulttext = '<span class="LC_error">'.              $resulttext = '<span class="LC_error">'.
                           &mt('An error occurred: [_1]',$putresult).'</span>';                            &mt('An error occurred: [_1]',$putresult).'</span>';
         }          }
     } else {      } else {
         $resulttext =  &mt('No changes made to settings for user session hosting/offloading.');          $resulttext = $nochgmsg;
       }
       return $resulttext;
   }
   
   sub modify_loadbalancing {
       my ($dom,%domconfig) = @_;
       my $primary_id = &Apache::lonnet::domain($dom,'primary');
       my $intdom = &Apache::lonnet::internet_dom($primary_id);
       my ($othertitle,$usertypes,$types) =
           &Apache::loncommon::sorted_inst_types($dom);
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my @sparestypes = ('primary','default');
       my %typetitles = &sparestype_titles();
       my $resulttext;
       if (keys(%servers) > 1) {
           my ($currbalancer,$currtargets,$currrules);
           if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
               $currbalancer = $domconfig{'loadbalancing'}{'lonhost'};
               $currtargets = $domconfig{'loadbalancing'}{'targets'};
               $currrules = $domconfig{'loadbalancing'}{'rules'};
           } else {
               ($currbalancer,$currtargets) = 
                   &Apache::lonnet::get_lonbalancer_config(\%servers);
           }
           my ($saveloadbalancing,%defaultshash,%changes);
           my ($alltypes,$othertypes,$titles) =
               &loadbalancing_titles($dom,$intdom,$usertypes,$types);
           my %ruletitles = &offloadtype_text();
           my $balancer = $env{'form.loadbalancing_lonhost'};
           if (!$servers{$balancer}) {
               undef($balancer);
           }
           if ($currbalancer ne $balancer) {
               $changes{'lonhost'} = 1;
           }
           $defaultshash{'loadbalancing'}{'lonhost'} = $balancer;
           if ($balancer ne '') {
               unless (ref($domconfig{'loadbalancing'}) eq 'HASH') {
                   $saveloadbalancing = 1;
               }
               foreach my $sparetype (@sparestypes) {
                   my @targets = &Apache::loncommon::get_env_multiple('form.loadbalancing_target_'.$sparetype);
                   my @offloadto;
                   foreach my $target (@targets) {
                       if (($servers{$target}) && ($target ne $balancer)) {
                           if ($sparetype eq 'default') {
                               if (ref($defaultshash{'loadbalancing'}{'targets'}{'primary'}) eq 'ARRAY') {
                                   next if (grep(/^\Q$target\E$/,@{$defaultshash{'loadbalancing'}{'targets'}{'primary'}}));
                               }
                           }
                           unless(grep(/^\Q$target\E$/,@offloadto)) {
                               push(@offloadto,$target);
                           }
                       }
                       $defaultshash{'loadbalancing'}{'targets'}{$sparetype} = \@offloadto;
                   }
               }
           } else {
               foreach my $sparetype (@sparestypes) {
                   $defaultshash{'loadbalancing'}{'targets'}{$sparetype} = [];
               }
           }
           if (ref($currtargets) eq 'HASH') {
               foreach my $sparetype (@sparestypes) {
                   if (ref($currtargets->{$sparetype}) eq 'ARRAY') {
                       my @targetdiffs = &Apache::loncommon::compare_arrays($currtargets->{$sparetype},$defaultshash{'loadbalancing'}{'targets'}{$sparetype});
                       if (@targetdiffs > 0) {
                           $changes{'targets'} = 1;
                       }
                   } elsif (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') {
                       if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) {
                           $changes{'targets'} = 1;
                       }
                   }
               }
           } else {
               foreach my $sparetype (@sparestypes) {
                   if (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') {
                       if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) {
                           $changes{'targets'} = 1;  
                       }
                   }
               }  
           }
           my $ishomedom;
           if ($balancer ne '') {
               if (&Apache::lonnet::host_domain($balancer) eq $dom) {
                   $ishomedom = 1;
               }
           }
           if (ref($alltypes) eq 'ARRAY') {
               foreach my $type (@{$alltypes}) {
                   my $rule;
                   if ($balancer ne '') {
                       unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) && 
                            (!$ishomedom)) {
                           $rule = $env{'form.loadbalancing_rules_'.$type};
                       }
                       if ($rule eq 'specific') {
                           $rule = $env{'form.loadbalancing_singleserver_'.$type};
                       }
                   }
                   $defaultshash{'loadbalancing'}{'rules'}{$type} = $rule;
                   if (ref($currrules) eq 'HASH') {
                       if ($rule ne $currrules->{$type}) {
                           $changes{'rules'}{$type} = 1;
                       }
                   } elsif ($rule ne '') {
                       $changes{'rules'}{$type} = 1;
                   }
               }
           }
           my $nochgmsg = &mt('No changes made to Load Balancer settings.');
           if ((keys(%changes) > 0) || ($saveloadbalancing)) {
               my $putresult = &Apache::lonnet::put_dom('configuration',
                                                        \%defaultshash,$dom);
               if ($putresult eq 'ok') {
                   if (keys(%changes) > 0) {
                       if ($changes{'lonhost'}) {
                           if ($currbalancer ne '') {
                               &Apache::lonnet::remote_devalidate_cache($currbalancer,'loadbalancing',$dom);
                           }
                           if ($balancer eq '') {
                               $resulttext .= '<li>'.&mt('Load Balancing with dedicated server discontinued').'</li>'; 
                           } else {
                               &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom);
                               $resulttext .= '<li>'.&mt('Dedicated Load Balancer server set to [_1]',$balancer);
                           }
                       } else {
                           &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom);
                       }
                       if (($changes{'targets'}) && ($balancer ne '')) {
                           my %offloadstr;
                           foreach my $sparetype (@sparestypes) {
                               if (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') {
                                   if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) {
                                       $offloadstr{$sparetype} = join(', ',@{$defaultshash{'loadbalancing'}{'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 server set to offload to: [_1]',$showoffload).'</li>';
                           }
                       }
                       if ((ref($changes{'rules'}) eq 'HASH') && ($balancer ne '')) {
                           if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) {
                               foreach my $type (@{$alltypes}) {
                                   if ($changes{'rules'}{$type}) {
                                       my $rule = $defaultshash{'loadbalancing'}{'rules'}{$type};
                                       my $balancetext;
                                       if ($rule eq '') {
                                           $balancetext =  $ruletitles{'default'};
                                       } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer')) {
                                           $balancetext =  $ruletitles{$rule};
                                       } else {
                                           $balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{'rules'}{$type});
                                       }
                                       $resulttext .= '<li>'.&mt('Load Balancing for [_1] set to: [_2]',$titles->{$type},$balancetext).'</li>';     
                                   }
                               }
                           }
                       }
                       if ($resulttext ne '') {
                           $resulttext = &mt('Changes made:').'<ul>'.$resulttext.'</ul>';
                       } else {
                           $resulttext = $nochgmsg;
                       }
                   } else {
                       $resulttext = $nochgmsg;
                       if ($balancer ne '') {
                           &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom);
                       }
                   }
               } else {
                   $resulttext = '<span class="LC_error">'.
                                 &mt('An error occurred: [_1]',$putresult).'</span>';
               }
           } else {
               $resulttext = $nochgmsg;
           }
       } else {
           $resulttext =  &mt('Load Balancing unavailable as this domain only has one server.');
     }      }
     return $resulttext;      return $resulttext;
 }  }
Line 7247  sub recurse_cat_deletes { Line 8144  sub recurse_cat_deletes {
     return;      return;
 }  }
   
 sub dom_servers {  
     my ($dom) = @_;  
     my (%uniqservers,%servers);  
     my $primaryserver = &Apache::lonnet::hostname(&Apache::lonnet::domain($dom,'primary'));  
     my @machinedoms = &Apache::lonnet::machine_domains($primaryserver);  
     foreach my $mdom (@machinedoms) {  
         my %currservers = %servers;  
         my %server = &Apache::lonnet::get_servers($mdom);  
         %servers = (%currservers,%server);  
     }  
     my %by_hostname;  
     foreach my $id (keys(%servers)) {  
         push(@{$by_hostname{$servers{$id}}},$id);  
     }  
     foreach my $hostname (sort(keys(%by_hostname))) {  
         if (@{$by_hostname{$hostname}} > 1) {  
             my $match = 0;  
             foreach my $id (@{$by_hostname{$hostname}}) {  
                 if (&Apache::lonnet::host_domain($id) eq $dom) {  
                     $uniqservers{$id} = $hostname;  
                     $match = 1;  
                 }  
             }  
             unless ($match) {  
                 $uniqservers{$by_hostname{$hostname}[0]} = $hostname;  
             }  
         } else {  
             $uniqservers{$by_hostname{$hostname}[0]} = $hostname;  
         }  
     }  
     return %uniqservers;  
 }  
   
 sub get_active_dcs {  sub get_active_dcs {
     my ($dom) = @_;      my ($dom) = @_;
     my %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc']);      my %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc']);
Line 7353  sub active_dc_picker { Line 8217  sub active_dc_picker {
 sub usersession_titles {  sub usersession_titles {
     return &Apache::lonlocal::texthash(      return &Apache::lonlocal::texthash(
                hosted => 'Hosting of sessions for users from other domains on servers in this domain',                 hosted => 'Hosting of sessions for users from other domains on servers in this domain',
   
                remote => 'Hosting of sessions for users in this domain on servers in other domains',                 remote => 'Hosting of sessions for users in this domain on servers in other domains',
                spares => 'Servers offloaded to, when busy',                 spares => 'Servers offloaded to, when busy',
                version => 'LON-CAPA version requirement',                 version => 'LON-CAPA version requirement',
                excludedomain => 'Allow all, but exclude specific domains',                 excludedomain => 'Allow all, but exclude specific domains',
                includedomain => 'Deny all, but include specific domains',                 includedomain => 'Deny all, but include specific domains',
                primary => 'Primary (checked first)',                 primary => 'Primary (checked first)',
                default => 'Default',                  default => 'Default',
            );             );
 }  }
   
   sub id_for_thisdom {
       my (%servers) = @_;
       my %altids;
       foreach my $server (keys(%servers)) {
           my $serverhome = &Apache::lonnet::get_server_homeID($servers{$server});
           if ($serverhome ne $server) {
               $altids{$serverhome} = $server;
           }
       }
       return %altids;
   }
   
   sub count_servers {
       my ($currbalancer,%servers) = @_;
       my (@spares,$numspares);
       foreach my $lonhost (sort(keys(%servers))) {
           next if ($currbalancer eq $lonhost);
           push(@spares,$lonhost);
       }
       if ($currbalancer) {
           $numspares = scalar(@spares);
       } else {
           $numspares = scalar(@spares) - 1;
       }
       return ($numspares,@spares);
   }
   
   sub lonbalance_targets_js {
       my ($dom,$types,$servers) = @_;
       my $select = &mt('Select');
       my ($alltargets,$allishome,$allinsttypes,@alltypes);
       if (ref($servers) eq 'HASH') {
           $alltargets = join("','",sort(keys(%{$servers})));
           my @homedoms;
           foreach my $server (sort(keys(%{$servers}))) {
               if (&Apache::lonnet::host_domain($server) eq $dom) {
                   push(@homedoms,'1');
               } else {
                   push(@homedoms,'0');
               }
           }
           $allishome = join("','",@homedoms);
       }
       if (ref($types) eq 'ARRAY') {
           if (@{$types} > 0) {
               @alltypes = @{$types};
           }
       }
       push(@alltypes,'default','_LC_adv','_LC_author','_LC_internetdom','_LC_external');
       $allinsttypes = join("','",@alltypes);
       return <<"END";
   
   <script type="text/javascript">
   // <![CDATA[
   
   function toggleTargets() {
       var balancer = document.display.loadbalancing_lonhost.options[document.display.loadbalancing_lonhost.selectedIndex].value;
       if (balancer == '') {
           hideSpares();
       } else {
           var homedoms = new Array('$allishome');
           var ishomedom = homedoms[document.display.loadbalancing_lonhost.selectedIndex];
           showSpares(balancer,ishomedom);
       }
       return;
   }
   
   function showSpares(balancer,ishomedom) {
       var alltargets = new Array('$alltargets');
       var insttypes = new Array('$allinsttypes');
       var offloadtypes = new Array('primary','default');
   
       document.getElementById('loadbalancing_targets').style.display='block';
       document.getElementById('loadbalancing_disabled').style.display='none';
    
       for (var i=0; i<offloadtypes.length; i++) {
           var count = 0;
           for (var j=0; j<alltargets.length; j++) {
               if (alltargets[j] != balancer) {
                   document.getElementById('loadbalancing_target_'+offloadtypes[i]+'_'+count).value = alltargets[j];
                   document.getElementById('loadbalancing_targettxt_'+offloadtypes[i]+'_'+count).style.textAlign='left';
                   document.getElementById('loadbalancing_targettxt_'+offloadtypes[i]+'_'+count).style.textFace='normal';
                   document.getElementById('loadbalancing_targettxt_'+offloadtypes[i]+'_'+count).innerHTML = alltargets[j];
                   count ++;
               }
           }
       }
       for (var k=0; k<insttypes.length; k++) {
           if ((insttypes[k] == '_LC_external') || (insttypes[k] == '_LC_internetdom')) {
               if (ishomedom == 1) {
                   document.getElementById('balanceruletitle_'+insttypes[k]).style.display='block';
                   document.getElementById('balancerule_'+insttypes[k]).style.display='block';
               } else {
                   document.getElementById('balanceruletitle_'+insttypes[k]).style.display='none';
                   document.getElementById('balancerule_'+insttypes[k]).style.display='none';
   
               }
           } else {
               document.getElementById('balanceruletitle_'+insttypes[k]).style.display='block';
               document.getElementById('balancerule_'+insttypes[k]).style.display='block';
           }
           if ((insttypes[k] != '_LC_external') && 
               ((insttypes[k] != '_LC_internetdom') ||
                ((insttypes[k] == '_LC_internetdom') && (ishomedom == 1)))) {
               document.getElementById('loadbalancing_singleserver_'+insttypes[k]).options[0] = new Option("","",true,true);
               for (var m=0; m<alltargets.length; m++) {
                   var idx = m+1;
                   if (alltargets[m] != balancer) {
                       document.getElementById('loadbalancing_singleserver_'+insttypes[k]).options[idx] = new Option(alltargets[m],alltargets[m],false,false);
                   }
               }
           }
       }
       return;
   }
   
   function hideSpares() {
       var alltargets = new Array('$alltargets');
       var insttypes = new Array('$allinsttypes');
       var offloadtypes = new Array('primary','default');
   
       document.getElementById('loadbalancing_targets').style.display='none';
       document.getElementById('loadbalancing_disabled').style.display='block';
   
       var total = alltargets.length - 1;
       for (var i=0; i<offloadtypes; i++) {
           for (var j=0; j<total; j++) {
              document.getElementById('loadbalancing_target_'+offloadtypes[i]+'_'+j).checked = false;
              document.getElementById('loadbalancing_target_'+offloadtypes[i]+'_'+j).value = '';
              document.getElementById('loadbalancing_targettxt_'+offloadtypes[i]+'_'+j).innerHTML = '';
           }
       }
       for (var k=0; k<insttypes.length; k++) {
           document.getElementById('balanceruletitle_'+insttypes[k]).style.display='none';
           document.getElementById('balancerule_'+insttypes[k]).style.display='none';
           if (insttypes[k] != '_LC_external') {
               document.getElementById('loadbalancing_singleserver_'+insttypes[k]).length = 0;
               document.getElementById('loadbalancing_singleserver_'+insttypes[k]).options[0] = new Option("","",true,true);
           }
       }
       return;
   }
   
   function checkOffloads(item,type) {
       var alltargets = new Array('$alltargets');
       var offloadtypes = new Array('primary','default');
       if (item.checked) {
           var total = alltargets.length - 1;
           var other;
           if (type == offloadtypes[0]) {
               other = offloadtypes[1];
           } else {
               other = offloadtypes[0];
           }
           for (var i=0; i<total; i++) {
               var server = document.getElementById('loadbalancing_target_'+other+'_'+i).value;
               if (server == item.value) {
                   if (document.getElementById('loadbalancing_target_'+other+'_'+i).checked) {
                       document.getElementById('loadbalancing_target_'+other+'_'+i).checked = false;
                   }
               }
           }
       }
       return;
   }
   
   function singleServerToggle(type) {
       var offloadtoSelIdx = document.getElementById('loadbalancing_singleserver_'+type).selectedIndex;
       if (offloadtoSelIdx == 0) {
           document.getElementById('loadbalancing_rules_'+type+'_0').checked = true;
           document.getElementById('loadbalancing_singleserver_'+type).options[0].text = '';
   
       } else {
           document.getElementById('loadbalancing_rules_'+type+'_2').checked = true;
           document.getElementById('loadbalancing_singleserver_'+type).options[0].text = '$select';
       }
       return;
   }
   
   function balanceruleChange(formname,type) {
       if (type == '_LC_external') {
           return; 
       }
       var typesRules = getIndicesByName(formname,'loadbalancing_rules_'+type);
       for (var i=0; i<typesRules.length; i++) {
           if (formname.elements[typesRules[i]].checked) {
               if (formname.elements[typesRules[i]].value != 'specific') {
                   document.getElementById('loadbalancing_singleserver_'+type).selectedIndex = 0;
                   document.getElementById('loadbalancing_singleserver_'+type).options[0].text = '';
               } else {
                   document.getElementById('loadbalancing_singleserver_'+type).options[0].text = '$select';
               }
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   END
   }
   
   sub new_spares_js {
       my @sparestypes = ('primary','default');
       my $types = join("','",@sparestypes);
       my $select = &mt('Select');
       return <<"END";
   
   <script type="text/javascript">
   // <![CDATA[
   
   function updateNewSpares(formname,lonhost) {
       var types = new Array('$types');
       var include = new Array();
       var exclude = new Array();
       for (var i=0; i<types.length; i++) {
           var spareboxes = getIndicesByName(formname,'spare_'+types[i]+'_'+lonhost);
           for (var j=0; j<spareboxes.length; j++) {
               if (formname.elements[spareboxes[j]].checked) {
                   exclude.push(formname.elements[spareboxes[j]].value);
               } else {
                   include.push(formname.elements[spareboxes[j]].value);
               }
           }
       }
       for (var i=0; i<types.length; i++) {
           var newSpare = document.getElementById('newspare_'+types[i]+'_'+lonhost);
           var selIdx = newSpare.selectedIndex;
           var currnew = newSpare.options[selIdx].value;
           var okSpares = new Array();
           for (var j=0; j<newSpare.options.length; j++) {
               var possible = newSpare.options[j].value;
               if (possible != '') {
                   if (exclude.indexOf(possible) == -1) {
                       okSpares.push(possible);
                   } else {
                       if (currnew == possible) {
                           selIdx = 0;
                       }
                   }
               }
           }
           for (var k=0; k<include.length; k++) {
               if (okSpares.indexOf(include[k]) == -1) {
                   okSpares.push(include[k]);
               }
           }
           okSpares.sort();
           newSpare.options.length = 0;
           if (selIdx == 0) {
               newSpare.options[0] = new Option("$select","",true,true);
           } else {
               newSpare.options[0] = new Option("$select","",false,false);
           }
           for (var m=0; m<okSpares.length; m++) {
               var idx = m+1;
               var selThis = 0;
               if (selIdx != 0) {
                   if (okSpares[m] == currnew) {
                       selThis = 1;
                   }
               }
               if (selThis == 1) {
                   newSpare.options[idx] = new Option(okSpares[m],okSpares[m],true,true);
               } else {
                   newSpare.options[idx] = new Option(okSpares[m],okSpares[m],false,false);
               }
           }
       }
       return;
   }
   
   function checkNewSpares(lonhost,type) {
       var newSpare = document.getElementById('newspare_'+type+'_'+lonhost);
       var chosen =  newSpare.options[newSpare.selectedIndex].value;
       if (chosen != '') { 
           var othertype;
           var othernewSpare;
           if (type == 'primary') {
               othernewSpare = document.getElementById('newspare_default_'+lonhost);
           }
           if (type == 'default') {
               othernewSpare = document.getElementById('newspare_primary_'+lonhost);
           }
           if (othernewSpare.options[othernewSpare.selectedIndex].value == chosen) {
               othernewSpare.selectedIndex = 0;
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   END
   
   }
   
   sub common_domprefs_js {
       return <<"END";
   
   <script type="text/javascript">
   // <![CDATA[
   
   function getIndicesByName(formname,item) {
       var group = new Array();
       for (var i=0;i<formname.elements.length;i++) {
           if (formname.elements[i].name == item) {
               group.push(formname.elements[i].id);
           }
       }
       return group;
   }
   
   // ]]>
   </script>
   
   END
   
   }
   
   sub recaptcha_js {
       my %lt = &captcha_phrases();
       return <<"END";
   
   <script type="text/javascript">
   // <![CDATA[
   
   function updateCaptcha(caller,context) {
       var privitem;
       var pubitem;
       var privtext;
       var pubtext;
       if (document.getElementById(context+'_recaptchapub')) {
           pubitem = document.getElementById(context+'_recaptchapub');
       } else {
           return;
       }
       if (document.getElementById(context+'_recaptchapriv')) {
           privitem = document.getElementById(context+'_recaptchapriv');
       } else {
           return;
       }
       if (document.getElementById(context+'_recaptchapubtxt')) {
           pubtext = document.getElementById(context+'_recaptchapubtxt');
       } else {
           return;
       }
       if (document.getElementById(context+'_recaptchaprivtxt')) {
           privtext = document.getElementById(context+'_recaptchaprivtxt');
       } else {
           return;
       }
       if (caller.checked) {
           if (caller.value == 'recaptcha') {
               pubitem.type = 'text';
               privitem.type = 'text';
               pubitem.size = '40';
               privitem.size = '40';
               pubtext.innerHTML = "$lt{'pub'}";
               privtext.innerHTML = "$lt{'priv'}";
           } else {
               pubitem.type = 'hidden';
               privitem.type = 'hidden';
               pubtext.innerHTML = '';
               privtext.innerHTML = '';
           }
       }
       return;
   }
   
   // ]]>
   </script>
   
   END
   
   }
   
   sub captcha_phrases {
       return &Apache::lonlocal::texthash (
                    priv => 'Private key',
                    pub  => 'Public key',
                    original  => 'original (CAPTCHA)',
                    recaptcha => 'successor (ReCAPTCHA)',
                    notused   => 'unused',
       );
   }
   
 1;  1;

Removed from v.1.146  
changed lines
  Added in v.1.165


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