--- loncom/interface/domainprefs.pm	2017/06/22 02:11:25	1.160.6.84.2.1
+++ loncom/interface/domainprefs.pm	2017/07/18 16:03:08	1.302
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set domain-wide configuration settings
 #
-# $Id: domainprefs.pm,v 1.160.6.84.2.1 2017/06/22 02:11:25 raeburn Exp $
+# $Id: domainprefs.pm,v 1.302 2017/07/18 16:03:08 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -104,8 +104,8 @@ $datatable  - HTML containing form eleme
 
 In the case of course requests, radio buttons are displayed for each institutional
 affiliate type (and also default, and _LC_adv) for each of the course types 
-(official, unofficial, community, and textbook).  In each case the radio buttons 
-allow the selection of one of four values:
+(official, unofficial, community, textbook, and placement).  
+In each case the radio buttons allow the selection of one of four values:  
 
 0, approval, validate, autolimit=N (where N is blank, or a positive integer).
 which have the following effects:
@@ -170,10 +170,12 @@ use Apache::loncoursequeueadmin();
 use LONCAPA qw(:DEFAULT :match);
 use LONCAPA::Enrollment;
 use LONCAPA::lonauthcgi();
+use LONCAPA::SSL;
 use File::Copy;
 use Locale::Language;
 use DateTime::TimeZone;
 use DateTime::Locale;
+use Time::HiRes qw( sleep );
 
 my $registered_cleanup;
 my $modified_urls;
@@ -217,7 +219,7 @@ sub handler {
                 'serverstatuses','requestcourses','helpsettings',
                 'coursedefaults','usersessions','loadbalancing',
                 'requestauthor','selfenrollment','inststatus',
-                'ltitools'],$dom);
+                'ltitools','ssl','trust'],$dom);
     if (ref($domconfig{'ltitools'}) eq 'HASH') {
         my %encconfig =
             &Apache::lonnet::get_dom('encconfig',['ltitools'],$dom);
@@ -236,7 +238,7 @@ sub handler {
                        'usercreation','selfcreation','usermodification','scantron',
                        'requestcourses','requestauthor','coursecategories',
                        'serverstatuses','helpsettings','coursedefaults',
-                       'ltitools','selfenrollment','usersessions');
+                       'ltitools','selfenrollment','usersessions','ssl','trust');
     my %existing;
     if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
         %existing = %{$domconfig{'loadbalancing'}};
@@ -466,6 +468,14 @@ sub handler {
                   print => \&print_selfenrollment,
                   modify => \&modify_selfenrollment,
                  },
+        'privacy' => 
+                 {text   => 'User Privacy',
+                  help   => 'Domain_Configuration_User_Privacy',
+                  header => [{col1 => 'Setting',
+                              col2 => 'Value',}],
+                  print => \&print_privacy,
+                  modify => \&modify_privacy,
+                 },
         'usersessions' =>
                  {text  => 'User session hosting/offloading',
                   help  => 'Domain_Configuration_User_Sessions',
@@ -489,7 +499,7 @@ sub handler {
                   print => \&print_loadbalancing,
                   modify => \&modify_loadbalancing,
                  },
-        'ltitools' =>
+        'ltitools' => 
                  {text => 'External Tools (LTI)',
                   help => 'Domain_Configuration_LTI_Tools',
                   header => [{col1 => 'Setting',
@@ -497,6 +507,44 @@ sub handler {
                   print => \&print_ltitools,
                   modify => \&modify_ltitools,
                  },
+        'ssl' =>
+                 {text  => 'LON-CAPA Network (SSL)',
+                  help  => 'Domain_Configuration_Network_SSL',
+                  header => [{col1 => 'Server',
+                              col2 => 'Certificate Status'},
+                             {col1 => 'Connections to other servers',
+                              col2 => 'Rules'},
+                             {col1 => 'Connections from other servers',
+                              col2 => 'Rules'},
+                             {col1 => "Replicating domain's published content",
+                              col2 => 'Rules'}],
+                  print => \&print_ssl,
+                  modify => \&modify_ssl,
+                 },
+        'trust' =>
+                 {text   => 'Trust Settings',
+                  help   => 'Domain_Configuration_Trust',
+                  header => [{col1 => "Access to this domain's content by others",
+                              col2 => 'Rules'},
+                             {col1 => "Access to other domain's content by this domain",
+                              col2 => 'Rules'},
+                             {col1 => "Enrollment in this domain's courses by others",
+                              col2 => 'Rules',},
+                             {col1 => "Co-author roles in this domain for others",
+                              col2 => 'Rules',},
+                             {col1 => "Co-author roles for this domain's users elsewhere",
+                              col2 => 'Rules',},
+                             {col1 => "Domain roles in this domain assignable to others",
+                              col2 => 'Rules'},
+                             {col1 => "Course catalog for this domain displayed elsewhere",
+                              col2 => 'Rules'},
+                             {col1 => "Requests for creation of courses in this domain by others",
+                              col2 => 'Rules'},
+                             {col1 => "Users in other domains can send messages to this domain",
+                              col2 => 'Rules'},],
+                  print => \&print_trust,
+                  modify => \&modify_trust,
+                 },
     );
     if (keys(%servers) > 1) {
         $prefs{'login'}  = { text   => 'Log-in page options',
@@ -675,6 +723,10 @@ sub process_changes {
         $output = &modify_loadbalancing($dom,%domconfig);
     } elsif ($action eq 'ltitools') {
         $output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig);
+    } elsif ($action eq 'ssl') {
+        $output = &modify_ssl($dom,$lastactref,%domconfig);
+    } elsif ($action eq 'trust') {
+        $output = &modify_trust($dom,$lastactref,%domconfig);
     }
     return $output;
 }
@@ -701,7 +753,7 @@ sub print_config_box {
         &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
         my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
         $output =
-            &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full,
+            &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full, 
                                                       \@templateroles);
     }
     $output .=
@@ -738,8 +790,9 @@ sub print_config_box {
         $rowtotal ++;
         if (($action eq 'autoupdate') || ($action eq 'usercreation') || ($action eq 'selfcreation') ||
             ($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') ||
-            ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'directorysrch') ||
-            ($action eq 'helpsettings') || ($action eq 'contacts')) {
+            ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'ssl') ||
+            ($action eq 'directorysrch') || ($action eq 'trust') || ($action eq 'helpsettings') ||
+            ($action eq 'contacts')) {
             $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'coursecategories') {
             $output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal);
@@ -769,15 +822,46 @@ sub print_config_box {
             $rowtotal ++;
         if (($action eq 'autoupdate') || ($action eq 'usercreation') ||
             ($action eq 'selfcreation') || ($action eq 'selfenrollment') ||
-            ($action eq 'usersessions') || ($action eq 'coursecategories') ||
-            ($action eq 'contacts') || ($action eq 'defaults')) {
+            ($action eq 'usersessions') || ($action eq 'coursecategories') || 
+            ($action eq 'trust') || ($action eq 'contacts') || ($action eq 'defaults')) {
             if ($action eq 'coursecategories') {
                 $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);
                 $colspan = ' colspan="2"';
+            } elsif ($action eq 'trust') {
+                $output .= $item->{'print'}->('shared',$dom,$settings,\$rowtotal);
             } else {
                 $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);
             }
-            $output .= '
+            if ($action eq 'trust') {
+                $output .= '
+            </table>
+          </td>
+         </tr>';
+                my @trusthdrs = qw(2 3 4 5 6 7);
+                my @prefixes = qw(enroll othcoau coaurem domroles catalog reqcrs);
+                for (my $i=0; $i<@trusthdrs; $i++) {
+                    $output .= '
+         <tr>
+           <td>
+            <table class="LC_nested">
+             <tr class="LC_info_row">
+              <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[$trusthdrs[$i]]->{'col1'}).'</td>
+              <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[$trusthdrs[$i]]->{'col2'}).'</td></tr>'.
+                           $item->{'print'}->($prefixes[$i],$dom,$settings,\$rowtotal).'
+            </table>
+          </td>
+         </tr>';
+                }
+                $output .= '
+         <tr>
+           <td>
+            <table class="LC_nested">
+             <tr class="LC_info_row">
+              <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[8]->{'col1'}).'</td>
+              <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[8]->{'col2'}).'</td></tr>'.
+                           $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
+            } else {
+                $output .= '
            </table>
           </td>
          </tr>
@@ -788,16 +872,39 @@ sub print_config_box {
               <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
               <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
              </tr>'."\n";
-            if ($action eq 'coursecategories') {
-                $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
-            } else {
-                $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
+                if ($action eq 'coursecategories') {
+                    $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
+                } else {
+                    $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
+                }
             }
             $rowtotal ++;
         } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||
                  ($action eq 'defaults') || ($action eq 'directorysrch') ||
                  ($action eq 'helpsettings')) {
             $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
+        } elsif ($action eq 'ssl') {
+            $output .= $item->{'print'}->('connto',$dom,$settings,\$rowtotal).'
+            </table>
+          </td>
+         </tr>
+         <tr>
+           <td>
+            <table class="LC_nested">
+             <tr class="LC_info_row">
+              <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
+              <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td></tr>'.
+                           $item->{'print'}->('connfrom',$dom,$settings,\$rowtotal).'
+            </table>
+          </td>
+         </tr>
+         <tr>
+           <td>
+            <table class="LC_nested">
+             <tr class="LC_info_row">
+              <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
+              <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td></tr>'.
+                           $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'login') {
             if ($numheaders == 4) {
                 $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'
@@ -954,7 +1061,7 @@ sub print_config_box {
         if ($action eq 'quotas') {
             $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
         } elsif (($action eq 'autoenroll') || ($action eq 'autocreate') || 
-                 ($action eq 'serverstatuses') || ($action eq 'loadbalancing') ||
+                 ($action eq 'serverstatuses') || ($action eq 'loadbalancing') || 
                  ($action eq 'ltitools')) {
             $output .= $item->{'print'}->($dom,$settings,\$rowtotal);
         } elsif ($action eq 'scantron') {
@@ -1759,7 +1866,7 @@ sub print_quotas {
     my $typecount = 0;
     my ($css_class,%titles);
     if ($context eq 'requestcourses') {
-        @usertools = ('official','unofficial','community','textbook');
+        @usertools = ('official','unofficial','community','textbook','placement');
         @options =('norequest','approval','validate','autolimit');
         %validations = &Apache::lonnet::auto_courserequest_checks($dom);
         %titles = &courserequest_titles();
@@ -2211,7 +2318,7 @@ sub print_studentcode {
     my ($settings,$rowtotal) = @_;
     my $rownum = 0; 
     my ($output,%current);
-    my @crstypes = ('official','unofficial','community','textbook');
+    my @crstypes = ('official','unofficial','community','textbook','placement');
     if (ref($settings) eq 'HASH') {
         if (ref($settings->{'uniquecode'}) eq 'HASH') {
             foreach my $type (@crstypes) {
@@ -2307,8 +2414,7 @@ sub print_textbookcourses {
                               ('&nbsp;'x2).
                               '<span class="LC_nobreak">'.&mt('Thumbnail:');
                 if ($image) {
-                    $datatable .= '<span class="LC_nobreak">'.
-                                  $imgsrc.
+                    $datatable .= $imgsrc.
                                   '<label><input type="checkbox" name="'.$type.'_image_del"'.
                                   ' value="'.$key.'" />'.&mt('Delete?').'</label></span> '.
                                   '<span class="LC_nobreak">&nbsp;'.&mt('Replace:').'&nbsp;';
@@ -3194,7 +3300,7 @@ sub print_helpsettings {
                 @jsarray = ('bystatus');
             }
         }
-        my %domhelpdesk = &Apache::lonnet::get_active_domroles($dom,['dh'.'da']);
+        my %domhelpdesk = &Apache::lonnet::get_active_domroles($dom,['dh','da']);
         if (keys(%domhelpdesk)) {
             push(@accesstypes,('inc','exc'));
             push(@jsarray,('notinc','notexc'));
@@ -3743,7 +3849,7 @@ sub print_ltitools {
                 if (!$rolemaps{$role}) {
                     $selectnone = ' selected="selected"';
                 }
-                $datatable .= '<td align="center">'.
+                $datatable .= '<td align="center">'. 
                               &Apache::lonnet::plaintext($role,'Course').'<br />'.
                               '<select name="ltitools_roles_'.$role.'_'.$i.'">'.
                               '<option value=""'.$selectnone.'>'.&mt('Select').'</option>';
@@ -3915,7 +4021,7 @@ sub ltitools_names {
                                           'url'            => 'URL',
                                           'key'            => 'Key',
                                           'secret'         => 'Secret',
-                                          'icon'           => 'Icon',
+                                          'icon'           => 'Icon',   
                                           'user'           => 'Username:domain',
                                           'fullname'       => 'Full Name',
                                           'firstname'      => 'First Name',
@@ -3933,11 +4039,10 @@ sub ltitools_names {
                                           'roster'         => 'Tool can retrieve roster:',
                                           'crstarget'      => 'Display target',
                                           'crslabel'       => 'Course label',
-                                          'crstitle'       => 'Course title',
+                                          'crstitle'       => 'Course title', 
                                           'crslinktext'    => 'Link Text',
                                           'crsexplanation' => 'Explanation',
                                         );
-
     return %lt;
 }
 
@@ -3946,6 +4051,7 @@ sub print_coursedefaults {
     my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles);
     my $itemcount = 1;
     my %choices =  &Apache::lonlocal::texthash (
+        canuse_pdfforms      => 'Course/Community users can create/upload PDF forms',
         uploadquota          => 'Default quota for files uploaded directly to course/community using Course Editor (MB)',
         anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',
         coursecredits        => 'Credits can be specified for courses',
@@ -3963,11 +4069,12 @@ sub print_coursedefaults {
                          );
     if ($position eq 'top') {
         %defaultchecked = (
+                            'canuse_pdfforms' => 'off',
                             'uselcmath'       => 'on',
                             'usejsme'         => 'on',
                             'canclone'        => 'none',
                           );
-        @toggles = ('uselcmath','usejsme');
+        @toggles = ('canuse_pdfforms','uselcmath','usejsme');
         ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
                                                      \%choices,$itemcount);
         $css_class = $itemcount%2?' class="LC_odd_row"':'';
@@ -4046,7 +4153,7 @@ sub print_coursedefaults {
         my ($currdefresponder,%defcredits,%curruploadquota,%deftimeout,%currmysql);
         my $currusecredits = 0;
         my $postsubmitclient = 1;
-        my @types = ('official','unofficial','community','textbook');
+        my @types = ('official','unofficial','community','textbook','placement');
         if (ref($settings) eq 'HASH') {
             $currdefresponder = $settings->{'anonsurvey_threshold'};
             if (ref($settings->{'uploadquota'}) eq 'HASH') {
@@ -4203,7 +4310,7 @@ sub print_selfenrollment {
     my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable);
     my $itemcount = 1;
-    my @types = ('official','unofficial','community','textbook');
+    my @types = ('official','unofficial','community','textbook','placement');
     if (($position eq 'top') || ($position eq 'middle')) {
         my ($rowsref,$titlesref) = &Apache::lonuserutils::get_selfenroll_titles();
         my %descs = &Apache::lonuserutils::selfenroll_default_descs();
@@ -4426,15 +4533,14 @@ sub print_validation_rows {
 
 sub print_usersessions {
     my ($position,$dom,$settings,$rowtotal) = @_;
-    my ($css_class,$datatable,%checked,%choices);
-    my (%by_ip,%by_location,@intdoms);
-    &build_location_hashes(\@intdoms,\%by_ip,\%by_location);
+    my ($css_class,$datatable,$itemcount,%checked,%choices);
+    my (%by_ip,%by_location,@intdoms,@instdoms);
+    &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
 
     my @alldoms = &Apache::lonnet::all_domains();
     my %serverhomes = %Apache::lonnet::serverhomeIDs;
     my %servers = &Apache::lonnet::internet_dom_servers($dom);
     my %altids = &id_for_thisdom(%servers);
-    my $itemcount = 1;
     if ($position eq 'top') {
         if (keys(%serverhomes) > 1) {
             my %spareid = &current_offloads_to($dom,$settings,\%servers);
@@ -4447,118 +4553,256 @@ sub print_usersessions {
             $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$curroffloadnow,$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.');
+                          &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.').
+                          '</td></tr>';
         }
     } else {
-        if (keys(%by_location) == 0) {
-            $datatable .= '<tr'.$css_class.'><td colspan="2">'.
-                          &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.');
+        my %titles = &usersession_titles();
+        my ($prefix,@types);
+        if ($position eq 'bottom') {
+            $prefix = 'remote';
+            @types = ('version','excludedomain','includedomain');
         } else {
-            my %lt = &usersession_titles();
-            my $numinrow = 5;
-            my $prefix;
-            my @types;
-            if ($position eq 'bottom') {
-                $prefix = 'remote';
-                @types = ('version','excludedomain','includedomain');
-            } else {
-                $prefix = 'hosted';
-                @types = ('excludedomain','includedomain');
-            }
-            my (%current,%checkedon,%checkedoff);
-            my @lcversions = &Apache::lonnet::all_loncaparevs();
-            my @locations = sort(keys(%by_location));
-            foreach my $type (@types) {
-                $checkedon{$type} = '';
-                $checkedoff{$type} = ' checked="checked"';
-            }
-            if (ref($settings) eq 'HASH') {
-                if (ref($settings->{$prefix}) eq 'HASH') {
-                    foreach my $key (keys(%{$settings->{$prefix}})) {
-                        $current{$key} = $settings->{$prefix}{$key};
-                        if ($key eq 'version') {
-                            if ($current{$key} ne '') {
-                                $checkedon{$key} = ' checked="checked"';
-                                $checkedoff{$key} = '';
-                            }
-                        } elsif (ref($current{$key}) eq 'ARRAY') {
+            $prefix = 'hosted';
+            @types = ('excludedomain','includedomain');
+        }
+        ($datatable,$itemcount) = &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
+    }
+    $$rowtotal += $itemcount;
+    return $datatable;
+}
+
+sub rules_by_location {
+    my ($settings,$prefix,$by_location,$by_ip,$types,$titles) = @_; 
+    my ($datatable,$itemcount,$css_class);
+    if (keys(%{$by_location}) == 0) {
+        $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
+        $datatable = '<tr'.$css_class.'><td colspan="2">'.
+                     &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.').
+                     '</td></tr>';
+        $itemcount = 1;
+    } else {
+        $itemcount = 0;
+        my $numinrow = 5;
+        my (%current,%checkedon,%checkedoff);
+        my @locations = sort(keys(%{$by_location}));
+        foreach my $type (@{$types}) {
+            $checkedon{$type} = '';
+            $checkedoff{$type} = ' checked="checked"';
+        }
+        if (ref($settings) eq 'HASH') {
+            if (ref($settings->{$prefix}) eq 'HASH') {
+                foreach my $key (keys(%{$settings->{$prefix}})) {
+                    $current{$key} = $settings->{$prefix}{$key};
+                    if ($key eq 'version') {
+                        if ($current{$key} ne '') {
                             $checkedon{$key} = ' checked="checked"';
                             $checkedoff{$key} = '';
                         }
+                    } elsif (ref($current{$key}) eq 'ARRAY') {
+                        $checkedon{$key} = ' checked="checked"';
+                        $checkedoff{$key} = '';
                     }
                 }
             }
-            foreach my $type (@types) {
-                next if ($type ne 'version' && !@locations);
-                $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
-                $datatable .= '<tr'.$css_class.'>
-                               <td><span class="LC_nobreak">'.$lt{$type}.'</span><br />
-                               <span class="LC_nobreak">&nbsp;
-                               <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>&nbsp;
-                               <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';
-                if ($type eq 'version') {
-                    my $selector = '<select name="'.$prefix.'_version">';
-                    foreach my $version (@lcversions) {
-                        my $selected = '';
-                        if ($current{'version'} eq $version) {
-                            $selected = ' selected="selected"';
-                        }
-                        $selector .= ' <option value="'.$version.'"'.
-                                     $selected.'>'.$version.'</option>';
+        }
+        foreach my $type (@{$types}) {
+            next if ($type ne 'version' && !@locations);
+            $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
+            $datatable .= '<tr'.$css_class.'>
+                           <td><span class="LC_nobreak">'.$titles->{$type}.'</span><br />
+                           <span class="LC_nobreak">&nbsp;
+                           <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>&nbsp;
+                           <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';
+            if ($type eq 'version') {
+                my @lcversions = &Apache::lonnet::all_loncaparevs();
+                my $selector = '<select name="'.$prefix.'_version">';
+                foreach my $version (@lcversions) {
+                    my $selected = '';
+                    if ($current{'version'} eq $version) {
+                        $selected = ' selected="selected"';
                     }
-                    $selector .= '</select> ';
-                    $datatable .= &mt('remote server must be version: [_1] or later',$selector);
-                } else {
-                    $datatable.= '<div><input type="button" value="'.&mt('check all').'" '.
-                                 'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.
-                                 ' />'.('&nbsp;'x2).
-                                 '<input type="button" value="'.&mt('uncheck all').'" '.
-                                 'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.
-                                 "\n".
-                                 '</div><div><table>';
-                    my $rem;
-                    for (my $i=0; $i<@locations; $i++) {
-                        my ($showloc,$value,$checkedtype);
-                        if (ref($by_location{$locations[$i]}) eq 'ARRAY') {
-                            my $ip = $by_location{$locations[$i]}->[0];
-                            if (ref($by_ip{$ip}) eq 'ARRAY') {
-                                 $value = join(':',@{$by_ip{$ip}});
-                                $showloc = join(', ',@{$by_ip{$ip}});
-                                if (ref($current{$type}) eq 'ARRAY') {
-                                    foreach my $loc (@{$by_ip{$ip}}) {  
-                                        if (grep(/^\Q$loc\E$/,@{$current{$type}})) {
-                                            $checkedtype = ' checked="checked"';
-                                            last;
-                                        }
+                    $selector .= ' <option value="'.$version.'"'.
+                                 $selected.'>'.$version.'</option>';
+                }
+                $selector .= '</select> ';
+                $datatable .= &mt('remote server must be version: [_1] or later',$selector);
+            } else {
+                $datatable.= '<div><input type="button" value="'.&mt('check all').'" '.
+                             'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.
+                             ' />'.('&nbsp;'x2).
+                             '<input type="button" value="'.&mt('uncheck all').'" '.
+                             'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.
+                             "\n".
+                             '</div><div><table>';
+                my $rem;
+                for (my $i=0; $i<@locations; $i++) {
+                    my ($showloc,$value,$checkedtype);
+                    if (ref($by_location->{$locations[$i]}) eq 'ARRAY') {
+                        my $ip = $by_location->{$locations[$i]}->[0];
+                        if (ref($by_ip->{$ip}) eq 'ARRAY') {
+                            $value = join(':',@{$by_ip->{$ip}});
+                            $showloc = join(', ',@{$by_ip->{$ip}});
+                            if (ref($current{$type}) eq 'ARRAY') {
+                                foreach my $loc (@{$by_ip->{$ip}}) {
+                                    if (grep(/^\Q$loc\E$/,@{$current{$type}})) {
+                                        $checkedtype = ' checked="checked"';
+                                        last;
                                     }
                                 }
                             }
                         }
-                        $rem = $i%($numinrow);
-                        if ($rem == 0) {
-                            if ($i > 0) {
-                                $datatable .= '</tr>';
-                            }
-                            $datatable .= '<tr>';
-                        }
-                        $datatable .= '<td class="LC_left_item">'.
-                                      '<span class="LC_nobreak"><label>'.
-                                      '<input type="checkbox" name="'.$prefix.'_'.$type.
-                                      '" value="'.$value.'"'.$checkedtype.' />'.$showloc.
-                                      '</label></span></td>';
                     }
-                    $rem = @locations%($numinrow);
-                    my $colsleft = $numinrow - $rem;
-                    if ($colsleft > 1 ) {
-                        $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
-                                      '&nbsp;</td>';
-                    } elsif ($colsleft == 1) {
-                        $datatable .= '<td class="LC_left_item">&nbsp;</td>';
+                    $rem = $i%($numinrow);
+                    if ($rem == 0) {
+                        if ($i > 0) {
+                            $datatable .= '</tr>';
+                        }
+                        $datatable .= '<tr>';
+                    }
+                    $datatable .= '<td class="LC_left_item">'.
+                                  '<span class="LC_nobreak"><label>'.
+                                  '<input type="checkbox" name="'.$prefix.'_'.$type.
+                                  '" value="'.$value.'"'.$checkedtype.' />'.$showloc.
+                                  '</label></span></td>';
+                }
+                $rem = @locations%($numinrow);
+                my $colsleft = $numinrow - $rem;
+                if ($colsleft > 1 ) {
+                    $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
+                                  '&nbsp;</td>';
+                } elsif ($colsleft == 1) {
+                    $datatable .= '<td class="LC_left_item">&nbsp;</td>';
+                }
+                $datatable .= '</tr></table>';
+            }
+            $datatable .= '</td></tr>';
+            $itemcount ++;
+        }
+    }
+    return ($datatable,$itemcount);
+}
+
+sub print_ssl {
+    my ($position,$dom,$settings,$rowtotal) = @_;
+    my ($css_class,$datatable);
+    my $itemcount = 1;
+    if ($position eq 'top') {
+        my $primary_id = &Apache::lonnet::domain($dom,'primary');
+        my $intdom = &Apache::lonnet::internet_dom($primary_id);
+        my $same_institution;
+        if ($intdom ne '') {
+            my $internet_names = &Apache::lonnet::get_internet_names($Apache::lonnet::perlvar{'lonHostID'});
+            if (ref($internet_names) eq 'ARRAY') {
+                if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
+                    $same_institution = 1;
+                }
+            }
+        }
+        $css_class = $itemcount%2?' class="LC_odd_row"':'';
+        $datatable = '<tr'.$css_class.'><td colspan="2">';
+        if ($same_institution) {
+            my %domservers = &Apache::lonnet::get_servers($dom);
+            $datatable .= &LONCAPA::SSL::print_certstatus(\%domservers,'web','domprefs');
+        } else {
+            $datatable .= &mt("You need to be logged into one of your own domain's servers to display information about the status of LON-CAPA SSL certificates.");
+        }
+        $datatable .= '</td></tr>';
+        $itemcount ++;
+    } else {
+        my %titles = &ssl_titles();
+        my (%by_ip,%by_location,@intdoms,@instdoms);
+        &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
+        my @alldoms = &Apache::lonnet::all_domains();
+        my %serverhomes = %Apache::lonnet::serverhomeIDs;
+        my @domservers = &Apache::lonnet::get_servers($dom);
+        my %servers = &Apache::lonnet::internet_dom_servers($dom);
+        my %altids = &id_for_thisdom(%servers);
+        if (($position eq 'connto') || ($position eq 'connfrom')) {
+            my $legacy;
+            unless (ref($settings) eq 'HASH') {
+                my $name;
+                if ($position eq 'connto') {
+                    $name = 'loncAllowInsecure';
+                } else {
+                    $name = 'londAllowInsecure';
+                }
+                my $primarylibserv = &Apache::lonnet::domain($dom,'primary');
+                my @ids=&Apache::lonnet::current_machine_ids();
+                if (($primarylibserv ne '') && (!grep(/^\Q$primarylibserv\E$/,@ids))) {
+                    my %what = (
+                                   $name => 1,
+                               );
+                    my ($result,$returnhash) =
+                        &Apache::lonnet::get_remote_globals($primarylibserv,\%what);
+                    if ($result eq 'ok') {
+                        if (ref($returnhash) eq 'HASH') {
+                            $legacy = $returnhash->{$name};
+                        }
+                    }
+                } else {
+                    $legacy = $Apache::lonnet::perlvar{$name};
+                }
+            }
+            foreach my $type ('dom','intdom','other') {
+                my %checked;
+                $css_class = $itemcount%2?' class="LC_odd_row"':'';
+                $datatable .= '<tr'.$css_class.'><td>'.$titles{$type}.'</td>'.
+                              '<td class="LC_right_item">';
+                my $skip; 
+                if ($type eq 'dom') {
+                    unless (keys(%servers) > 1) {
+                        $datatable .= &mt('Nothing to set here, as there are no other servers/VMs');    
+                        $skip = 1;
+                    }
+                }
+                if ($type eq 'intdom') {
+                    unless (@instdoms > 1) {
+                        $datatable .= &mt('Nothing to set here, as there are no other domains for this institution');
+                        $skip = 1;
+                    } 
+                } elsif ($type eq 'other') {
+                    if (keys(%by_location) == 0) {
+                        $datatable .= &mt('Nothing to set here, as there are no other institutions');
+                        $skip = 1;
+                    }
+                }
+                unless ($skip) {
+                    $checked{'yes'} = ' checked="checked"'; 
+                    if (ref($settings) eq 'HASH') {
+                        if (ref($settings->{$position}) eq 'HASH') {
+                            if ($settings->{$position}->{$type} =~ /^(no|req)$/) {
+                                $checked{$1} = $checked{'yes'};
+                                delete($checked{'yes'}); 
+                            }
+                        }
+                    } else {
+                        if ($legacy == 0) {
+                            $checked{'req'} = $checked{'yes'};
+                            delete($checked{'yes'});    
+                        }
+                    }
+                    foreach my $option ('no','yes','req') {
+                        $datatable .= '<span class="LC_nobreak"><label>'.
+                                      '<input type="radio" name="'.$position.'_'.$type.'" '.
+                                      'value="'.$option.'"'.$checked{$option}.' />'.$titles{$option}.
+                                      '</label></span>'.('&nbsp;'x2);
                     }
-                    $datatable .= '</tr></table>';
                 }
                 $datatable .= '</td></tr>';
+                $itemcount ++; 
+            }
+        } else {
+            my $prefix = 'replication';
+            my @types = ('certreq','nocertreq');
+            if (keys(%by_location) == 0) {
+                $datatable .= '<tr'.$css_class.'><td>'.
+                              &mt('Nothing to set here, as there are no other institutions').
+                              '</td></tr>';
                 $itemcount ++;
+            } else {
+                ($datatable,$itemcount) = 
+                    &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
             }
         }
     }
@@ -4566,10 +4810,60 @@ sub print_usersessions {
     return $datatable;
 }
 
+sub ssl_titles {
+    return &Apache::lonlocal::texthash (
+               dom           => 'LON-CAPA servers/VMs from same domain',
+               intdom        => 'LON-CAPA servers/VMs from same "internet" domain',
+               other         => 'External LON-CAPA servers/VMs',
+               connto        => 'Connections to other servers',
+               connfrom      => 'Connections from other servers',
+               replication   => 'Replicating content to other institutions',
+               certreq       => 'Client certificate required, but specific domains exempt',
+               nocertreq     => 'No client certificate required, except for specific domains',
+               no            => 'SSL not used',
+               yes           => 'SSL Optional (used if available)',
+               req           => 'SSL Required',
+    );
+}
+
+sub print_trust {
+    my ($prefix,$dom,$settings,$rowtotal) = @_;
+    my ($css_class,$datatable,%checked,%choices);
+    my (%by_ip,%by_location,@intdoms,@instdoms);
+    &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
+    my $itemcount = 1;
+    my %titles = &trust_titles();
+    my @types = ('exc','inc');
+    if ($prefix eq 'top') {
+        $prefix = 'content';
+    } elsif ($prefix eq 'bottom') {
+        $prefix = 'msg';
+    }
+    ($datatable,$itemcount) = &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
+    $$rowtotal += $itemcount;
+    return $datatable;
+}
+
+sub trust_titles {
+    return &Apache::lonlocal::texthash(
+               content  => "Access to this domain's content by others",
+               shared   => "Access to other domain's content by this domain",
+               enroll   => "Enrollment in this domain's courses by others", 
+               othcoau  => "Co-author roles in this domain for others",
+               coaurem  => "Co-author roles for this domain's users elsewhere", 
+               domroles => "Domain roles in this domain assignable to others",
+               catalog  => "Course Catalog for this domain displayed elsewhere",
+               reqcrs   => "Requests for creation of courses in this domain by others",
+               msg      => "Users in other domains can send messages to this domain",
+               exc      => "Allow all, but exclude specific domains",
+               inc      => "Deny all, but include specific domains",
+           );
+} 
+
 sub build_location_hashes {
-    my ($intdoms,$by_ip,$by_location) = @_;
+    my ($intdoms,$by_ip,$by_location,$instdoms) = @_;
     return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') &&
-                  (ref($by_location) eq 'HASH')); 
+                  (ref($by_location) eq 'HASH') && (ref($instdoms) eq 'ARRAY'));
     my %iphost = &Apache::lonnet::get_iphost();
     my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary');
     my $primary_ip = &Apache::lonnet::get_host_ip($primary_id);
@@ -4586,7 +4880,13 @@ sub build_location_hashes {
             foreach my $id (@{$iphost{$ip}}) {
                 my $location = &Apache::lonnet::internet_dom($id);
                 if ($location) {
-                    next if (grep(/^\Q$location\E$/,@{$intdoms}));
+                    if (grep(/^\Q$location\E$/,@{$intdoms})) {
+                        my $dom = &Apache::lonnet::host_domain($id);
+                        unless (grep(/^\Q$dom\E/,@{$instdoms})) {
+                            push(@{$instdoms},$dom);
+                        }
+                        next;
+                    }
                     if (ref($by_ip->{$ip}) eq 'ARRAY') {
                         unless(grep(/^\Q$location\E$/,@{$by_ip->{$ip}})) {
                             push(@{$by_ip->{$ip}},$location);
@@ -5090,9 +5390,14 @@ sub loadbalancing_titles {
            '_LC_ipchange'    => &mt('Non-SSO users with IP mismatch'),
                      );
     my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external','_LC_ipchangesso','_LC_ipchange');
+    my @available;
     if (ref($types) eq 'ARRAY') {
-        unshift(@alltypes,@{$types},'default');
+        @available = @{$types};
+    }
+    unless (grep(/^default$/,@available)) {
+        push(@available,'default');
     }
+    unshift(@alltypes,@available);
     my %titles;
     foreach my $type (@alltypes) {
         if ($type =~ /^_LC_/) {
@@ -5271,6 +5576,7 @@ sub tool_titles {
                      unofficial => 'Unofficial courses',
                      community  => 'Communities',
                      textbook   => 'Textbook courses',
+                     placement  => 'Placement tests',
                  );
     return %titles;
 }
@@ -5281,6 +5587,7 @@ sub courserequest_titles {
                                    unofficial => 'Unofficial',
                                    community  => 'Communities',
                                    textbook   => 'Textbook',
+                                   placement  => 'Placement tests',
                                    norequest  => 'Not allowed',
                                    approval   => 'Approval by Dom. Coord.',
                                    validate   => 'With validation',
@@ -5468,6 +5775,7 @@ sub print_selfcreation {
     my %radiohash;
     my $numinrow = 4;
     map { $radiohash{'cancreate_'.$_} = 1; } @selfcreate;
+    my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
     if ($position eq 'top') {
         my %choices = &Apache::lonlocal::texthash (
                                                       cancreate_login      => 'Institutional Login',
@@ -5483,8 +5791,6 @@ sub print_selfcreation {
                                                      \%choices,$itemcount,$onclick);
         $$rowtotal += $itemcount;
         
-        my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
-
         if (ref($usertypes) eq 'HASH') {
             if (keys(%{$usertypes}) > 0) {
                 $datatable .= &insttypes_row($createsettings,$types,$usertypes,
@@ -5534,16 +5840,22 @@ sub print_selfcreation {
         $$rowtotal ++;
     } elsif ($position eq 'middle') {
         my %domconf = &Apache::lonnet::get_dom('configuration',['usermodification'],$dom);
-        my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
-        $usertypes->{'default'} = $othertitle;
+        my @posstypes;
         if (ref($types) eq 'ARRAY') {
-            push(@{$types},'default');
-            $usertypes->{'default'} = $othertitle;
-            foreach my $status (@{$types}) {
-                $datatable .= &modifiable_userdata_row('selfcreate',$status,$domconf{'usermodification'},
-                                                       $numinrow,$$rowtotal,$usertypes);
-                $$rowtotal ++;
-            }
+            @posstypes = @{$types};
+        }
+        unless (grep(/^default$/,@posstypes)) {
+            push(@posstypes,'default');
+        }
+        my %usertypeshash;
+        if (ref($usertypes) eq 'HASH') {
+            %usertypeshash = %{$usertypes};
+        }
+        $usertypeshash{'default'} = $othertitle;
+        foreach my $status (@posstypes) {
+            $datatable .= &modifiable_userdata_row('selfcreate',$status,$domconf{'usermodification'},
+                                                   $numinrow,$$rowtotal,\%usertypeshash);
+            $$rowtotal ++;
         }
     } else {
         my %choices = &Apache::lonlocal::texthash (
@@ -5561,29 +5873,34 @@ sub print_selfcreation {
         my $onclick = "toggleDisplay(this.form,'emailoptions');";
         my $additional = '<div id="emailoptions" style="display: '.$display.'">';
         my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
-        my $usertypes = {};
-        my $order = [];
-        if ((ref($domdefaults{'inststatustypes'}) eq 'HASH') && (ref($domdefaults{'inststatusguest'}) eq 'ARRAY')) {
-            $usertypes = $domdefaults{'inststatustypes'};
+        my $order;
+        if (ref($domdefaults{'inststatusguest'}) eq 'ARRAY') {
             $order = $domdefaults{'inststatusguest'};
         }
+        my (@ordered,%usertypeshash);
         if (ref($order) eq 'ARRAY') {
-            push(@{$order},'default');
-            if (@{$order} > 1) {
-                $usertypes->{'default'} = &mt('Other users');
-                $additional .= '<table><tr>';
-                foreach my $status (@{$order}) {
-                    $additional .= '<th>'.$usertypes->{$status}.'</th>';
-                }
-                $additional .= '</tr><tr>';
-                foreach my $status (@{$order}) {
-                    $additional .= '<td>'.&email_as_username($rowtotal,$processing,$status).'</td>';
-                }
-                $additional .= '</tr></table>';
-            } else {
-                $usertypes->{'default'} = &mt('All users');
-                $additional .= &email_as_username($rowtotal,$processing);
+            @ordered = @{$order};
+        }
+        if (@ordered) {
+            unless (grep(/^default$/,@ordered)) {
+                push(@ordered,'default');
+            }
+            if (ref($usertypes) eq 'HASH') {
+                %usertypeshash = %{$usertypes};
+            }
+            $usertypeshash{'default'} = $othertitle;
+            $additional .= '<table><tr>';
+            foreach my $status (@ordered) {
+                $additional .= '<th>'.$usertypeshash{$status}.'</th>';
             }
+            $additional .= '</tr><tr>';
+            foreach my $status (@ordered) {
+                $additional .= '<td>'.&email_as_username($rowtotal,$processing,$status).'</td>';
+            }
+            $additional .= '</tr></table>';
+        } else {
+            $usertypeshash{'default'} = $othertitle;
+            $additional .= &email_as_username($rowtotal,$processing);
         }
         $additional .= '</div>'."\n";
 
@@ -5594,12 +5911,10 @@ sub print_selfcreation {
         $$rowtotal ++;
         my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();
         $numinrow = 1;
-        if (ref($order) eq 'ARRAY') {
-            foreach my $status (@{$order}) {
-                $datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,
-                                                       $numinrow,$$rowtotal,$usertypes,$infofields,$infotitles);
-                $$rowtotal ++;
-            }
+        foreach my $status (@ordered) {
+            $datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,
+                                                   $numinrow,$$rowtotal,\%usertypeshash,$infofields,$infotitles);
+            $$rowtotal ++;
         }
         my ($emailrules,$emailruleorder) =
             &Apache::lonnet::inst_userrules($dom,'email');
@@ -5671,7 +5986,7 @@ sub email_as_username {
 sub captcha_choice {
     my ($context,$settings,$itemcount) = @_;
     my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext,
-        $vertext,$currver); 
+        $vertext,$currver);
     my %lt = &captcha_phrases();
     $keyentry = 'hidden';
     if ($context eq 'cancreate') {
@@ -6003,7 +6318,7 @@ sub print_defaults {
                 $datatable .= '</table>';
             } else {
                 $datatable .= '<input type="text" name="'.$item.'" value="'.
-                              $defaults{$item}.'" size="3" onblur="javascript:warnIntAuth(this);" />';
+                              $defaults{$item}.'" size="3" onblur="javascript:warnIntAuth(this);" />'; 
             }
             $datatable .= '</td></tr>';
             $rownum ++;
@@ -6208,7 +6523,7 @@ sub print_scantronformat {
     if (ref($settings) eq 'HASH') {
         if ($settings->{'scantronformat'} eq "/res/$dom/$confname/scantron/custom.tab") {
             my @info = &Apache::lonnet::stat_file($settings->{'scantronformat'});
-            if (0 && ((!@info) || ($info[0] eq 'no_such_dir'))) {
+            if ((!@info) || ($info[0] eq 'no_such_dir')) {
                 $scantronurl = '';
             } else {
                 $scantronurl = $settings->{'scantronformat'};
@@ -6349,6 +6664,10 @@ sub print_coursecategories {
         my $toggle_catscomm_dom = ' checked="checked" ';
         my $can_catcomm_comm = ' ';
         my $can_catcomm_dom = ' checked="checked" ';
+        my $toggle_catsplace_place = ' ';
+        my $toggle_catsplace_dom = ' checked="checked" ';
+        my $can_catplace_place = ' ';
+        my $can_catplace_dom = ' checked="checked" ';
 
         if (ref($settings) eq 'HASH') {
             if ($settings->{'togglecats'} eq 'crs') {
@@ -6367,17 +6686,28 @@ sub print_coursecategories {
                 $can_catcomm_comm = $can_catcomm_dom;
                 $can_catcomm_dom = ' ';
             }
+            if ($settings->{'togglecatsplace'} eq 'place') {
+                $toggle_catsplace_place = $toggle_catsplace_dom;
+                $toggle_catsplace_dom = ' ';
+            }
+            if ($settings->{'categorizeplace'} eq 'place') {
+                $can_catplace_place = $can_catplace_dom;
+                $can_catplace_dom = ' ';
+            }
         }
         my %title = &Apache::lonlocal::texthash (
-                     togglecats     => 'Show/Hide a course in catalog',
-                     togglecatscomm => 'Show/Hide a community in catalog',
-                     categorize     => 'Assign a category to a course',
-                     categorizecomm => 'Assign a category to a community',
+                     togglecats      => 'Show/Hide a course in catalog',
+                     togglecatscomm  => 'Show/Hide a community in catalog',
+                     togglecatsplace => 'Show/Hide a placement test in catalog',
+                     categorize      => 'Assign a category to a course',
+                     categorizecomm  => 'Assign a category to a community',
+                     categorizeplace => 'Assign a category to a placement test',
                     );
         my %level = &Apache::lonlocal::texthash (
-                     dom  => 'Set in Domain',
-                     crs  => 'Set in Course',
-                     comm => 'Set in Community',
+                     dom   => 'Set in Domain',
+                     crs   => 'Set in Course',
+                     comm  => 'Set in Community',
+                     place => 'Set in Placement Test',
                     );
         $datatable = '<tr class="LC_odd_row">'.
                   '<td>'.$title{'togglecats'}.'</td>'.
@@ -6407,8 +6737,22 @@ sub print_coursecategories {
                   $can_catcomm_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.
                   '<label><input type="radio" name="categorizecomm"'.
                   $can_catcomm_comm.'value="comm" />'.$level{'comm'}.'</label></span></td>'.
+                  '</tr><tr>'.
+                  '<td>'.$title{'togglecatsplace'}.'</td>'.
+                  '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
+                  '<input type="radio" name="togglecatsplace"'.
+                  $toggle_catsplace_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.
+                  '<label><input type="radio" name="togglecatscomm"'.
+                  $toggle_catsplace_place.' value="comm" />'.$level{'place'}.'</label></span></td>'.
+                  '</tr><tr>'.
+                  '<td>'.$title{'categorizeplace'}.'</td>'.
+                  '<td class="LC_right_item"><span class="LC_nobreak">'.
+                  '<label><input type="radio" name="categorizeplace"'.
+                  $can_catplace_dom.' value="dom" />'.$level{'dom'}.'</label>&nbsp;'.
+                  '<label><input type="radio" name="categorizeplace"'.
+                  $can_catplace_place.'value="place" />'.$level{'place'}.'</label></span></td>'.
                   '</tr>';
-        $$rowtotal += 4;
+        $$rowtotal += 6;
     } else {
         my $css_class;
         my $itemcount = 1;
@@ -6433,12 +6777,15 @@ sub print_coursecategories {
                     my %default_names = (
                           instcode    => &mt('Official courses'),
                           communities => &mt('Communities'),
+                          placement   => &mt('Placement Tests'),
                     );
 
                     if ((!grep(/^instcode$/,@{$cats[0]})) || 
                         ($cathash->{'instcode::0'} eq '') ||
                         (!grep(/^communities$/,@{$cats[0]})) || 
-                        ($cathash->{'communities::0'} eq '')) {
+                        ($cathash->{'communities::0'} eq '') ||
+                        (!grep(/^placement$/,@{$cats[0]})) ||
+                        ($cathash->{'placement::0'} eq '')) {
                         $maxnum ++;
                     }
                     my $lastidx;
@@ -6459,7 +6806,7 @@ sub print_coursecategories {
                             $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
                         }
                         $datatable .= '</select></span></td><td>';
-                        if ($parent eq 'instcode' || $parent eq 'communities') {
+                        if ($parent eq 'instcode' || $parent eq 'communities' || $parent eq 'placement') {
                             $datatable .=  '<span class="LC_nobreak">'
                                            .$default_names{$parent}.'</span>';
                             if ($parent eq 'instcode') {
@@ -6482,7 +6829,7 @@ sub print_coursecategories {
                             $datatable .= '<label><input type="radio" name="'
                                           .$parent.'" value="0" />'
                                           .&mt('Do not display').'</label></span>';
-                            if ($parent eq 'communities') {
+                            if (($parent eq 'communities') || ($parent eq 'placement')) {
                                 $datatable .= '</td></tr></table>';
                             }
                             $datatable .= '</td>';
@@ -6514,7 +6861,7 @@ sub print_coursecategories {
                                   .'<input type="text" size="20" name="addcategory_name" value="" /></td>'
                                   .'</tr>'."\n";
                     $itemcount ++;
-                    foreach my $default ('instcode','communities') {
+                    foreach my $default ('instcode','communities','placement') {
                         if ((!grep(/^\Q$default\E$/,@{$cats[0]})) || ($cathash->{$default.'::0'} eq '')) {
                             $css_class = $itemcount%2?' class="LC_odd_row"':'';
                             my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','$lastidx'".');"';
@@ -6603,9 +6950,9 @@ sub print_serverstatuses {
 
 sub serverstatus_pages {
     return ('userstatus','lonstatus','loncron','server-status','codeversions',
-            'checksums','clusterstatus','metadata_keywords','metadata_harvest',
-            'takeoffline','takeonline','showenv','toggledebug','ping','domconf',
-            'uniquecodes','diskusage','coursecatalog');
+            'checksums','clusterstatus','certstatus','metadata_keywords',
+            'metadata_harvest','takeoffline','takeonline','showenv','toggledebug',
+            'ping','domconf','uniquecodes','diskusage','coursecatalog');
 }
 
 sub defaults_javascript {
@@ -6727,9 +7074,11 @@ sub coursecategories_javascript {
     }
     my $instcode_reserved = &mt('The name: [_1] is a reserved category.','"instcode"');
     my $communities_reserved = &mt('The name: [_1] is a reserved category.','"communities"');
+    my $placement_reserved = &mt('The name: [_1] is a reserved category.','"placement"');
     my $choose_again = "\n".&mt('Please use a different name for the new top level category.'); 
     &js_escape(\$instcode_reserved);
     &js_escape(\$communities_reserved);
+    &js_escape(\$placement_reserved);
     &js_escape(\$choose_again);
     $output = <<"ENDSCRIPT";
 <script type="text/javascript">
@@ -6799,6 +7148,10 @@ function categoryCheck(form) {
         alert('$communities_reserved\\n$choose_again');
         return false;
     }
+    if (form.elements['addcategory_name'].value == 'placement') {
+        alert('$placement_reserved\\n$choose_again');
+        return false;
+    }
     return true;
 }
 
@@ -6815,13 +7168,14 @@ sub initialize_categories {
     my %default_names = (
                       instcode    => 'Official courses (with institutional codes)',
                       communities => 'Communities',
+                      placement   => 'Placement Tests',
                         );
     my $select0 = ' selected="selected"';
     my $select1 = '';
-    foreach my $default ('instcode','communities') {
+    foreach my $default ('instcode','communities','placement') {
         $css_class = $itemcount%2?' class="LC_odd_row"':'';
         $chgstr = ' onchange="javascript:reorderCats(this.form,'."'',$default"."_pos','0'".');"';
-        if ($default eq 'communities') {
+        if (($default eq 'communities') || ($default eq 'placement')) {
             $select1 = $select0;
             $select0 = '';
         }
@@ -8130,7 +8484,7 @@ sub check_authorstatus {
 
 sub publishlogo {
     my ($r,$action,$formname,$dom,$confname,$subdir,$thumbwidth,$thumbheight,$savefileas) = @_;
-    my ($output,$fname,$logourl);
+    my ($output,$fname,$logourl,$madethumb);
     if ($action eq 'upload') {
         $fname=$env{'form.'.$formname.'.filename'};
         chop($env{'form.'.$formname});
@@ -8258,6 +8612,7 @@ $env{'user.name'}.':'.$env{'user.domain'
                                     $r->set_handlers('PerlCleanupHandler' => [\&notifysubscribed,@{$handlers}]);
                                     $registered_cleanup=1;
                                 }
+                                $madethumb = 1;
                             } else {
                                 print $logfile "\nUnable to write ".$copyfile.
                                                ':'.$!."\n";
@@ -8270,7 +8625,7 @@ $env{'user.name'}.':'.$env{'user.domain'
             $output = $versionresult;
         }
     }
-    return ($output,$logourl);
+    return ($output,$logourl,$madethumb);
 }
 
 sub logo_versioning {
@@ -8424,7 +8779,7 @@ sub modify_quotas {
         $context = $action;
     }
     if ($context eq 'requestcourses') {
-        @usertools = ('official','unofficial','community','textbook');
+        @usertools = ('official','unofficial','community','textbook','placement');
         @options =('norequest','approval','validate','autolimit');
         %validations = &Apache::lonnet::auto_courserequest_checks($dom);
         %titles = &courserequest_titles();
@@ -8473,7 +8828,7 @@ sub modify_quotas {
         my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval');
         @approvalnotify = sort(@approvalnotify);
         $confhash{'notify'}{'approval'} = join(',',@approvalnotify);
-        my @crstypes = ('official','unofficial','community','textbook');
+        my @crstypes = ('official','unofficial','community','textbook','placement');
         my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');
         foreach my $type (@hasuniquecode) {
             if (grep(/^\Q$type\E$/,@crstypes)) {
@@ -9152,7 +9507,7 @@ sub modify_ltitools {
     map { $posslti{$_} = 1; } @ltiroles;
     my @allfields = ('fullname','firstname','lastname','email','user','roles');
     map { $possfield{$_} = 1; } @allfields;
-    my %lt = &ltitools_names();
+    my %lt = &ltitools_names(); 
     if ($env{'form.ltitools_add'}) {
         my $title = $env{'form.ltitools_add_title'};
         $title =~ s/(`)/'/g;
@@ -9189,7 +9544,7 @@ sub modify_ltitools {
                     }
                 } else {
                     if ($env{'form.ltitools_add_'.$item} ne '') {
-                        $confhash{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item};
+                        $confhash{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item}; 
                     }
                 }
             }
@@ -9226,7 +9581,7 @@ sub modify_ltitools {
                             if (($choice ne '') && ($posslti{$choice})) {
                                 $confhash{$newid}{'roles'}{$role} = $choice;
                                 if ($role eq 'cc') {
-                                    $confhash{$newid}{'roles'}{'co'} = $choice;
+                                    $confhash{$newid}{'roles'}{'co'} = $choice; 
                                 }
                             }
                         }
@@ -9247,7 +9602,7 @@ sub modify_ltitools {
                 $confhash{$newid}{'custom'}{$name} = $value;
             }
         } else {
-            my $error = &mt('Failed to acquire unique ID for new external tool');
+            my $error = &mt('Failed to acquire unique ID for new external tool');   
             $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
         }
     }
@@ -9261,7 +9616,7 @@ sub modify_ltitools {
         my @newcustom = &Apache::loncommon::get_env_multiple('form.ltitools_customadd');
         if (@newcustom) {
             map { $customadds{$_} = 1; } @newcustom;
-        }
+        } 
         my %imgdeletions;
         my @todeleteimages = &Apache::loncommon::get_env_multiple('form.ltitools_image_del');
         if (@todeleteimages) {
@@ -9437,7 +9792,7 @@ sub modify_ltitools {
                     }
                 }
                 my %customdels;
-                my @customdeletions = &Apache::loncommon::get_env_multiple('form.ltitools_customdel_'.$i);
+                my @customdeletions = &Apache::loncommon::get_env_multiple('form.ltitools_customdel_'.$i); 
                 if (@customdeletions) {
                     $changes{$itemid} = 1;
                 }
@@ -9446,7 +9801,7 @@ sub modify_ltitools {
                     foreach my $key (keys(%{$domconfig{$action}{$itemid}{'custom'}})) {
                         unless ($customdels{$key}) {
                             if ($env{'form.ltitools_customval_'.$key.'_'.$i} ne '') {
-                                $confhash{$itemid}{'custom'}{$key} = $env{'form.ltitools_customval_'.$key.'_'.$i};
+                                $confhash{$itemid}{'custom'}{$key} = $env{'form.ltitools_customval_'.$key.'_'.$i}; 
                             }
                             if ($domconfig{$action}{$itemid}{'custom'}{$key} ne $env{'form.ltitools_customval_'.$key.'_'.$i}) {
                                 $changes{$itemid} = 1;
@@ -9521,7 +9876,7 @@ sub modify_ltitools {
                 $bynum{$position} = $itemid;
             }
             foreach my $pos (sort { $a <=> $b } keys(%bynum)) {
-                my $itemid = $bynum{$pos};
+                my $itemid = $bynum{$pos}; 
                 if (ref($confhash{$itemid}) ne 'HASH') {
                     $resulttext .= '<li>'.&mt('Deleted: [_1]',$changes{$itemid}).'</li>';
                 } else {
@@ -9549,8 +9904,8 @@ sub modify_ltitools {
                     }
                     $resulttext .= '<li>'.&mt('Configurable in course:');
                     my @possconfig = ('label','title','target','linktext','explanation');
-                    my $numconfig = 0;
-                    if (ref($confhash{$itemid}{'crsconf'}) eq 'HASH') {
+                    my $numconfig = 0; 
+                    if (ref($confhash{$itemid}{'crsconf'}) eq 'HASH') { 
                         foreach my $item (@possconfig) {
                             if ($confhash{$itemid}{'crsconf'}{$item}) {
                                 $numconfig ++;
@@ -9577,7 +9932,7 @@ sub modify_ltitools {
                             $displaylist = &mt('Display target').':&nbsp;'.
                                            $confhash{$itemid}{'display'}{'target'}.',';
                         }
-                        foreach my $size ('width','height') {
+                        foreach my $size ('width','height') { 
                             if ($confhash{$itemid}{'display'}{$size}) {
                                 $displaylist .= ('&nbsp;'x2).$lt{$size}.':&nbsp;'.
                                                 $confhash{$itemid}{'display'}{$size}.',';
@@ -9614,7 +9969,7 @@ sub modify_ltitools {
                             }
                         }
                         if ($rolemaps) {
-                            $rolemaps =~ s/,$//;
+                            $rolemaps =~ s/,$//; 
                             $resulttext .= '<li>'.&mt('Role mapping:').$rolemaps.'</li>';
                         }
                     }
@@ -9623,12 +9978,12 @@ sub modify_ltitools {
                         if (keys(%{$confhash{$itemid}{'custom'}})) {
                             foreach my $key (sort(keys(%{$confhash{$itemid}{'custom'}}))) {
                                 $customlist .= $key.':'.$confhash{$itemid}{'custom'}{$key}.('&nbsp;'x2);
-                            }
+                            } 
                         }
                         if ($customlist) {
                             $resulttext .= '<li>'.&mt('Custom items').':'.$customlist.'</li>';
                         }
-                    }
+                    } 
                     $resulttext .= '</ul></li>';
                 }
             }
@@ -9689,7 +10044,7 @@ sub get_ltitools_id {
     my $tries = 0;
     my $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
     my ($id,$error);
-
+ 
     while (($gotlock ne 'ok') && ($tries<10)) {
         $tries ++;
         sleep (0.1);
@@ -10512,7 +10867,7 @@ sub modify_contacts {
                             $resulttext .= $bcctext.': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';
                         } elsif (!@text) {
                             $resulttext .= &mt('No one');
-                        }
+                        }   
                         if ($includestr{$type} ne '') {
                             if ($includeloc{$type} eq 'b') {
                                 $resulttext .= '<br />'.&mt('Text automatically added to e-mail body:').' '.$includestr{$type};
@@ -11996,6 +12351,15 @@ sub modify_coursecategories {
         if ($domconfig{'coursecategories'}{'categorizecomm'} ne $env{'form.categorizecomm'}) {
             $changes{'categorizecomm'} = 1;
             $domconfig{'coursecategories'}{'categorizecomm'} = $env{'form.categorizecomm'};
+
+        }
+        if ($domconfig{'coursecategories'}{'togglecatsplace'} ne $env{'form.togglecatsplace'}) {
+            $changes{'togglecatsplace'} = 1;
+            $domconfig{'coursecategories'}{'togglecatsplace'} = $env{'form.togglecatsplace'};
+        }
+        if ($domconfig{'coursecategories'}{'categorizeplace'} ne $env{'form.categorizeplace'}) {
+            $changes{'categorizeplace'} = 1;
+            $domconfig{'coursecategories'}{'categorizeplace'} = $env{'form.categorizeplace'};
         }
         foreach my $item (@catitems) {
             if (grep(/^\Q$env{'form.coursecat_'.$item}\E$/,@cattypes)) {
@@ -12010,11 +12374,15 @@ sub modify_coursecategories {
         $changes{'categorize'} = 1;
         $changes{'togglecatscomm'} = 1;
         $changes{'categorizecomm'} = 1;
+        $changes{'togglecatsplace'} = 1;
+        $changes{'categorizeplace'} = 1;
         $domconfig{'coursecategories'} = {
                                              togglecats => $env{'form.togglecats'},
                                              categorize => $env{'form.categorize'},
                                              togglecatscomm => $env{'form.togglecatscomm'},
                                              categorizecomm => $env{'form.categorizecomm'},
+                                             togglecatsplace => $env{'form.togglecatsplace'},
+                                             categorizeplace => $env{'form.categorizeplace'},
                                          };
         foreach my $item (@catitems) {
             if ($env{'form.coursecat_'.$item} ne 'std') {
@@ -12032,6 +12400,9 @@ sub modify_coursecategories {
         if (($domconfig{'coursecategories'}{'cats'}{'communities::0'} ne '')  && ($env{'form.communities'} == 0)) {
             push(@deletecategory,'communities::0');
         }
+        if (($domconfig{'coursecategories'}{'cats'}{'placement::0'} ne '')  && ($env{'form.placement'} == 0)) {
+            push(@deletecategory,'placement::0');
+        }
     }
     my (@predelcats,@predeltrails,%predelallitems,%sort_by_deltrail);
     if (ref($cathash) eq 'HASH') {
@@ -12094,9 +12465,23 @@ sub modify_coursecategories {
             $adds{$newitem} = 1;
         }
     }
+    if ($env{'form.placement'} eq '1') {
+        if (ref($cathash) eq 'HASH') {
+            my $newitem = 'placement::0';
+            if ($cathash->{$newitem} eq '') {
+                $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.placement_pos'};
+                $adds{$newitem} = 1;
+            }
+        } else {
+            my $newitem = 'placement::0';
+            $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.placement_pos'};
+            $adds{$newitem} = 1;
+        }
+    }
     if ($env{'form.addcategory_name'} ne '') {
         if (($env{'form.addcategory_name'} ne 'instcode') &&
-            ($env{'form.addcategory_name'} ne 'communities')) {
+            ($env{'form.addcategory_name'} ne 'communities') &&
+            ($env{'form.addcategory_name'} ne 'placement')) {
             my $newitem = &escape($env{'form.addcategory_name'}).'::0';
             $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.addcategory_pos'};
             $adds{$newitem} = 1;
@@ -12691,14 +13076,16 @@ sub modify_coursedefaults {
     my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,$errors,%changes,%defaultshash);
     my %defaultchecked = (
+                           'canuse_pdfforms' => 'off',
                            'uselcmath'       => 'on',
                            'usejsme'         => 'on'
                          );
-    my @toggles = ('uselcmath','usejsme');
+    my @toggles = ('canuse_pdfforms','uselcmath','usejsme');
     my @numbers = ('anonsurvey_threshold','uploadquota_official','uploadquota_unofficial',
-                   'uploadquota_community','uploadquota_textbook','mysqltables_official',
-                   'mysqltables_unofficial','mysqltables_community','mysqltables_textbook');
-    my @types = ('official','unofficial','community','textbook');
+                   'uploadquota_community','uploadquota_textbook','uploadquota_placement',
+                   'mysqltables_official','mysqltables_unofficial','mysqltables_community',
+                   'mysqltables_textbook','mysqltables_placement');
+    my @types = ('official','unofficial','community','textbook','placement');
     my %staticdefaults = (
                            anonsurvey_threshold => 10,
                            uploadquota          => 500,
@@ -12883,10 +13270,10 @@ sub modify_coursedefaults {
     if ($putresult eq 'ok') {
         if (keys(%changes) > 0) {
             my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
-            if (($changes{'uploadquota'}) || ($changes{'postsubmit'}) ||
+            if (($changes{'canuse_pdfforms'}) || ($changes{'uploadquota'}) || ($changes{'postsubmit'}) ||
                 ($changes{'coursecredits'}) || ($changes{'uselcmath'}) || ($changes{'usejsme'}) ||
                 ($changes{'canclone'}) || ($changes{'mysqltables'})) {
-                foreach my $item ('uselcmath','usejsme') {
+                foreach my $item ('canuse_pdfforms','uselcmath','usejsme') { 
                     if ($changes{$item}) {
                         $domdefaults{$item}=$defaultshash{'coursedefaults'}{$item};
                     }
@@ -12937,7 +13324,13 @@ sub modify_coursedefaults {
             }
             $resulttext = &mt('Changes made:').'<ul>';
             foreach my $item (sort(keys(%changes))) {
-                if ($item eq 'uselcmath') {
+                if ($item eq 'canuse_pdfforms') {
+                    if ($env{'form.'.$item} eq '1') {
+                        $resulttext .= '<li>'.&mt("Course/Community users can create/upload PDF forms set to 'on'").'</li>';
+                    } else {
+                        $resulttext .= '<li>'.&mt('Course/Community users can create/upload PDF forms set to "off"').'</li>';
+                    }
+                } elsif ($item eq 'uselcmath') {
                     if ($env{'form.'.$item} eq '1') {
                         $resulttext .= '<li>'.&mt('Math preview uses LON-CAPA previewer (javascript), if supported by browser.').'</li>';
                     } else {
@@ -12957,7 +13350,7 @@ sub modify_coursedefaults {
                                        '<li>'.&mt('Official courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'official'}.'</b>').'</li>'.
                                        '<li>'.&mt('Unofficial courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'unofficial'}.'</b>').'</li>'.
                                        '<li>'.&mt('Textbook courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'textbook'}.'</b>').'</li>'.
-
+                                       '<li>'.&mt('Placement tests: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'placement'}.'</b>').'</li>'. 
                                        '<li>'.&mt('Communities: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'community'}.'</b>').'</li>'.
                                        '</ul>'.
                                        '</li>';
@@ -12970,6 +13363,7 @@ sub modify_coursedefaults {
                                        '<li>'.&mt('Official courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'official'}.'</b>').'</li>'.
                                        '<li>'.&mt('Unofficial courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'unofficial'}.'</b>').'</li>'.
                                        '<li>'.&mt('Textbook courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'textbook'}.'</b>').'</li>'.
+                                       '<li>'.&mt('Placement tests: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'placement'}.'</b>').'</li>'.
                                        '<li>'.&mt('Communities: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'community'}.'</b>').'</li>'.
                                        '</ul>'.
                                        '</li>';
@@ -13005,6 +13399,8 @@ sub modify_coursedefaults {
                                     $resulttext .= &mt('Unofficial courses');
                                 } elsif ($type eq 'textbook') {
                                     $resulttext .= &mt('Textbook courses');
+                                } elsif ($type eq 'placement') {
+                                    $resulttext .= &mt('Placement tests');
                                 }
                                 $resulttext .= ' -- '.$display.'</li>';
                             }
@@ -13056,7 +13452,7 @@ sub modify_coursedefaults {
 sub modify_selfenrollment {
     my ($dom,$lastactref,%domconfig) = @_;
     my ($resulttext,$errors,%changes,%selfenrollhash,%ordered);
-    my @types = ('official','unofficial','community','textbook');
+    my @types = ('official','unofficial','community','textbook','placement');
     my %titles = &tool_titles();
     my %descs = &Apache::lonuserutils::selfenroll_default_descs();
     ($ordered{'admin'},my $titlesref) = &Apache::lonuserutils::get_selfenroll_titles();
@@ -13303,8 +13699,8 @@ sub modify_usersessions {
                 );
     my @prefixes = ('remote','hosted','spares');
     my @lcversions = &Apache::lonnet::all_loncaparevs();
-    my (%by_ip,%by_location,@intdoms);
-    &build_location_hashes(\@intdoms,\%by_ip,\%by_location);
+    my (%by_ip,%by_location,@intdoms,@instdoms);
+    &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
     my @locations = sort(keys(%by_location));
     my (%defaultshash,%changes);
     foreach my $prefix (@prefixes) {
@@ -13607,6 +14003,298 @@ sub modify_usersessions {
                     }
                 }
                 $resulttext .= '</ul>';
+            } else {
+                $resulttext = $nochgmsg;
+            }
+        } else {
+            $resulttext = '<span class="LC_error">'.
+                          &mt('An error occurred: [_1]',$putresult).'</span>';
+        }
+    } else {
+        $resulttext = $nochgmsg;
+    }
+    return $resulttext;
+}
+
+sub modify_ssl {
+    my ($dom,$lastactref,%domconfig) = @_;
+    my (%by_ip,%by_location,@intdoms,@instdoms);
+    &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
+    my @locations = sort(keys(%by_location));
+    my %servers = &Apache::lonnet::internet_dom_servers($dom);
+    my (%defaultshash,%changes);
+    my $action = 'ssl';
+    my @prefixes = ('connto','connfrom','replication');
+    foreach my $prefix (@prefixes) {
+        $defaultshash{$action}{$prefix} = {};
+    }
+    my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
+    my $resulttext;
+    my %iphost = &Apache::lonnet::get_iphost();
+    my @reptypes = ('certreq','nocertreq');
+    my @connecttypes = ('dom','intdom','other');
+    my %types = (
+                  connto      => \@connecttypes,
+                  connfrom    => \@connecttypes,
+                  replication => \@reptypes,
+                );
+    foreach my $prefix (sort(keys(%types))) {
+        foreach my $type (@{$types{$prefix}}) {
+            if (($prefix eq 'connto') || ($prefix eq 'connfrom')) {
+                my $value = 'yes';
+                if ($env{'form.'.$prefix.'_'.$type} =~ /^(no|req)$/) {
+                    $value = $env{'form.'.$prefix.'_'.$type};
+                }
+                if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
+                    if ($domconfig{$action}{$prefix}{$type} ne '') {
+                        if ($value ne $domconfig{$action}{$prefix}{$type}) {
+                            $changes{$prefix}{$type} = 1;
+                        }
+                        $defaultshash{$action}{$prefix}{$type} = $value;
+                    } else {
+                        $defaultshash{$action}{$prefix}{$type} = $value;
+                        $changes{$prefix}{$type} = 1;
+                    }
+                } else {
+                    $defaultshash{$action}{$prefix}{$type} = $value;
+                    $changes{$prefix}{$type} = 1;
+                }
+                if (($type eq 'dom') && (keys(%servers) == 1)) {
+                    delete($changes{$prefix}{$type});
+                } elsif (($type eq 'intdom') && (@instdoms == 1)) {
+                    delete($changes{$prefix}{$type});
+                } elsif (($type eq 'other') && (keys(%by_location) == 0)) { 
+                    delete($changes{$prefix}{$type});
+                }
+            } elsif ($prefix eq 'replication') {
+                if (@locations > 0) {
+                    my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
+                    my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
+                    my @okvals;
+                    foreach my $val (@vals) {
+                        if ($val =~ /:/) {
+                            my @items = split(/:/,$val);
+                            foreach my $item (@items) {
+                                if (ref($by_location{$item}) eq 'ARRAY') {
+                                    push(@okvals,$item);
+                                }
+                            }
+                        } else {
+                            if (ref($by_location{$val}) eq 'ARRAY') {
+                                push(@okvals,$val);
+                            }
+                        }
+                    }
+                    @okvals = sort(@okvals);
+                    if (ref($domconfig{$action}) eq 'HASH') {
+                        if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
+                            if (ref($domconfig{$action}{$prefix}{$type}) eq 'ARRAY') {
+                                if ($inuse == 0) {
+                                    $changes{$prefix}{$type} = 1;
+                                } else {
+                                    $defaultshash{$action}{$prefix}{$type} = \@okvals;
+                                    my @changed = &Apache::loncommon::compare_arrays($domconfig{$action}{$prefix}{$type},$defaultshash{$action}{$prefix}{$type});
+                                    if (@changed > 0) {
+                                        $changes{$prefix}{$type} = 1;
+                                    }
+                                }
+                            } else {
+                                if ($inuse == 1) {
+                                    $defaultshash{$action}{$prefix}{$type} = \@okvals;
+                                    $changes{$prefix}{$type} = 1;
+                                }
+                            }
+                        } else {
+                            if ($inuse == 1) {
+                                $defaultshash{$action}{$prefix}{$type} = \@okvals;
+                                $changes{$prefix}{$type} = 1;
+                            }
+                        }
+                    } else {
+                        if ($inuse == 1) {
+                            $defaultshash{$action}{$prefix}{$type} = \@okvals;
+                            $changes{$prefix}{$type} = 1;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    my $nochgmsg = &mt('No changes made to LON-CAPA SSL settings');
+    if (keys(%changes) > 0) {
+        my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
+                                                 $dom);
+        if ($putresult eq 'ok') {
+            if (ref($defaultshash{$action}) eq 'HASH') {
+                if (ref($defaultshash{$action}{'replication'}) eq 'HASH') {
+                    $domdefaults{'replication'} = $defaultshash{$action}{'replication'};
+                }
+                if (ref($defaultshash{$action}{'connto'}) eq 'HASH') {
+                    $domdefaults{'connto'} = $domconfig{$action}{'connto'};
+                }
+                if (ref($defaultshash{$action}{'connfrom'}) eq 'HASH') {
+                    $domdefaults{'connfrom'} = $domconfig{$action}{'connfrom'};
+                }
+            }
+            my $cachetime = 24*60*60;
+            &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
+            if (ref($lastactref) eq 'HASH') {
+                $lastactref->{'domdefaults'} = 1;
+            }
+            if (keys(%changes) > 0) {
+                my %titles = &ssl_titles();
+                $resulttext = &mt('Changes made:').'<ul>';
+                foreach my $prefix (@prefixes) {
+                    if (ref($changes{$prefix}) eq 'HASH') {
+                        $resulttext .= '<li>'.$titles{$prefix}.'<ul>';
+                        foreach my $type (@{$types{$prefix}}) {
+                            if (defined($changes{$prefix}{$type})) {
+                                my $newvalue;
+                                if (ref($defaultshash{$action}) eq 'HASH') {
+                                    if (ref($defaultshash{$action}{$prefix})) {
+                                        if (($prefix eq 'connto') || ($prefix eq 'connfrom')) {
+                                            $newvalue = $titles{$defaultshash{$action}{$prefix}{$type}};
+                                        } elsif (ref($defaultshash{$action}{$prefix}{$type}) eq 'ARRAY') {
+                                            if (@{$defaultshash{$action}{$prefix}{$type}} > 0) {
+                                                $newvalue = join(', ',@{$defaultshash{$action}{$prefix}{$type}});
+                                            }
+                                        }
+                                    }
+                                    if ($newvalue eq '') {
+                                        $resulttext .= '<li>'.&mt('[_1] set to: none',$titles{$type}).'</li>';
+                                    } else {
+                                        $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$titles{$type},$newvalue).'</li>';
+                                    }
+                                }
+                            }
+                        }
+                        $resulttext .= '</ul>';
+                    }
+                }
+            } else {
+                $resulttext = $nochgmsg;
+            }
+        } else {
+            $resulttext = '<span class="LC_error">'.
+                          &mt('An error occurred: [_1]',$putresult).'</span>';
+        }
+    } else {
+        $resulttext = $nochgmsg;
+    }
+    return $resulttext;
+}
+
+sub modify_trust {
+    my ($dom,$lastactref,%domconfig) = @_;
+    my (%by_ip,%by_location,@intdoms,@instdoms);
+    &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
+    my @locations = sort(keys(%by_location));
+    my @prefixes = qw(content shared enroll othcoau coaurem domroles catalog reqcrs msg);
+    my @types = ('exc','inc');
+    my (%defaultshash,%changes);
+    foreach my $prefix (@prefixes) {
+        $defaultshash{'trust'}{$prefix} = {};
+    }
+    my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
+    my $resulttext;
+    foreach my $prefix (@prefixes) {
+        foreach my $type (@types) {
+            my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
+            my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
+            my @okvals;
+            foreach my $val (@vals) {
+                if ($val =~ /:/) {
+                    my @items = split(/:/,$val);
+                    foreach my $item (@items) {
+                        if (ref($by_location{$item}) eq 'ARRAY') {
+                            push(@okvals,$item);
+                        }
+                    }
+                } else {
+                    if (ref($by_location{$val}) eq 'ARRAY') {
+                        push(@okvals,$val);
+                    }
+                }
+            }
+            @okvals = sort(@okvals);
+            if (ref($domconfig{'trust'}) eq 'HASH') {
+                if (ref($domconfig{'trust'}{$prefix}) eq 'HASH') {
+                    if (ref($domconfig{'trust'}{$prefix}{$type}) eq 'ARRAY') {
+                        if ($inuse == 0) {
+                            $changes{$prefix}{$type} = 1;
+                        } else {
+                            $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
+                            my @changed = &Apache::loncommon::compare_arrays($domconfig{'trust'}{$prefix}{$type},$defaultshash{'trust'}{$prefix}{$type});
+                            if (@changed > 0) {
+                                $changes{$prefix}{$type} = 1;
+                            }
+                        }
+                    } else {
+                        if ($inuse == 1) {
+                            $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
+                            $changes{$prefix}{$type} = 1;
+                        }
+                    }
+                } else {
+                    if ($inuse == 1) {
+                        $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
+                        $changes{$prefix}{$type} = 1;
+                    }
+                }
+            } else {
+                if ($inuse == 1) {
+                    $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
+                    $changes{$prefix}{$type} = 1;
+                }
+            }
+        }
+    }
+    my $nochgmsg = &mt('No changes made to trust settings.');
+    if (keys(%changes) > 0) {
+        my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
+                                                 $dom);
+        if ($putresult eq 'ok') {
+            if (ref($defaultshash{'trust'}) eq 'HASH') {
+                foreach my $prefix (@prefixes) {
+                    if (ref($defaultshash{'trust'}{$prefix}) eq 'HASH') {
+                        $domdefaults{'trust'.$prefix} = $defaultshash{'trust'}{$prefix};
+                    }
+                }
+            }
+            my $cachetime = 24*60*60;
+            &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
+            if (ref($lastactref) eq 'HASH') {
+                $lastactref->{'domdefaults'} = 1;
+            }
+            if (keys(%changes) > 0) {
+                my %lt = &trust_titles();
+                $resulttext = &mt('Changes made:').'<ul>';
+                foreach my $prefix (@prefixes) {
+                    if (ref($changes{$prefix}) eq 'HASH') {
+                        $resulttext .= '<li>'.$lt{$prefix}.'<ul>';
+                        foreach my $type (@types) {
+                            if (defined($changes{$prefix}{$type})) {
+                                my $newvalue;
+                                if (ref($defaultshash{'trust'}) eq 'HASH') {
+                                    if (ref($defaultshash{'trust'}{$prefix})) {
+                                        if (ref($defaultshash{'trust'}{$prefix}{$type}) eq 'ARRAY') {
+                                            if (@{$defaultshash{'trust'}{$prefix}{$type}} > 0) {
+                                                $newvalue = join(', ',@{$defaultshash{'trust'}{$prefix}{$type}});
+                                            }
+                                        }
+                                    }
+                                }
+                                if ($newvalue eq '') {
+                                    $resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';
+                                } else {
+                                    $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';
+                                }
+                            }
+                        }
+                        $resulttext .= '</ul>';
+                    }
+                }
+                $resulttext .= '</ul>';
             } else {
                 $resulttext = $nochgmsg;
             }