--- loncom/interface/domainprefs.pm	2020/01/15 16:55:18	1.160.6.102.2.1
+++ loncom/interface/domainprefs.pm	2021/03/07 00:32:21	1.160.6.102.2.11
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set domain-wide configuration settings
 #
-# $Id: domainprefs.pm,v 1.160.6.102.2.1 2020/01/15 16:55:18 raeburn Exp $
+# $Id: domainprefs.pm,v 1.160.6.102.2.11 2021/03/07 00:32:21 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -349,6 +349,8 @@ sub handler {
                                 col2 => 'Value',},
                                {col1 => 'Recipient(s) for notifications',
                                 col2 => 'Value',},
+                               {col1 => 'Nightly status check e-mail',
+                                col2 => 'Settings',},
                                {col1 => 'Ask helpdesk form settings',
                                 col2 => 'Value',},],
                     print => \&print_contacts,
@@ -726,6 +728,8 @@ sub print_config_box {
         $output =
             &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full,
                                                       \@templateroles);
+    } elsif ($action eq 'ltitools') {
+        $output .= &ltitools_javascript($settings);
     }
     $output .=
          '<table class="LC_nested_outer">
@@ -742,6 +746,7 @@ sub print_config_box {
     if ($numheaders > 1) {
         my $colspan = '';
         my $rightcolspan = '';
+        my $leftnobr = '';
         if (($action eq 'rolecolors') || ($action eq 'defaults') ||
             ($action eq 'directorysrch') ||
             (($action eq 'login') && ($numheaders < 4))) {
@@ -750,12 +755,15 @@ sub print_config_box {
         if ($action eq 'usersessions') {
             $rightcolspan = ' colspan="3"'; 
         }
+        if ($action eq 'passwords') {
+            $leftnobr = ' LC_nobreak';
+        }
         $output .= '
           <tr>
            <td>
             <table class="LC_nested">
              <tr class="LC_info_row">
-              <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
+              <td class="LC_left_item'.$leftnobr.'"'.$colspan.'>'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
               <td class="LC_right_item"'.$rightcolspan.'>'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
              </tr>';
         $rowtotal ++;
@@ -814,13 +822,18 @@ sub print_config_box {
            <td>
             <table class="LC_nested">
              <tr class="LC_info_row">
-              <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
+              <td class="LC_left_item'.$leftnobr.'"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
              </tr>'."\n";
             if ($action eq 'coursecategories') {
                 $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
-            } elsif ($action eq 'passwords') {
-                $output .= $item->{'print'}->('lower',$dom,$confname,$settings,\$rowtotal).'
+            } elsif (($action eq 'contacts') || ($action eq 'passwords')) {
+                if ($action eq 'passwords') {
+                    $output .= $item->{'print'}->('lower',$dom,$confname,$settings,\$rowtotal);
+                } else {
+                    $output .= $item->{'print'}->('lower',$dom,$settings,\$rowtotal);
+                }
+                $output .= '
              </tr>
             </table>
            </td>
@@ -830,8 +843,13 @@ sub print_config_box {
             <table class="LC_nested">
              <tr class="LC_info_row">
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
-              <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td></tr>'."\n".
-              $item->{'print'}->('bottom',$dom,$confname,$settings,\$rowtotal).'
+              <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td></tr>'."\n";
+                if ($action eq 'passwords') {
+                    $output .= $item->{'print'}->('bottom',$dom,$confname,$settings,\$rowtotal);
+                } else {
+                    $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
+                }
+                $output .= '
             </table>
           </td>
          </tr>
@@ -2521,7 +2539,10 @@ ENDSCRIPT
 
 sub ltitools_javascript {
     my ($settings) = @_;
-    return unless(ref($settings) eq 'HASH');
+    my $togglejs = &ltitools_toggle_js();
+    unless (ref($settings) eq 'HASH') {
+        return $togglejs;
+    }
     my (%ordered,$total,%jstext);
     $total = 0;
     foreach my $item (keys(%{$settings})) {
@@ -2539,7 +2560,7 @@ sub ltitools_javascript {
     return <<"ENDSCRIPT";
 <script type="text/javascript">
 // <![CDATA[
-function reorderLTI(form,item) {
+function reorderLTITools(form,item) {
     var changedVal;
 $jstext
     var newpos = 'ltitools_add_pos';
@@ -2584,6 +2605,37 @@ $jstext
 // ]]>
 </script>
 
+$togglejs
+
+ENDSCRIPT
+}
+
+sub ltitools_toggle_js {
+    return <<"ENDSCRIPT";
+<script type="text/javascript">
+// <![CDATA[
+
+function toggleLTITools(form,setting,item) {
+    var radioname = '';
+    var divid = '';
+    if (setting == 'user') {
+        divid = 'ltitools_'+setting+'_div_'+item;
+        var checkid = 'ltitools_'+setting+'_field_'+item;
+        if (document.getElementById(divid)) {
+            if (document.getElementById(checkid)) {
+                if (document.getElementById(checkid).checked) {
+                    document.getElementById(divid).style.display = 'inline-block';
+                } else {
+                    document.getElementById(divid).style.display = 'none';
+                }
+            }
+        }
+    }
+    return;
+}
+// ]]>
+</script>
+
 ENDSCRIPT
 }
 
@@ -2948,7 +3000,7 @@ sub print_contacts {
     my $datatable;
     my @contacts = ('adminemail','supportemail');
     my (%checked,%to,%otheremails,%bccemails,%includestr,%includeloc,%currfield,
-        $maxsize,$fields,$fieldtitles,$fieldoptions,$possoptions,@mailings);
+        $maxsize,$fields,$fieldtitles,$fieldoptions,$possoptions,@mailings,%lonstatus);
     if ($position eq 'top') {
         if (ref($settings) eq 'HASH') {
             foreach my $item (@contacts) {
@@ -2963,6 +3015,12 @@ sub print_contacts {
         foreach my $type (@mailings) {
             $otheremails{$type} = '';
         }
+    } elsif ($position eq 'lower') {
+        if (ref($settings) eq 'HASH') {
+            if (ref($settings->{'lonstatus'}) eq 'HASH') {
+                %lonstatus = %{$settings->{'lonstatus'}};
+            }
+        }
     } else {
         @mailings = ('helpdeskmail','otherdomsmail');
         foreach my $type (@mailings) {
@@ -2975,7 +3033,7 @@ sub print_contacts {
         ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();
     }
     if (ref($settings) eq 'HASH') {
-        unless ($position eq 'top') {
+        unless (($position eq 'top') || ($position eq 'lower')) {
             foreach my $type (@mailings) {
                 if (exists($settings->{$type})) {
                     if (ref($settings->{$type}) eq 'HASH') {
@@ -3108,7 +3166,7 @@ sub print_contacts {
         $datatable .= '</td></tr>'."\n";
         $rownum ++;
     }
-    unless ($position eq 'top') {
+    unless (($position eq 'top') || ($position eq 'lower')) {
         foreach my $type (@mailings) {
             $css_class = $rownum%2?' class="LC_odd_row"':'';
             $datatable .= '<tr'.$css_class.'>'.
@@ -3155,18 +3213,104 @@ sub print_contacts {
     }
     if ($position eq 'middle') {
         my %choices;
-        $choices{'reporterrors'} = &mt('E-mail error reports to [_1]',
-                                       &Apache::loncommon::modal_link('http://loncapa.org/core.html',
-                                       &mt('LON-CAPA core group - MSU'),600,500));
+        my $corelink = &core_link_msu();
+        $choices{'reporterrors'} = &mt('E-mail error reports to [_1]',$corelink);
         $choices{'reportupdates'} = &mt('E-mail record of completed LON-CAPA updates to [_1]',
-                                        &Apache::loncommon::modal_link('http://loncapa.org/core.html',
-                                        &mt('LON-CAPA core group - MSU'),600,500));
-        my @toggles = ('reporterrors','reportupdates');
+                                        $corelink);
+        $choices{'reportstatus'} = &mt('E-mail status if errors above threshold to [_1]',$corelink);
+        my @toggles = ('reporterrors','reportupdates','reportstatus');
         my %defaultchecked = ('reporterrors'  => 'on',
-                              'reportupdates' => 'on');
+                              'reportupdates' => 'on',
+                              'reportstatus'  => 'on');
         (my $reports,$rownum) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
                                                    \%choices,$rownum);
         $datatable .= $reports;
+    } elsif ($position eq 'lower') {
+        my (%current,%excluded,%weights);
+        my ($defaults,$names) = &Apache::loncommon::lon_status_items();
+        if ($lonstatus{'threshold'} =~ /^\d+$/) {
+            $current{'errorthreshold'} = $lonstatus{'threshold'};
+        } else {
+            $current{'errorthreshold'} = $defaults->{'threshold'};
+        }
+        if ($lonstatus{'sysmail'} =~ /^\d+$/) {
+            $current{'errorsysmail'} = $lonstatus{'sysmail'};
+        } else {
+            $current{'errorsysmail'} = $defaults->{'sysmail'};
+        }
+        if (ref($lonstatus{'weights'}) eq 'HASH') {
+            foreach my $type ('E','W','N','U') {
+                if ($lonstatus{'weights'}{$type} =~ /^\d+$/) {
+                    $weights{$type} = $lonstatus{'weights'}{$type};
+                } else {
+                    $weights{$type} = $defaults->{$type};
+                }
+            }
+        } else {
+            foreach my $type ('E','W','N','U') {
+                $weights{$type} = $defaults->{$type};
+            }
+        }
+        if (ref($lonstatus{'excluded'}) eq 'ARRAY') {
+            if (@{$lonstatus{'excluded'}} > 0) {
+                map {$excluded{$_} = 1; } @{$lonstatus{'excluded'}};
+            }
+        }
+        foreach my $item ('errorthreshold','errorsysmail') {
+            $css_class = $rownum%2?' class="LC_odd_row"':'';
+            $datatable .= '<tr'.$css_class.'>'.
+                          '<td class="LC_left_item"><span class="LC_nobreak">'.
+                          $titles->{$item}.
+                          '</span></td><td class="LC_left_item">'.
+                          '<input type="text" name="'.$item.'" value="'.
+                          $current{$item}.'" size="5" /></td></tr>';
+            $rownum ++;
+        }
+        $css_class = $rownum%2?' class="LC_odd_row"':'';
+        $datatable .= '<tr'.$css_class.'>'.
+                      '<td class="LC_left_item">'.
+                      '<span class="LC_nobreak">'.$titles->{'errorweights'}.
+                      '</span></td><td class="LC_left_item"><table><tr>';
+        foreach my $type ('E','W','N','U') {
+            $datatable .= '<td>'.$names->{$type}.'<br />'.
+                          '<input type="text" name="errorweights_'.$type.'" value="'.
+                          $weights{$type}.'" size="5" /></td>';
+        }
+        $datatable .= '</tr></table></tr>';
+        $rownum ++;
+        $css_class = $rownum%2?' class="LC_odd_row"':'';
+        $datatable .= '<tr'.$css_class.'><td class="LC_left_item">'.
+                      $titles->{'errorexcluded'}.'</td>'.
+                      '<td class="LC_left_item"><table>';
+        my $numinrow = 4;
+        my @ids = sort(values(%Apache::lonnet::serverhomeIDs));
+        for (my $i=0; $i<@ids; $i++) {
+            my $rem = $i%($numinrow);
+            if ($rem == 0) {
+                if ($i > 0) {
+                    $datatable .= '</tr>';
+                }
+                $datatable .= '<tr>';
+            }
+            my $check;
+            if ($excluded{$ids[$i]}) {
+                $check = ' checked="checked" ';
+            }
+            $datatable .= '<td class="LC_left_item">'.
+                          '<span class="LC_nobreak"><label>'.
+                          '<input type="checkbox" name="errorexcluded" '.
+                          'value="'.$ids[$i].'"'.$check.' />'.
+                          $ids[$i].'</label></span></td>';
+        }
+        my $colsleft = $numinrow - @ids%($numinrow);
+        if ($colsleft > 1 ) {
+            $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
+                          '&nbsp;</td>';
+        } elsif ($colsleft == 1) {
+            $datatable .= '<td class="LC_left_item">&nbsp;</td>';
+        }
+        $datatable .= '</tr></table></td></tr>';
+        $rownum ++;
     } elsif ($position eq 'bottom') {
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
         my (@posstypes,%usertypeshash);
@@ -3240,6 +3384,11 @@ sub print_contacts {
     return $datatable;
 }
 
+sub core_link_msu {
+    return &Apache::loncommon::modal_link('http://loncapa.org/core.html',
+                                          &mt('LON-CAPA core group - MSU'),600,500);
+}
+
 sub overridden_helpdesk {
     my ($checked,$otheremails,$bccemails,$includeloc,$includestr,$type,$rowid,
         $typetitle,$css_class,$rowstyle,$contacts,$short_titles) = @_;
@@ -3812,28 +3961,34 @@ sub print_ltitools {
     my $confname = $dom.'-domainconfig';
     my $switchserver = &check_switchserver($dom,$confname);
     my $maxnum = scalar(keys(%ordered));
-    my $datatable = &ltitools_javascript($settings);
+    my $datatable;
     my %lt = &ltitools_names();
     my @courseroles = ('cc','in','ta','ep','st');
     my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner);
-    my @fields = ('fullname','firstname','lastname','email','user','roles');
+    my @fields = ('fullname','firstname','lastname','email','roles','user');
     if (keys(%ordered)) {
         my @items = sort { $a <=> $b } keys(%ordered);
         for (my $i=0; $i<@items; $i++) {
             $css_class = $itemcount%2?' class="LC_odd_row"':'';
             my $item = $ordered{$items[$i]};
-            my ($title,$key,$secret,$url,$imgsrc,$version);
+            my ($title,$key,$secret,$url,$lifetime,$imgsrc,%sigsel);
             if (ref($settings->{$item}) eq 'HASH') {
                 $title = $settings->{$item}->{'title'};
                 $url = $settings->{$item}->{'url'};
                 $key = $settings->{$item}->{'key'};
                 $secret = $settings->{$item}->{'secret'};
+                $lifetime = $settings->{$item}->{'lifetime'};
                 my $image = $settings->{$item}->{'image'};
                 if ($image ne '') {
                     $imgsrc = '<img src="'.$image.'" alt="'.&mt('Tool Provider icon').'" />';
                 }
+                if ($settings->{$item}->{'sigmethod'} eq 'HMAC-256') {
+                    $sigsel{'HMAC-256'} = ' selected="selected"';
+                } else {
+                    $sigsel{'HMAC-SHA1'} = ' selected="selected"';
+                }
             }
-            my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_".$item."'".');"';
+            my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_".$item."'".');"';
             $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
                          .'<select name="ltitools_'.$item.'"'.$chgstr.'>';
             for (my $k=0; $k<=$maxnum; $k++) {
@@ -3849,20 +4004,27 @@ sub print_ltitools {
                 &mt('Delete?').'</label></span></td>'.
                 '<td colspan="2">'.
                 '<fieldset><legend>'.&mt('Required settings').'</legend>'.
-                '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="30" name="ltitools_title_'.$i.'" value="'.$title.'" /></span> '.
+                '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="20" name="ltitools_title_'.$i.'" value="'.$title.'" /></span> '.
                 ('&nbsp;'x2).
                 '<span class="LC_nobreak">'.$lt{'version'}.':<select name="ltitools_version_'.$i.'">'.
                 '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '.
                 ('&nbsp;'x2).
                 '<span class="LC_nobreak">'.$lt{'msgtype'}.':<select name="ltitools_msgtype_'.$i.'">'.
                 '<option value="basic-lti-launch-request" selected="selected">Launch</option></select></span> '.
+                ('&nbsp;'x2).
+                '<span class="LC_nobreak">'.$lt{'sigmethod'}.':<select name="ltitools_sigmethod_'.$i.'">'.
+                '<option value="HMAC-SHA1"'.$sigsel{'HMAC-SHA1'}.'>HMAC-SHA1</option>'.
+                '<option value="HMAC-SHA256"'.$sigsel{'HMAC-SHA256'}.'>HMAC-SHA256</option></select></span>'.
                 '<br /><br />'.
-                '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="30" name="ltitools_url_'.$i.'"'.
+                '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="40" name="ltitools_url_'.$i.'"'.
                 ' value="'.$url.'" /></span>'.
                 ('&nbsp;'x2).
-                '<span class="LC_nobreak">'.$lt{'key'}.
+                '<span class="LC_nobreak">'.$lt{'key'}.':'.
                 '<input type="text" size="25" name="ltitools_key_'.$i.'" value="'.$key.'" /></span> '.
                 ('&nbsp;'x2).
+                '<span class="LC_nobreak">'.$lt{'lifetime'}.':'.
+                '<input type="text" size="5" name="ltitools_lifetime_'.$i.'" value="'.$lifetime.'" /></span> '.
+                ('&nbsp;'x2).
                 '<span class="LC_nobreak">'.$lt{'secret'}.':'.
                 '<input type="password" size="20" name="ltitools_secret_'.$i.'" value="'.$secret.'" />'.
                 '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.ltitools_secret_'.$i.'.type='."'text'".' } else { this.form.ltitools_secret_'.$i.'.type='."'password'".' }" />'.&mt('Visible input').'</label>'.
@@ -3900,27 +4062,14 @@ sub print_ltitools {
                               '<input type="text" name="ltitools_'.$dimen.'_'.$i.'" size="5" value="'.$currdisp{$dimen}.'" /></label>'.
                               ('&nbsp;'x2);
             }
-            $datatable .= '<br />'.
+            $datatable .= '</span><br />'.
                           '<div class="LC_left_float">'.$lt{'linktext'}.'<br />'.
-                          '<input type="text" name="ltitools_linktext_'.$i.'" size="25" value="'.$currdisp{'linktext'}.'" /></label></div>'.
+                          '<input type="text" name="ltitools_linktext_'.$i.'" size="25" value="'.$currdisp{'linktext'}.'" /></div>'.
                           '<div class="LC_left_float">'.$lt{'explanation'}.'<br />'.
                           '<textarea name="ltitools_explanation_'.$i.'" rows="5" cols="40">'.$currdisp{'explanation'}.
-                          '</textarea></div><div style=""></div><br />';
-            $datatable .= '<br />';
-            foreach my $extra ('passback','roster') {
-                my $checkedon = '';
-                my $checkedoff = ' checked="checked"';
-                if ($settings->{$item}->{$extra}) {
-                    $checkedon = $checkedoff;
-                    $checkedoff = '';
-                }
-                $datatable .= $lt{$extra}.'&nbsp;'.
-                              '<label><input type="radio" name="ltitools_'.$extra.'_'.$i.'" value="1"'.$checkedon.' />'.
-                              &mt('Yes').'</label>'.('&nbsp;'x2).
-                              '<label><input type="radio" name="ltitools_'.$extra.'_'.$i.'" value="0"'.$checkedoff.' />'.
-                              &mt('No').'</label>'.('&nbsp;'x4);
-            }
-            $datatable .= '<br /><br /><span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;';
+                          '</textarea></div><div style=""></div>'.
+                          '<div style="padding:0;clear:both;margin:0;border:0"></div>';
+            $datatable .= '<span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;';
             if ($imgsrc) {
                 $datatable .= $imgsrc.
                               '<label><input type="checkbox" name="ltitools_image_del"'.
@@ -3935,11 +4084,12 @@ sub print_ltitools {
                 $datatable .= '<input type="file" name="ltitools_image_'.$i.'" value="" />';
             }
             $datatable .= '</span></fieldset>';
-            my (%checkedfields,%rolemaps);
+            my (%checkedfields,%rolemaps,$userincdom);
             if (ref($settings->{$item}) eq 'HASH') {
                 if (ref($settings->{$item}->{'fields'}) eq 'HASH') {
                     %checkedfields = %{$settings->{$item}->{'fields'}};
                 }
+                $userincdom = $settings->{$item}->{'incdom'};
                 if (ref($settings->{$item}->{'roles'}) eq 'HASH') {
                     %rolemaps = %{$settings->{$item}->{'roles'}};
                     $checkedfields{'roles'} = 1;
@@ -3947,16 +4097,40 @@ sub print_ltitools {
             }
             $datatable .= '<fieldset><legend>'.&mt('User data sent on launch').'</legend>'.
                           '<span class="LC_nobreak">';
+            my $userfieldstyle = 'display:none;';
+            my $seluserdom = '';
+            my $unseluserdom = ' selected="selected"';
             foreach my $field (@fields) {
-                my $checked;
+                my ($checked,$onclick,$id,$spacer);
                 if ($checkedfields{$field}) {
                     $checked = ' checked="checked"';
                 }
+                if ($field eq 'user') {
+                    $id = ' id="ltitools_user_field_'.$i.'"';
+                    $onclick = ' onclick="toggleLTITools(this.form,'."'$field','$i'".')"';
+                    if ($checked) {
+                        $userfieldstyle = 'display:inline-block';
+                        if ($userincdom) {
+                            $seluserdom = $unseluserdom;
+                            $unseluserdom = '';
+                        }
+                    }
+                } else {
+                    $spacer = ('&nbsp;' x2);
+                }
                 $datatable .= '<label>'.
-                              '<input type="checkbox" name="ltitools_fields_'.$i.'" value="'.$field.'"'.$checked.' />'.
-                              $lt{$field}.'</label>'.('&nbsp;' x2);
+                              '<input type="checkbox" name="ltitools_fields_'.$i.'" value="'.$field.'"'.$id.$checked.$onclick.' />'.
+                              $lt{$field}.'</label>'.$spacer;
             }
-            $datatable .= '</span></fieldset>'.
+            $datatable .= '</span>';
+            $datatable .= '<div style="'.$userfieldstyle.'" id="ltitools_user_div_'.$i.'">'.
+                          '<span class="LC_nobreak"> : '.
+                          '<select name="ltitools_userincdom_'.$i.'">'.
+                          '<option value="">'.&mt('Select').'</option>'.
+                          '<option value="0"'.$unseluserdom.'>'.&mt('username').'</option>'.
+                          '<option value="1"'.$seluserdom.'>'.&mt('username:domain').'</option>'.
+                          '</select></span></div>';
+            $datatable .= '</fieldset>'.
                           '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';
             foreach my $role (@courseroles) {
                 my ($selected,$selectnone);
@@ -3987,7 +4161,7 @@ sub print_ltitools {
                 }
             }
             $datatable .= '<fieldset><legend>'.&mt('Configurable in course').'</legend><span class="LC_nobreak">';
-            foreach my $item ('label','title','target','linktext','explanation') {
+            foreach my $item ('label','title','target','linktext','explanation','append') {
                 my $checked;
                 if ($courseconfig{$item}) {
                     $checked = ' checked="checked"';
@@ -4020,7 +4194,7 @@ sub print_ltitools {
         }
     }
     $css_class = $itemcount%2?' class="LC_odd_row"':'';
-    my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_add_pos'".');"';
+    my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_add_pos'".');"';
     $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
                   '<input type="hidden" name="ltitools_maxnum" value="'.$maxnum.'" />'."\n".
                   '<select name="ltitools_add_pos"'.$chgstr.'>';
@@ -4033,21 +4207,26 @@ sub print_ltitools {
         $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
     }
     $datatable .= '</select>&nbsp;'."\n".
-                  '<input type="checkbox" name="ltitools_add" value="1" />'.&mt('Add').'</td>'."\n".
+                  '<input type="checkbox" name="ltitools_add" value="1" />'.&mt('Add').'</span></td>'."\n".
                   '<td colspan="2">'.
                   '<fieldset><legend>'.&mt('Required settings').'</legend>'.
-                  '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="30" name="ltitools_add_title" value="" /></span> '."\n".
+                  '<span class="LC_nobreak">'.$lt{'title'}.':<input type="text" size="20" name="ltitools_add_title" value="" /></span> '."\n".
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'version'}.':<select name="ltitools_add_version">'.
                   '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '."\n".
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'msgtype'}.':<select name="ltitools_add_msgtype">'.
                   '<option value="basic-lti-launch-request" selected="selected">Launch</option></select></span> '.
+                  '<span class="LC_nobreak">'.$lt{'sigmethod'}.':<select name="ltitools_add_sigmethod">'.
+                  '<option value="HMAC-SHA1" selected="selected">HMAC-SHA1</option>'.
+                  '<option value="HMAC-SHA256">HMAC-SHA256</option></select></span>'.
                   '<br />'.
-                  '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="30" name="ltitools_add_url" value="" /></span> '."\n".
+                  '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="40" name="ltitools_add_url" value="" /></span> '."\n".
                   ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'key'}.':<input type="text" size="25" name="ltitools_add_key" value="" /></span> '."\n".
                   ('&nbsp;'x2).
+                  '<span class="LC_nobreak">'.$lt{'lifetime'}.':<input type="text" size="5" name="ltitools_add_lifetime" value="300" /></span> '."\n".
+                  ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'secret'}.':<input type="password" size="20" name="ltitools_add_secret" value="" />'.
                   '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.ltitools_add_secret.type='."'text'".' } else { this.form.ltitools_add_secret.type='."'password'".' }" />'.&mt('Visible input').'</label></span> '."\n".
                   '</fieldset>'.
@@ -4065,20 +4244,14 @@ sub print_ltitools {
                       '<input type="text" name="ltitools_add_'.$dimen.'" size="5" /></label>'.
                       ('&nbsp;'x2);
     }
-    $datatable .= '<br />'.
+    $datatable .= '</span><br />'.
                   '<div class="LC_left_float">'.$lt{'linktext'}.'<br />'.
-                  '<input type="text" name="ltitools_add_linktext" size="5" /></label></div>'.
+                  '<input type="text" name="ltitools_add_linktext" size="5" /></div>'.
                   '<div class="LC_left_float">'.$lt{'explanation'}.'<br />'.
-                  '<textarea name=ltitools_add_explanation" rows="5" cols="40"></textarea>'.
-                  '</div><div style=""></div><br />';
-    foreach my $extra ('passback','roster') {
-        $datatable .= $lt{$extra}.'&nbsp;'.
-                      '<label><input type="radio" name="ltitools_add_'.$extra.'" value="1" />'.
-                      &mt('Yes').'</label>'.('&nbsp;'x2).
-                      '<label><input type="radio" name="ltitools_add_'.$extra.'" value="0" checked="checked" />'.
-                      &mt('No').'</label>'.('&nbsp;'x4);
-    }
-    $datatable .= '<br /><br /><span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;'.
+                  '<textarea name="ltitools_add_explanation" rows="5" cols="40"></textarea>'.
+                  '</div><div style=""></div>'.
+                  '<div style="padding:0;clear:both;margin:0;border:0"></div>';
+    $datatable .= '<span class="LC_nobreak">'.$lt{'icon'}.':&nbsp;'.
                   '('.&mt('if larger than 21x21 pixels, image will be scaled').')&nbsp;';
     if ($switchserver) {
         $datatable .= &mt('Upload to library server: [_1]',$switchserver);
@@ -4089,12 +4262,26 @@ sub print_ltitools {
                   '<fieldset><legend>'.&mt('User data sent on launch').'</legend>'.
                   '<span class="LC_nobreak">';
     foreach my $field (@fields) {
+        my ($id,$onclick,$spacer);
+        if ($field eq 'user') {
+            $id = ' id="ltitools_user_field_add"';
+            $onclick = ' onclick="toggleLTITools(this.form,'."'$field','add'".')"';
+        } else {
+            $spacer = ('&nbsp;' x2);
+        }
         $datatable .= '<label>'.
-                      '<input type="checkbox" name="ltitools_add_fields" value="'.$field.'" />'.
-                      $lt{$field}.'</label>'.('&nbsp;' x2);
+                      '<input type="checkbox" name="ltitools_add_fields" value="'.$field.'"'.$id.$onclick.' />'.
+                      $lt{$field}.'</label>'.$spacer;
     }
-    $datatable .= '</span></fieldset>'.
-                  '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';
+    $datatable .= '</span>'.
+                  '<div style="display:none;" id="ltitools_user_div_add">'.
+                  '<span class="LC_nobreak"> : '.
+                  '<select name="ltitools_userincdom_add">'.
+                  '<option value="" selected="selected">'.&mt('Select').'</option>'.
+                  '<option value="0">'.&mt('username').'</option>'.
+                  '<option value="1">'.&mt('username:domain').'</option>'.
+                  '</select></span></div></fieldset>';
+    $datatable .= '<fieldset><legend>'.&mt('Role mapping').'</legend><table><tr>';
     foreach my $role (@courseroles) {
         my ($checked,$checkednone);
         $datatable .= '<td align="center">'.
@@ -4108,7 +4295,7 @@ sub print_ltitools {
     }
     $datatable .= '</tr></table></fieldset>'.
                   '<fieldset><legend>'.&mt('Configurable in course').'</legend><span class="LC_nobreak">';
-    foreach my $item ('label','title','target','linktext','explanation') {
+    foreach my $item ('label','title','target','linktext','explanation','append') {
         $datatable .= '<label>'.
                       '<input type="checkbox" name="ltitools_courseconfig" value="'.$item.'" checked="checked" />'.
                       $lt{'crs'.$item}.'</label>'.('&nbsp;' x2)."\n";
@@ -4120,7 +4307,7 @@ sub print_ltitools {
                   '<label><input type="checkbox" name="ltitools_add_custom" value="1" />'.
                   &mt('Add').'</label></span></td><td><input type="text" name="ltitools_add_custom_name" />'.
                   '</td><td><input type="text" name="ltitools_add_custom_value" /></td></tr>'.
-                  '</table></fieldset></td></tr>'."\n".
+                  '</table></fieldset>'."\n".
                   '</td>'."\n".
                   '</tr>'."\n";
     $itemcount ++;
@@ -4132,11 +4319,13 @@ sub ltitools_names {
                                           'title'          => 'Title',
                                           'version'        => 'Version',
                                           'msgtype'        => 'Message Type',
+                                          'sigmethod'      => 'Signature Method',
                                           'url'            => 'URL',
                                           'key'            => 'Key',
+                                          'lifetime'       => 'Nonce lifetime (s)',
                                           'secret'         => 'Secret',
                                           'icon'           => 'Icon',
-                                          'user'           => 'Username:domain',
+                                          'user'           => 'User',
                                           'fullname'       => 'Full Name',
                                           'firstname'      => 'First Name',
                                           'lastname'       => 'Last Name',
@@ -4149,13 +4338,12 @@ sub ltitools_names {
                                           'width'          => 'Width',
                                           'linktext'       => 'Default Link Text',
                                           'explanation'    => 'Default Explanation',
-                                          'passback'       => 'Tool can return grades:',
-                                          'roster'         => 'Tool can retrieve roster:',
                                           'crstarget'      => 'Display target',
                                           'crslabel'       => 'Course label',
                                           'crstitle'       => 'Course title',
                                           'crslinktext'    => 'Link Text',
                                           'crsexplanation' => 'Explanation',
+                                          'crsappend'      => 'Provider URL',
                                         );
 
     return %lt;
@@ -4227,7 +4415,7 @@ sub print_coursedefaults {
         my $currcanclone = 'none';
         my $onclick;
         my @cloneoptions = ('none','domain');
-        my %clonetitles = (
+        my %clonetitles = &Apache::lonlocal::texthash (
                              none     => 'No additional course requesters',
                              domain   => "Any course requester in course's domain",
                              instcode => 'Course requests for official courses ...',
@@ -4759,7 +4947,7 @@ sub print_passwords {
                 $datatable .= '<span class="LC_nobreak"><label>'.
                               '<input type="checkbox" name="passwords_case_sensitive" value="'.
                               $item.'"'.$checkedcase.' />'.$usertypes->{$item}.'</label>'.
-                              '<span>&nbsp;&nbsp; ';
+                              '</span>&nbsp;&nbsp; ';
             }
         }
         my $checkedcase;
@@ -4863,7 +5051,7 @@ sub print_passwords {
                       &mt('(If you use the same account ...  reset a password from this page.)').'</span><br /><br />'.
                       &mt('Include custom text:');
         if ($customurl) {
-            my $link =  &Apache::loncommon::modal_link($customurl,&mt('Custom text file'),600,500,
+            my $link =  &Apache::loncommon::modal_link($customurl,&mt('custom text'),600,500,
                                                        undef,undef,undef,undef,'background-color:#ffffff');
             $datatable .= '<span class="LC_nobreak">&nbsp;'.$link.
                           '<label><input type="checkbox" name="passwords_custom_del"'.
@@ -5079,7 +5267,7 @@ sub print_passwords {
                     $datatable .= '<span class="LC_nobreak"><label>'.
                                   '<input type="checkbox" name="passwords_crsowner_'.$item.'" value="'.
                                   $type.'"'.$checked.' />'.$usertypes->{$type}.'</label>'.
-                                  '<span>&nbsp;&nbsp; ';
+                                  '</span>&nbsp;&nbsp; ';
                 }
             }
             my $checked;
@@ -5109,13 +5297,18 @@ sub print_usersessions {
     if ($position eq 'top') {
         if (keys(%serverhomes) > 1) {
             my %spareid = &current_offloads_to($dom,$settings,\%servers);
-            my $curroffloadnow;
+            my ($curroffloadnow,$curroffloadoth);
             if (ref($settings) eq 'HASH') {
                 if (ref($settings->{'offloadnow'}) eq 'HASH') {
                     $curroffloadnow = $settings->{'offloadnow'};
                 }
+                if (ref($settings->{'offloadoth'}) eq 'HASH') {
+                    $curroffloadoth = $settings->{'offloadoth'};
+                }
             }
-            $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$curroffloadnow,$rowtotal);
+            my $other_insts = scalar(keys(%by_location));
+            $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,
+                                      $other_insts,$curroffloadnow,$curroffloadoth,$rowtotal);
         } else {
             $datatable .= '<tr'.$css_class.'><td colspan="2">'.
                           &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.');
@@ -5365,7 +5558,8 @@ sub current_offloads_to {
 }
 
 sub spares_row {
-    my ($dom,$servers,$spareid,$serverhomes,$altids,$curroffloadnow,$rowtotal) = @_;
+    my ($dom,$servers,$spareid,$serverhomes,$altids,$other_insts,
+        $curroffloadnow,$curroffloadoth,$rowtotal) = @_;
     my $css_class;
     my $numinrow = 4;
     my $itemcount = 1;
@@ -5385,12 +5579,17 @@ sub spares_row {
                 }
             }
             next unless (ref($spareid->{$server}) eq 'HASH');
-            my $checkednow;
+            my ($checkednow,$checkedoth);
             if (ref($curroffloadnow) eq 'HASH') {
                 if ($curroffloadnow->{$server}) {
                     $checkednow = ' checked="checked"';
                 }
             }
+            if (ref($curroffloadoth) eq 'HASH') {
+                if ($curroffloadoth->{$server}) {
+                    $checkedoth = ' checked="checked"';
+                }
+            }
             $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
             $datatable .= '<tr'.$css_class.'>
                            <td rowspan="2">
@@ -5399,8 +5598,15 @@ sub spares_row {
                               ,'<b>'.$server.'</b>').'</span><br />'.
                           '<span class="LC_nobreak">'."\n".
                           '<label><input type="checkbox" name="offloadnow" value="'.$server.'"'.$checkednow.' />'.
-                          '&nbsp;'.&mt('Switch active users on next access').'</label></span>'.
+                          '&nbsp;'.&mt('Switch any active user on next access').'</label></span>'.
                           "\n";
+            if ($other_insts) {
+                $datatable .= '<br />'.
+                              '<span class="LC_nobreak">'."\n".
+                          '<label><input type="checkbox" name="offloadoth" value="'.$server.'"'.$checkedoth.' />'.
+                          '&nbsp;'.&mt('Switch other institutions on next access').'</label></span>'.
+                          "\n";
+            }
             my (%current,%canselect);
             my @choices = 
                 &possible_newspares($server,$spareid->{$server},$serverhomes,$altids);
@@ -5919,6 +6125,10 @@ sub contact_titles {
                    'updatesmail'     => 'E-mail from nightly check of LON-CAPA module integrity/updates',
                    'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID',
                    'hostipmail'      => 'E-mail from nightly check of hostname/IP network changes',
+                   'errorthreshold'  => 'Error count threshold for status e-mail to admin(s)',
+                   'errorsysmail'    => 'Error count threshold for e-mail to developer group',
+                   'errorweights'    => 'Weights used to compute error count',
+                   'errorexcluded'   => 'Servers with unsent updates excluded from count',
                  );
     my %short_titles = &Apache::lonlocal::texthash (
                            adminemail   => 'Admin E-mail address',
@@ -6961,7 +7171,7 @@ sub print_defaults {
                     $datatable .= '</select>&nbsp;'.&mt('Internal ID:').'&nbsp;<b>'.$item.'</b>&nbsp;'.
                                   '<input type="checkbox" name="inststatus_delete" value="'.$item.'" />'.
                                   &mt('delete').'</span></td>'.
-                                  '<td class="LC_left_item"><span class="LC_nobreak">'.&mt('Name displayed:').
+                                  '<td class="LC_left_item"><span class="LC_nobreak">'.&mt('Name displayed').':'.
                                   '<input type="text" size="20" name="inststatus_title_'.$item.'" value="'.$title.'" />'.
                                   '</span></td></tr>';
                 }
@@ -6981,7 +7191,7 @@ sub print_defaults {
                               '<input type="text" size="10" name="addinststatus" value="" />'.
                               '&nbsp;'.&mt('(new)').
                               '</span></td><td class="LC_left_item"><span class="LC_nobreak">'.
-                              &mt('Name displayed:').
+                              &mt('Name displayed').':'.
                               '<input type="text" size="20" name="addinststatus_title" value="" /></span></td>'.
                               '</tr>'."\n";
                 $rownum ++;
@@ -7830,8 +8040,8 @@ function warnIntPass(field) {
                             alert('$intalert{passnum}');
                         }
                     }
+                    field.value = '';
                 }
-                field.value = '';
             }
         }
     }
@@ -7951,7 +8161,7 @@ ENDSCRIPT
 sub initialize_categories {
     my ($itemcount) = @_;
     my ($datatable,$css_class,$chgstr);
-    my %default_names = (
+    my %default_names = &Apache::lonlocal::texthash (
                       instcode    => 'Official courses (with institutional codes)',
                       communities => 'Communities',
                         );
@@ -7984,7 +8194,7 @@ sub initialize_categories {
                   .'<option value="0">1</option>'
                   .'<option value="1">2</option>'
                   .'<option value="2" selected="selected">3</option></select>&nbsp;'
-                  .&mt('Add category').'</span></td><tda<span class="LC_nobreak">>'.&mt('Name:')
+                  .&mt('Add category').'</span></td><td><span class="LC_nobreak">'.&mt('Name:')
                   .'&nbsp;<input type="text" size="20" name="addcategory_name" value="" /></span>'
                   .'</td></tr>';
     return $datatable;
@@ -10364,8 +10574,11 @@ sub modify_ltitools {
                 $allpos[$position] = $newid;
             }
             $changes{$newid} = 1;
-            foreach my $item ('title','url','key','secret') {
+            foreach my $item ('title','url','key','secret','lifetime') {
                 $env{'form.ltitools_add_'.$item} =~ s/(`)/'/g;
+                if ($item eq 'lifetime') {
+                    $env{'form.ltitools_add_'.$item} =~ s/[^\d.]//g;
+                }
                 if ($env{'form.ltitools_add_'.$item}) {
                     if (($item eq 'key') || ($item eq 'secret')) {
                         $encconfig{$newid}{$item} = $env{'form.ltitools_add_'.$item};
@@ -10380,6 +10593,11 @@ sub modify_ltitools {
             if ($env{'form.ltitools_add_msgtype'} eq 'basic-lti-launch-request') {
                 $confhash{$newid}{'msgtype'} = $env{'form.ltitools_add_msgtype'};
             }
+            if ($env{'form.ltitools_add_sigmethod'} eq 'HMAC-SHA256') {
+                $confhash{$newid}{'sigmethod'} = $env{'form.ltitools_add_sigmethod'};
+            } else {
+                $confhash{$newid}{'sigmethod'} = 'HMAC-SHA1';
+            }
             foreach my $item ('width','height','linktext','explanation') {
                 $env{'form.ltitools_add_'.$item} =~ s/^\s+//;
                 $env{'form.ltitools_add_'.$item} =~ s/\s+$//;
@@ -10400,11 +10618,6 @@ sub modify_ltitools {
             } else {
                 $confhash{$newid}{'display'}{'target'} = 'iframe';
             }
-            foreach my $item ('passback','roster') {
-                if ($env{'form.ltitools_add_'.$item}) {
-                    $confhash{$newid}{$item} = 1;
-                }
-            }
             if ($env{'form.ltitools_add_image.filename'} ne '') {
                 my ($imageurl,$error) =
                     &process_ltitools_image($r,$dom,$confname,'ltitools_add_image',$newid,
@@ -10435,6 +10648,13 @@ sub modify_ltitools {
                     }
                 }
             }
+            if (ref($confhash{$newid}{'fields'}) eq 'HASH') {
+                if ($confhash{$newid}{'fields'}{'user'}) {
+                    if ($env{'form.ltitools_userincdom_add'}) {
+                        $confhash{$newid}{'incdom'} = 1;
+                    }
+                }
+            }
             my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig');
             foreach my $item (@courseconfig) {
                 $confhash{$newid}{'crsconf'}{$item} = 1;
@@ -10481,7 +10701,7 @@ sub modify_ltitools {
                 } else {
                     my $newpos = $env{'form.ltitools_'.$itemid};
                     $newpos =~ s/\D+//g;
-                    foreach my $item ('title','url') {
+                    foreach my $item ('title','url','lifetime') {
                         $confhash{$itemid}{$item} = $env{'form.ltitools_'.$item.'_'.$i};
                         if ($domconfig{$action}{$itemid}{$item} ne $confhash{$itemid}{$item}) {
                             $changes{$itemid} = 1;
@@ -10499,6 +10719,18 @@ sub modify_ltitools {
                     if ($env{'form.ltitools_msgtype_'.$i} eq 'basic-lti-launch-request') {
                         $confhash{$itemid}{'msgtype'} = $env{'form.ltitools_msgtype_'.$i};
                     }
+                    if ($env{'form.ltitools_sigmethod_'.$i} eq 'HMAC-SHA256') {
+                        $confhash{$itemid}{'sigmethod'} = $env{'form.ltitools_sigmethod_'.$i};
+                    } else {
+                        $confhash{$itemid}{'sigmethod'} = 'HMAC-SHA1';
+                    }
+                    if ($domconfig{$action}{$itemid}{'sigmethod'} eq '') {
+                        if ($confhash{$itemid}{'sigmethod'} ne 'HMAC-SHA1') {
+                            $changes{$itemid} = 1;
+                        }
+                    } elsif ($domconfig{$action}{$itemid}{'sigmethod'} ne $confhash{$itemid}{'sigmethod'}) {
+                        $changes{$itemid} = 1;
+                    }
                     foreach my $size ('width','height') {
                         $env{'form.ltitools_'.$size.'_'.$i} =~ s/^\s+//;
                         $env{'form.ltitools_'.$size.'_'.$i} =~ s/\s+$//;
@@ -10549,16 +10781,8 @@ sub modify_ltitools {
                     } else {
                         $changes{$itemid} = 1;
                     }
-                    foreach my $extra ('passback','roster') {
-                        if ($env{'form.ltitools_'.$extra.'_'.$i}) {
-                            $confhash{$itemid}{$extra} = 1;
-                        }
-                        if ($domconfig{$action}{$itemid}{$extra} ne $confhash{$itemid}{$extra}) {
-                            $changes{$itemid} = 1;
-                        }
-                    }
                     my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig_'.$i);
-                    foreach my $item ('label','title','target','linktext','explanation') {
+                    foreach my $item ('label','title','target','linktext','explanation','append') {
                         if (grep(/^\Q$item\E$/,@courseconfig)) {
                             $confhash{$itemid}{'crsconf'}{$item} = 1;
                             if (ref($domconfig{$action}{$itemid}{'crsconf'}) eq 'HASH') {
@@ -10602,6 +10826,16 @@ sub modify_ltitools {
                             }
                         }
                     }
+                    if (ref($confhash{$itemid}{'fields'}) eq 'HASH') {
+                        if ($confhash{$itemid}{'fields'}{'user'}) {
+                            if ($env{'form.ltitools_userincdom_'.$i}) {
+                                $confhash{$itemid}{'incdom'} = 1;
+                            }
+                            if ($domconfig{$action}{$itemid}{'incdom'} ne $confhash{$itemid}{'incdom'}) {
+                                $changes{$itemid} = 1;
+                            }
+                        }
+                    }
                     $allpos[$newpos] = $itemid;
                 }
                 if ($imgdeletions{$itemid}) {
@@ -10735,7 +10969,7 @@ sub modify_ltitools {
                     $resulttext .= '</li><ul>';
                     my $position = $pos + 1;
                     $resulttext .= '<li>'.&mt('Order: [_1]',$position).'</li>';
-                    foreach my $item ('version','msgtype','url') {
+                    foreach my $item ('version','msgtype','sigmethod','url','lifetime') {
                         if ($confhash{$itemid}{$item} ne '') {
                             $resulttext .= '<li>'.$lt{$item}.':&nbsp;'.$confhash{$itemid}{$item}.'</li>';
                         }
@@ -10749,7 +10983,7 @@ sub modify_ltitools {
                         $resulttext .= ('*'x$num).'</li>';
                     }
                     $resulttext .= '<li>'.&mt('Configurable in course:');
-                    my @possconfig = ('label','title','target','linktext','explanation');
+                    my @possconfig = ('label','title','target','linktext','explanation','append');
                     my $numconfig = 0;
                     if (ref($confhash{$itemid}{'crsconf'}) eq 'HASH') {
                         foreach my $item (@possconfig) {
@@ -10763,15 +10997,6 @@ sub modify_ltitools {
                         $resulttext .= &mt('None');
                     }
                     $resulttext .= '</li>';
-                    foreach my $item ('passback','roster') {
-                        $resulttext .= '<li>'.$lt{$item}.'&nbsp;';
-                        if ($confhash{$itemid}{$item}) {
-                            $resulttext .= &mt('Yes');
-                        } else {
-                            $resulttext .= &mt('No');
-                        }
-                        $resulttext .= '</li>';
-                    }
                     if (ref($confhash{$itemid}{'display'}) eq 'HASH') {
                         my $displaylist;
                         if ($confhash{$itemid}{'display'}{'target'}) {
@@ -10803,6 +11028,13 @@ sub modify_ltitools {
                         }
                         if ($fieldlist) {
                             $fieldlist =~ s/,$//;
+                            if ($confhash{$itemid}{'fields'}{'user'}) {
+                                if ($confhash{$itemid}{'incdom'}) {
+                                    $fieldlist .= ' ('.&mt('username:domain').')';
+                                } else {
+                                    $fieldlist .= ' ('.&mt('username').')';
+                                }
+                            }
                             $resulttext .= '<li>'.&mt('Data sent').':'.$fieldlist.'</li>';
                         }
                     }
@@ -10827,7 +11059,7 @@ sub modify_ltitools {
                             }
                         }
                         if ($customlist) {
-                            $resulttext .= '<li>'.&mt('Custom items').':'.$customlist.'</li>';
+                            $resulttext .= '<li>'.&mt('Custom items').': '.$customlist.'</li>';
                         }
                     }
                     $resulttext .= '</ul></li>';
@@ -11509,7 +11741,8 @@ sub modify_contacts {
     my @contacts = ('supportemail','adminemail');
     my @mailings = ('errormail','packagesmail','helpdeskmail','otherdomsmail',
                     'lonstatusmail','requestsmail','updatesmail','idconflictsmail','hostipmail');
-    my @toggles = ('reporterrors','reportupdates');
+    my @toggles = ('reporterrors','reportupdates','reportstatus');
+    my @lonstatus = ('threshold','sysmail','weights','excluded');
     my ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();
     foreach my $type (@mailings) {
         @{$newsetting{$type}} = 
@@ -11542,6 +11775,41 @@ sub modify_contacts {
             $contacts_hash{'contacts'}{$item} = $env{'form.'.$item};
         }
     }
+    my ($lonstatus_defs,$lonstatus_names) = &Apache::loncommon::lon_status_items();
+    foreach my $item (@lonstatus) {
+        if ($item eq 'excluded') {
+            my (%serverhomes,@excluded);
+            map { $serverhomes{$_} = 1; } values(%Apache::lonnet::serverhomeIDs);
+            my @possexcluded = &Apache::loncommon::get_env_multiple('form.errorexcluded');
+            if (@possexcluded) {
+                foreach my $id (sort(@possexcluded)) {
+                    if ($serverhomes{$id}) {
+                        push(@excluded,$id);
+                    }
+                }
+            }
+            if (@excluded) {
+                $contacts_hash{'contacts'}{'lonstatus'}{$item} = \@excluded;
+            }
+        } elsif ($item eq 'weights') {
+            foreach my $type ('E','W','N','U') {
+                $env{'form.error'.$item.'_'.$type} =~ s/^\s+|\s+$//g;
+                if ($env{'form.error'.$item.'_'.$type} =~ /^\d+$/) {
+                    unless ($env{'form.error'.$item.'_'.$type} == $lonstatus_defs->{$type}) {
+                        $contacts_hash{'contacts'}{'lonstatus'}{$item}{$type} =
+                            $env{'form.error'.$item.'_'.$type};
+                    }
+                }
+            }
+        } elsif (($item eq 'threshold') || ($item eq 'sysmail')) {
+            $env{'form.error'.$item} =~ s/^\s+|\s+$//g;
+            if ($env{'form.error'.$item} =~ /^\d+$/) {
+                unless ($env{'form.error'.$item} == $lonstatus_defs->{$item}) {
+                    $contacts_hash{'contacts'}{'lonstatus'}{$item} = $env{'form.error'.$item};
+                }
+            }
+        }
+    }
     if ((ref($fields) eq 'ARRAY') && (ref($possoptions) eq 'HASH')) {
         foreach my $field (@{$fields}) {
             if (ref($possoptions->{$field}) eq 'ARRAY') {
@@ -11680,6 +11948,76 @@ sub modify_contacts {
                 }
             }
         }
+        if (ref($currsetting{'lonstatus'}) eq 'HASH') {
+            foreach my $key ('excluded','weights','threshold','sysmail') {
+                if ($key eq 'excluded') {
+                    if ((ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') &&
+                        (ref($contacts_hash{contacts}{lonstatus}{excluded}) eq 'ARRAY')) {
+                        if ((ref($currsetting{'lonstatus'}{$key}) eq 'ARRAY') &&
+                            (@{$currsetting{'lonstatus'}{$key}})) {
+                            my @diffs =
+                                &Apache::loncommon::compare_arrays($contacts_hash{contacts}{lonstatus}{excluded},
+                                                                   $currsetting{'lonstatus'}{$key});
+                            if (@diffs) {
+                                push(@{$changes{'lonstatus'}},$key);
+                            }
+                        } elsif (@{$contacts_hash{contacts}{lonstatus}{excluded}}) {
+                            push(@{$changes{'lonstatus'}},$key);
+                        }
+                    } elsif ((ref($currsetting{'lonstatus'}{$key}) eq 'ARRAY') &&
+                             (@{$currsetting{'lonstatus'}{$key}})) {
+                        push(@{$changes{'lonstatus'}},$key);
+                    }
+                } elsif ($key eq 'weights') {
+                    if ((ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') &&
+                        (ref($contacts_hash{contacts}{lonstatus}{$key}) eq 'HASH')) {
+                        if (ref($currsetting{'lonstatus'}{$key}) eq 'HASH') {
+                            foreach my $type ('E','W','N','U') {
+                                unless ($contacts_hash{contacts}{lonstatus}{$key}{$type} eq
+                                        $currsetting{'lonstatus'}{$key}{$type}) {
+                                    push(@{$changes{'lonstatus'}},$key);
+                                    last;
+                                }
+                            }
+                        } else {
+                            foreach my $type ('E','W','N','U') {
+                                if ($contacts_hash{contacts}{lonstatus}{$key}{$type} ne '') {
+                                    push(@{$changes{'lonstatus'}},$key);
+                                    last;
+                                }
+                            }
+                        }
+                    } elsif (ref($currsetting{'lonstatus'}{$key}) eq 'HASH') {
+                        foreach my $type ('E','W','N','U') {
+                            if ($currsetting{'lonstatus'}{$key}{$type} ne '') {
+                                push(@{$changes{'lonstatus'}},$key);
+                                last;
+                            }
+                        }
+                    }
+                } elsif (($key eq 'threshold') || ($key eq 'sysmail')) {
+                    if (ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') {
+                        if ($currsetting{'lonstatus'}{$key} =~ /^\d+$/) {
+                            if ($currsetting{'lonstatus'}{$key} != $contacts_hash{contacts}{lonstatus}{$key}) {
+                                push(@{$changes{'lonstatus'}},$key);
+                            }
+                        } elsif ($contacts_hash{contacts}{lonstatus}{$key} =~ /^\d+$/) {
+                            push(@{$changes{'lonstatus'}},$key);
+                        }
+                    } elsif ($currsetting{'lonstatus'}{$key} =~ /^\d+$/) {
+                        push(@{$changes{'lonstatus'}},$key);
+                    }
+                }
+            }
+        } else {
+            if (ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') {
+                foreach my $key ('excluded','weights','threshold','sysmail') {
+                    if (exists($contacts_hash{contacts}{lonstatus}{$key})) {
+                        push(@{$changes{'lonstatus'}},$key);
+                    }
+                }
+            }
+        }
     } else {
         my %default;
         $default{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};
@@ -11725,6 +12063,13 @@ sub modify_contacts {
                 }
             }
         }
+        if (ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') {
+            foreach my $key ('excluded','weights','threshold','sysmail') {
+                if (exists($contacts_hash{contacts}{lonstatus}{$key})) {
+                    push(@{$changes{'lonstatus'}},$key);
+                }
+            }
+        }
     }
     foreach my $item (@toggles) {
         if (($env{'form.'.$item} == 1) && ($currsetting{$item} == 0)) {
@@ -11850,22 +12195,79 @@ sub modify_contacts {
                 }
             }
             my @offon = ('off','on');
+            my $corelink = &core_link_msu();
             if ($changes{'reporterrors'}) {
                 $resulttext .= '<li>'.
                                &mt('E-mail error reports to [_1] set to "'.
                                    $offon[$env{'form.reporterrors'}].'".',
-                                   &Apache::loncommon::modal_link('http://loncapa.org/core.html',
-                                       &mt('LON-CAPA core group - MSU'),600,500)).
+                                   $corelink).
                                '</li>';
             }
             if ($changes{'reportupdates'}) {
                 $resulttext .= '<li>'.
                                 &mt('E-mail record of completed LON-CAPA updates to [_1] set to "'.
                                     $offon[$env{'form.reportupdates'}].'".',
-                                    &Apache::loncommon::modal_link('http://loncapa.org/core.html',
-                                        &mt('LON-CAPA core group - MSU'),600,500)).
+                                    $corelink).
                                 '</li>';
             }
+            if ($changes{'reportstatus'}) {
+                $resulttext .= '<li>'.
+                                &mt('E-mail status if errors above threshold to [_1] set to "'.
+                                    $offon[$env{'form.reportstatus'}].'".',
+                                    $corelink).
+                                '</li>';
+            }
+            if (ref($changes{'lonstatus'}) eq 'ARRAY') {
+                $resulttext .= '<li>'.
+                               &mt('Nightly status check e-mail settings').':<ul>';
+                my (%defval,%use_def,%shown);
+                $defval{'threshold'} = $lonstatus_defs->{'threshold'};
+                $defval{'sysmail'} = $lonstatus_defs->{'sysmail'};
+                $defval{'weights'} =
+                    join(', ',map { $lonstatus_names->{$_}.'='.$lonstatus_defs->{$_}; } ('E','W','N','U'));
+                $defval{'excluded'} = &mt('None');
+                if (ref($contacts_hash{'contacts'}{'lonstatus'}) eq 'HASH') {
+                    foreach my $item ('threshold','sysmail','weights','excluded') {
+                        if (exists($contacts_hash{'contacts'}{'lonstatus'}{$item})) {
+                            if (($item eq 'threshold') || ($item eq 'sysmail')) {
+                                $shown{$item} = $contacts_hash{'contacts'}{'lonstatus'}{$item};
+                            } elsif ($item eq 'weights') {
+                                if (ref($contacts_hash{'contacts'}{'lonstatus'}{$item}) eq 'HASH') {
+                                    foreach my $type ('E','W','N','U') {
+                                        $shown{$item} .= $lonstatus_names->{$type}.'=';
+                                        if (exists($contacts_hash{'contacts'}{'lonstatus'}{$item}{$type})) {
+                                            $shown{$item} .= $contacts_hash{'contacts'}{'lonstatus'}{$item}{$type};
+                                        } else {
+                                            $shown{$item} .= $lonstatus_defs->{$type};
+                                        }
+                                        $shown{$item} .= ', ';
+                                    }
+                                    $shown{$item} =~ s/, $//;
+                                } else {
+                                    $shown{$item} = $defval{$item};
+                                }
+                            } elsif ($item eq 'excluded') {
+                                if (ref($contacts_hash{'contacts'}{'lonstatus'}{$item}) eq 'ARRAY') {
+                                    $shown{$item} = join(', ',@{$contacts_hash{'contacts'}{'lonstatus'}{$item}});
+                                } else {
+                                    $shown{$item} = $defval{$item};
+                                }
+                            }
+                        } else {
+                            $shown{$item} = $defval{$item};
+                        }
+                    }
+                } else {
+                    foreach my $item ('threshold','weights','excluded','sysmail') {
+                        $shown{$item} = $defval{$item};
+                    }
+                }
+                foreach my $item ('threshold','weights','excluded','sysmail') {
+                    $resulttext .= '<li>'.&mt($titles->{'error'.$item}.' -- [_1]',
+                                          $shown{$item}).'</li>';
+                }
+                $resulttext .= '</ul></li>';
+            }
             if ((ref($changes{'helpform'}) eq 'ARRAY') && (ref($fields) eq 'ARRAY')) {
                 my (@optional,@required,@unused,$maxsizechg);
                 foreach my $field (@{$changes{'helpform'}}) {
@@ -12174,6 +12576,8 @@ sub modify_passwords {
                 if ($staticdefaults{$rule} ne $newvalues{$rule}) {
                     $changes{'rules'} = 1;
                 }
+            } else {
+                $changes{'rules'} = 1;
             }
         } elsif (exists($current{$rule})) {
             $changes{'rules'} = 1;
@@ -12252,9 +12656,11 @@ sub modify_passwords {
                             $resulttext .= '<li>'.&mt('CAPTCHA validation set to use: original CAPTCHA').'</li>';
                         } elsif ($confighash{'passwords'}{'captcha'} eq 'recaptcha') {
                             $resulttext .= '<li>'.&mt('CAPTCHA validation set to use: reCAPTCHA').' '.
-                                           &mt('version: [_1]',$confighash{'passwords'}{'recaptchaversion'}).'<br />'.
-                                           &mt('Public key: [_1]',$confighash{'passwords'}{'recaptchapub'}).'</br>'.
-                                           &mt('Private key: [_1]',$confighash{'passwords'}{'recaptchapriv'}).'</li>';
+                                           &mt('version: [_1]',$confighash{'passwords'}{'recaptchaversion'}).'<br />';
+                            if (ref($confighash{'passwords'}{'recaptchakeys'}) eq 'HASH') {
+                                $resulttext .= &mt('Public key: [_1]',$confighash{'passwords'}{'recaptchakeys'}{'public'}).'</br>'.
+                                               &mt('Private key: [_1]',$confighash{'passwords'}{'recaptchakeys'}{'private'}).'</li>';
+                            }
                         } else {
                             $resulttext .= '<li>'.&mt('No CAPTCHA validation').'</li>';
                         }
@@ -12324,7 +12730,7 @@ sub modify_passwords {
                                 $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';
                             }
                         } else {
-                            $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA usedfor verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';
+                            $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';
                         }
                         if ($confighash{'passwords'}{'resetremove'}) {
                             $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" web form not shown').'</li>';
@@ -12333,8 +12739,9 @@ sub modify_passwords {
                         }
                         if ($confighash{'passwords'}{'resetcustom'}) {
                             my $customlink = &Apache::loncommon::modal_link($confighash{'passwords'}{'resetcustom'},
-                                                                            $titles{custom},600,500);
-                            $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" form includes [_1]',$customlink).'</li>';
+                                                                            &mt('custom text'),600,500,undef,undef,
+                                                                            undef,undef,'background-color:#ffffff');
+                            $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" form includes: [_1]',$customlink).'</li>';
                         } else {
                             $resulttext .= '<li>'.&mt('No custom text included in preamble to "Forgot Password" form').'</li>';
                         }
@@ -12380,6 +12787,24 @@ sub modify_passwords {
                                 $resulttext .= '<li>'.&mt('[_1] set to [_2]',$titles{$rule},$confighash{'passwords'}{$rule}).'</li>';
                             }
                         }
+                        if (ref($confighash{'passwords'}{'chars'}) eq 'ARRAY') {
+                            if (@{$confighash{'passwords'}{'chars'}} > 0) {
+                                my %rulenames = &Apache::lonlocal::texthash(
+                                                     uc => 'At least one upper case letter',
+                                                     lc => 'At least one lower case letter',
+                                                     num => 'At least one number',
+                                                     spec => 'At least one non-alphanumeric',
+                                                   );
+                                my $needed = '<ul><li>'.
+                                             join('</li><li>',map {$rulenames{$_} } @{$confighash{'passwords'}{'chars'}}).
+                                             '</li></ul>';
+                                $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$titles{'chars'},$needed).'</li>';
+                            } else {
+                                $resulttext .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';
+                            }
+                        } else {
+                            $resulttext .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';
+                        }
                     } elsif ($key eq 'crsownerchg') {
                         if (ref($confighash{'passwords'}{'crsownerchg'}) eq 'HASH') {
                             if ((@{$confighash{'passwords'}{'crsownerchg'}{'by'}} == 0) ||
@@ -13520,13 +13945,17 @@ sub modify_selfcreation {
 }
 
 sub process_captcha {
-    my ($container,$changes,$newsettings,$current) = @_;
-    return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH') || (ref($current) eq 'HASH'));
+    my ($container,$changes,$newsettings,$currsettings) = @_;
+    return unless ((ref($changes) eq 'HASH') && (ref($newsettings) 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'}) {
+    my %current;
+    if (ref($currsettings) eq 'HASH') {
+        %current = %{$currsettings};
+    }
+    if ($current{'captcha'} ne $newsettings->{'captcha'}) {
         if ($container eq 'cancreate') {
             if (ref($changes->{'cancreate'}) eq 'ARRAY') {
                 push(@{$changes->{'cancreate'}},'captcha');
@@ -13556,9 +13985,9 @@ sub process_captcha {
         }
         $newsettings->{'recaptchaversion'} = $newversion;
     }
-    if (ref($current->{'recaptchakeys'}) eq 'HASH') {
-        $currpub = $current->{'recaptchakeys'}{'public'};
-        $currpriv = $current->{'recaptchakeys'}{'private'};
+    if (ref($current{'recaptchakeys'}) eq 'HASH') {
+        $currpub = $current{'recaptchakeys'}{'public'};
+        $currpriv = $current{'recaptchakeys'}{'private'};
         unless ($newsettings->{'captcha'} eq 'recaptcha') {
             $newsettings->{'recaptchakeys'} = {
                                                  public  => '',
@@ -13566,8 +13995,8 @@ sub process_captcha {
                                               }
         }
     }
-    if ($current->{'captcha'} eq 'recaptcha') {
-        $currversion = $current->{'recaptchaversion'};
+    if ($current{'captcha'} eq 'recaptcha') {
+        $currversion = $current{'recaptchaversion'};
         if ($currversion ne '2') {
             $currversion = 1;
         }
@@ -15634,6 +16063,7 @@ sub modify_usersessions {
         }
     }
     $defaultshash{'usersessions'}{'offloadnow'} = {};
+    $defaultshash{'usersessions'}{'offloadoth'} = {};
     my @offloadnow = &Apache::loncommon::get_env_multiple('form.offloadnow');
     my @okoffload;
     if (@offloadnow) {
@@ -15650,6 +16080,22 @@ sub modify_usersessions {
             }
         }
     }
+    my @offloadoth = &Apache::loncommon::get_env_multiple('form.offloadoth');
+    my @okoffloadoth;
+    if (@offloadoth) {
+        foreach my $server (@offloadoth) {
+            if (&Apache::lonnet::hostname($server) ne '') {
+                unless (grep(/^\Q$server\E$/,@okoffloadoth)) {
+                    push(@okoffloadoth,$server);
+                }
+            }
+        }
+        if (@okoffloadoth) {
+            foreach my $lonhost (@okoffloadoth) {
+                $defaultshash{'usersessions'}{'offloadoth'}{$lonhost} = 1;
+            }
+        }
+    }
     if (ref($domconfig{'usersessions'}) eq 'HASH') {
         if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') {
             if (ref($changes{'spares'}) eq 'HASH') {
@@ -15660,26 +16106,38 @@ sub modify_usersessions {
         } else {
             $savespares = 1;
         }
-        if (ref($domconfig{'usersessions'}{'offloadnow'}) eq 'HASH') {
-            foreach my $lonhost (keys(%{$domconfig{'usersessions'}{'offloadnow'}})) {
-                unless ($defaultshash{'usersessions'}{'offloadnow'}{$lonhost}) {
-                    $changes{'offloadnow'} = 1;
-                    last;
-                }
-            }
-            unless ($changes{'offloadnow'}) {
-                foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{'offloadnow'}})) {
-                    unless ($domconfig{'usersessions'}{'offloadnow'}{$lonhost}) {
-                        $changes{'offloadnow'} = 1;
+        foreach my $offload ('offloadnow','offloadoth') {
+            if (ref($domconfig{'usersessions'}{$offload}) eq 'HASH') {
+                foreach my $lonhost (keys(%{$domconfig{'usersessions'}{$offload}})) {
+                    unless ($defaultshash{'usersessions'}{$offload}{$lonhost}) {
+                        $changes{$offload} = 1;
                         last;
                     }
                 }
+                unless ($changes{$offload}) {
+                    foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{$offload}})) {
+                        unless ($domconfig{'usersessions'}{$offload}{$lonhost}) {
+                            $changes{$offload} = 1;
+                            last;
+                        }
+                    }
+                }
+            } else {
+                if (($offload eq 'offloadnow') && (@okoffload)) {
+                     $changes{'offloadnow'} = 1;
+                }
+                if (($offload eq 'offloadoth') && (@okoffloadoth)) {
+                    $changes{'offloadoth'} = 1;
+                }
             }
-        } elsif (@okoffload) {
+        }
+    } else {
+        if (@okoffload) {
             $changes{'offloadnow'} = 1;
         }
-    } elsif (@okoffload) {
-        $changes{'offloadnow'} = 1;
+        if (@okoffloadoth) {
+            $changes{'offloadoth'} = 1;
+        }
     }
     my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');
     if ((keys(%changes) > 0) || ($savespares)) {
@@ -15696,6 +16154,9 @@ sub modify_usersessions {
                 if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
                     $domdefaults{'offloadnow'} = $defaultshash{'usersessions'}{'offloadnow'};
                 }
+                if (ref($defaultshash{'usersessions'}{'offloadoth'}) eq 'HASH') {
+                    $domdefaults{'offloadoth'} = $defaultshash{'usersessions'}{'offloadoth'};
+                }
             }
             my $cachetime = 24*60*60;
             &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
@@ -15769,16 +16230,31 @@ sub modify_usersessions {
                 if ($changes{'offloadnow'}) {
                     if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
                         if (keys(%{$defaultshash{'usersessions'}{'offloadnow'}}) > 0) {
-                            $resulttext .= '<li>'.&mt('Switch active users on next access, for server(s):').'<ul>';
+                            $resulttext .= '<li>'.&mt('Switch any active user on next access, for server(s):').'<ul>';
                             foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadnow'}}))) {
                                 $resulttext .= '<li>'.$lonhost.'</li>';
                             }
                             $resulttext .= '</ul>';
                         } else {
-                            $resulttext .= '<li>'.&mt('No servers now set to switch active users on next access.');
+                            $resulttext .= '<li>'.&mt('No servers now set to switch any active user on next access.');
                         }
                     } else {
-                        $resulttext .= '<li>'.&mt('No servers now set to switch active users on next access.').'</li>';
+                        $resulttext .= '<li>'.&mt('No servers now set to switch any active user on next access.').'</li>';
+                    }
+                }
+                if ($changes{'offloadoth'}) {
+                    if (ref($defaultshash{'usersessions'}{'offloadoth'}) eq 'HASH') {
+                        if (keys(%{$defaultshash{'usersessions'}{'offloadoth'}}) > 0) {
+                            $resulttext .= '<li>'.&mt('Switch other institutions on next access, for server(s):').'<ul>';
+                            foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadoth'}}))) {
+                                $resulttext .= '<li>'.$lonhost.'</li>';
+                            }
+                            $resulttext .= '</ul>';
+                        } else {
+                            $resulttext .= '<li>'.&mt('No servers now set to switch other institutions on next access.');
+                        }
+                    } else {
+                        $resulttext .= '<li>'.&mt('No servers now set to switch other institutions on next access.').'</li>';
                     }
                 }
                 $resulttext .= '</ul>';
@@ -16032,24 +16508,24 @@ sub modify_loadbalancing {
                             $resulttext .= '<li>'.&mt('Load Balancer: [_1] -- cookie use enabled',
                                                       $balancer).'</li>';
                         }
-                        if (keys(%toupdate)) {
-                            my %thismachine;
-                            my $updatedhere;
-                            my $cachetime = 60*60*24;
-                            map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
-                            foreach my $lonhost (keys(%toupdate)) {
-                                if ($thismachine{$lonhost}) {
-                                    unless ($updatedhere) {
-                                        &Apache::lonnet::do_cache_new('loadbalancing',$dom,
-                                                                      $defaultshash{'loadbalancing'},
-                                                                      $cachetime);
-                                        $updatedhere = 1;
-                                    }
-                                } else {
-                                    my $cachekey = &escape('loadbalancing').':'.&escape($dom);
-                                    &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
-                                }
+                    }
+                }
+                if (keys(%toupdate)) {
+                    my %thismachine;
+                    my $updatedhere;
+                    my $cachetime = 60*60*24;
+                    map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
+                    foreach my $lonhost (keys(%toupdate)) {
+                        if ($thismachine{$lonhost}) {
+                            unless ($updatedhere) {
+                                &Apache::lonnet::do_cache_new('loadbalancing',$dom,
+                                                              $defaultshash{'loadbalancing'},
+                                                              $cachetime);
+                                $updatedhere = 1;
                             }
+                        } else {
+                            my $cachekey = &escape('loadbalancing').':'.&escape($dom);
+                            &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
                         }
                     }
                 }