--- loncom/lonnet/perl/lonnet.pm	2020/01/17 16:49:28	1.1172.2.118.2.1
+++ loncom/lonnet/perl/lonnet.pm	2020/11/24 16:57:37	1.1172.2.118.2.12
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1172.2.118.2.1 2020/01/17 16:49:28 raeburn Exp $
+# $Id: lonnet.pm,v 1.1172.2.118.2.12 2020/11/24 16:57:37 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -263,9 +263,10 @@ sub get_server_loncaparev {
                 if ($caller eq 'loncron') {
                     my $ua=new LWP::UserAgent;
                     $ua->timeout(4);
+                    my $hostname = &hostname($lonhost);
                     my $protocol = $protocol{$lonhost};
                     $protocol = 'http' if ($protocol ne 'https');
-                    my $url = $protocol.'://'.&hostname($lonhost).'/adm/about.html';
+                    my $url = $protocol.'://'.$hostname.'/adm/about.html';
                     my $request=new HTTP::Request('GET',$url);
                     my $response=$ua->request($request);
                     unless ($response->is_error()) {
@@ -953,13 +954,13 @@ sub spareserver {
     }
 
     if (!$want_server_name) {
-        my $protocol = 'http';
-        if ($protocol{$spare_server} eq 'https') {
-            $protocol = $protocol{$spare_server};
-        }
         if (defined($spare_server)) {
             my $hostname = &hostname($spare_server);
             if (defined($hostname)) {
+                my $protocol = 'http';
+                if ($protocol{$spare_server} eq 'https') {
+                    $protocol = $protocol{$spare_server};
+                }
 	        $spare_server = $protocol.'://'.$hostname;
             }
         }
@@ -1081,6 +1082,21 @@ sub check_for_balancer_cookie {
     return ($otherserver,$cookie);
 }
 
+sub updatebalcookie {
+    my ($cookie,$balancer,$lastentry)=@_;
+    if ($cookie =~ /^($match_domain)\_($match_username)\_[a-f0-9]{32}$/) {
+        my ($udom,$uname) = ($1,$2);
+        my $uprimary_id = &domain($udom,'primary');
+        my $uintdom = &internet_dom($uprimary_id);
+        my $intdom = &internet_dom($balancer);
+        my $serverhomedom = &host_domain($balancer);
+        if (($uintdom ne '') && ($uintdom eq $intdom)) {
+            return &reply('updatebalcookie:'.&escape($cookie).':'.&escape($lastentry),$balancer);
+        }
+    }
+    return;
+}
+
 sub delbalcookie {
     my ($cookie,$balancer) =@_;
     if ($cookie =~ /^($match_domain)\_($match_username)\_[a-f0-9]{32}$/) {
@@ -1090,7 +1106,7 @@ sub delbalcookie {
         my $intdom = &internet_dom($balancer);
         my $serverhomedom = &host_domain($balancer);
         if (($uintdom ne '') && ($uintdom eq $intdom)) {
-            return &reply("delbalcookie:$cookie",$balancer);
+            return &reply('delbalcookie:'.&escape($cookie),$balancer);
         }
     }
 }
@@ -1161,6 +1177,28 @@ sub choose_server {
     return ($login_host,$hostname,$portal_path,$isredirect,$lowest_load);
 }
 
+sub get_course_sessions {
+    my ($cnum,$cdom,$lastactivity) = @_;
+    my %servers = &internet_dom_servers($cdom);
+    my %returnhash;
+    foreach my $server (sort(keys(%servers))) {
+        my $rep = &reply("coursesessions:$cdom:$cnum:$lastactivity",$server);
+        my @pairs=split(/\&/,$rep);
+        unless (($rep eq 'unknown_cmd') || ($rep =~ /^error/)) {
+            foreach my $item (@pairs) {
+                my ($key,$value)=split(/=/,$item,2);
+                $key = &unescape($key);
+                next if ($key =~ /^error: 2 /);
+                if (exists($returnhash{$key})) {
+                    next if ($value < $returnhash{$key});
+                }
+                $returnhash{$key}=$value;
+            }
+        }
+    }
+    return %returnhash;
+}
+
 # --------------------------------------------- Try to change a user's password
 
 sub changepass {
@@ -1555,7 +1593,7 @@ sub check_loadbalancing {
     if ($domneedscache) {
         &do_cache_new('loadbalancing',$domneedscache,$is_balancer,$cachetime);
     }
-    if ($is_balancer) {
+    if (($is_balancer) && ($caller ne 'switchserver')) {
         my $lowest_load = 30000;
         if (ref($offloadto) eq 'HASH') {
             if (ref($offloadto->{'primary'}) eq 'ARRAY') {
@@ -1595,9 +1633,9 @@ sub check_loadbalancing {
                 }
             }
         }
-        unless ($homeintdom) {
-            undef($setcookie);
-        }
+    }
+    if (($is_balancer) && (!$homeintdom)) {
+        undef($setcookie);
     }
     return ($is_balancer,$otherserver,$setcookie);
 }
@@ -2049,7 +2087,7 @@ sub usersearch {
             unless ($tryserver eq $perlvar{'lonHostID'}) {
                 if ($srch->{'srchby'} eq 'email') {
                     my $lcrev = &get_server_loncaparev($dom,$tryserver);
-                    my ($major,$minor,$subver) = ($lcrev =~ /^\'?(\d+)\.(\d+)\.(\d+)[\w.\-]+)\'?$/);
+                    my ($major,$minor,$subver) = ($lcrev =~ /^\'?(\d+)\.(\d+)\.(\d+)[\w.\-]+\'?$/);
                     next if (($major eq '' && $minor eq '') || ($major < 2) ||
                              (($major == 2) && ($minor < 11)) ||
                              (($major == 2) && ($minor == 11) && ($subver < 3)));
@@ -3071,6 +3109,27 @@ sub repcopy {
     }
 }
 
+# ------------------------------------------------- Unsubscribe from a resource
+
+sub unsubscribe {
+    my ($fname) = @_;
+    my $answer;
+    if ($fname=~/\/(aboutme|syllabus|bulletinboard|smppg)$/) { return $answer; }
+    $fname=~s/[\n\r]//g;
+    my $author=$fname;
+    $author=~s/\/home\/httpd\/html\/res\/([^\/]*)\/([^\/]*).*/$1\/$2/;
+    my ($udom,$uname)=split(/\//,$author);
+    my $home=homeserver($uname,$udom);
+    if ($home eq 'no_host') {
+        $answer = 'no_host';
+    } elsif (grep { $_ eq $home } &current_machine_ids()) {
+        $answer = 'home';
+    } else {
+        $answer = reply("unsub:$fname",$home);
+    }
+    return $answer;
+}
+
 # ------------------------------------------------ Get server side include body
 sub ssi_body {
     my ($filelink,%form)=@_;
@@ -3197,13 +3256,13 @@ sub remove_stale_resfile {
                     (grep { $_ eq $homeserver } &current_machine_ids())) {
                 my $fname = &filelocation('',$url);
                 if (-e $fname) {
-                    my $ua=new LWP::UserAgent;
-                    $ua->timeout(5);
-                    my $protocol = $protocol{$homeserver};
-                    $protocol = 'http' if ($protocol ne 'https');
                     my $hostname = &hostname($homeserver);
                     if ($hostname) {
+                        my $protocol = $protocol{$homeserver};
+                        $protocol = 'http' if ($protocol ne 'https');
                         my $uri = $protocol.'://'.$hostname.'/raw/'.&declutter($url);
+                        my $ua=new LWP::UserAgent;
+                        $ua->timeout(5);
                         my $request=new HTTP::Request('HEAD',$uri);
                         my $response=$ua->request($request);
                         if ($response->is_success()) {
@@ -3229,12 +3288,18 @@ sub remove_stale_resfile {
                                     $stale = 1;
                                 }
                                 if ($stale) {
-                                    unlink($fname);
-                                    if ($uri!~/\.meta$/) {
-                                        unlink($fname.'.meta');
+                                    if (unlink($fname)) {
+                                        if ($uri!~/\.meta$/) {
+                                            if (-e $fname.'.meta') {
+                                                unlink($fname.'.meta');
+                                            }
+                                        }
+                                        my $unsubresult = &unsubscribe($fname);
+                                        unless ($unsubresult eq 'ok') {
+                                            &logthis("no unsub of $fname from $homeserver, reason: $unsubresult");
+                                        }
+                                        $removed = 1;
                                     }
-                                    &reply("unsub:$fname",$homeserver);
-                                    $removed = 1;
                                 }
                             }
                         }
@@ -3384,6 +3449,18 @@ sub can_edit_resource {
                         $forceedit = 1;
                     }
                     $cfile = $resurl;
+                } elsif (($resurl =~ m{^/ext/}) && ($symb ne '')) {
+                    my ($map,$id,$res) = &decode_symb($symb);
+                    if ($map =~ /\.page$/) {
+                        $incourse = 1;
+                        if ($env{'form.forceedit'}) {
+                            $forceview = 1;
+                            $cfile = $map;
+                        } else {
+                            $forceedit = 1;
+                            $cfile =  '/adm/wrapper'.$resurl;
+                        }
+                    }
                 } elsif ($resurl =~ m{^/adm/wrapper/adm/$cdom/$cnum/\d+/ext\.tool$}) {
                     $incourse = 1;
                     if ($env{'form.forceedit'}) {
@@ -4656,7 +4733,11 @@ sub courseacclog {
                 if ($formitem =~ /^HWFILE(?:SIZE|TOOBIG)/) {
                     $what.=':'.$formitem.'='.$env{$key};
                 } elsif ($formitem !~ /^HWFILE(?:[^.]+)$/) {
-                    $what.=':'.$formitem.'='.$env{$key};
+                    if ($formitem eq 'proctorpassword') {
+                        $what.=':'.$formitem.'=' . '*' x length($env{$key});
+                    } else {
+                        $what.=':'.$formitem.'='.$env{$key};
+                    }
                 }
             }
         }
@@ -7769,7 +7850,7 @@ sub customaccess {
 # ------------------------------------------------- Check for a user privilege
 
 sub allowed {
-    my ($priv,$uri,$symb,$role,$clientip,$noblockcheck)=@_;
+    my ($priv,$uri,$symb,$role,$clientip,$noblockcheck,$ignorecache)=@_;
     my $ver_orguri=$uri;
     $uri=&deversion($uri);
     my $orguri=$uri;
@@ -7994,7 +8075,7 @@ sub allowed {
                 if ($noblockcheck) {
                     $thisallowed.=$value;
                 } else {
-                    my @blockers = &has_comm_blocking($priv,$symb,$uri);
+                    my @blockers = &has_comm_blocking($priv,$symb,$uri,$ignorecache);
                     if (@blockers > 0) {
                         $thisallowed = 'B';
                     } else {
@@ -8014,7 +8095,7 @@ sub allowed {
                         if ($noblockcheck) {
                             $thisallowed='F';
                         } else {
-                            my @blockers = &has_comm_blocking($priv,$symb,$refuri);
+                            my @blockers = &has_comm_blocking($priv,'',$refuri,'',1);
                             if (@blockers > 0) {
                                 $thisallowed = 'B';
                             } else {
@@ -8033,7 +8114,7 @@ sub allowed {
 	&& &is_portfolio_url($uri)) {
 	$thisallowed = &portfolio_access($uri,$clientip);
     }
-    
+
 # Full access at system, domain or course-wide level? Exit.
     if ($thisallowed=~/F/) {
 	return 'F';
@@ -8087,7 +8168,7 @@ sub allowed {
                    if ($noblockcheck) {
                        $thisallowed.=$value;
                    } else {
-                       my @blockers = &has_comm_blocking($priv,$symb,$uri);
+                       my @blockers = &has_comm_blocking($priv,$symb,$uri,$ignorecache);
                        if (@blockers > 0) {
                            $thisallowed = 'B';
                        } else {
@@ -8100,7 +8181,7 @@ sub allowed {
                $checkreferer=0;
            }
        }
-       
+
        if ($checkreferer) {
 	  my $refuri=$env{'httpref.'.$orguri};
             unless ($refuri) {
@@ -8129,7 +8210,7 @@ sub allowed {
                       if ($noblockcheck) {
                           $thisallowed.=$value;
                       } else {
-                          my @blockers = &has_comm_blocking($priv,$symb,$refuri);
+                          my @blockers = &has_comm_blocking($priv,'',$refuri,'',1);
                           if (@blockers > 0) {
                               $thisallowed = 'B';
                           } else {
@@ -8215,7 +8296,7 @@ sub allowed {
 	   }
        }
     }
-   
+
 #
 # Rest of the restrictions depend on selected course
 #
@@ -8373,22 +8454,27 @@ sub constructaccess {
 #
 # User for whom data are being temporarily cached.
 my $cacheduser='';
+# Course for which data are being temporarily cached.
+my $cachedcid='';
 # Cached blockers for this user (a hash of blocking items).
 my %cachedblockers=();
 # When the data were last cached.
 my $cachedlast='';
 
 sub load_all_blockers {
-    my ($uname,$udom,$blocks)=@_;
+    my ($uname,$udom)=@_;
     if (($uname ne '') && ($udom ne '')) {
         if (($cacheduser eq $uname.':'.$udom) &&
+            ($cachedcid eq $env{'request.course.id'}) &&
             (abs($cachedlast-time)<5)) {
             return;
         }
     }
     $cachedlast=time;
     $cacheduser=$uname.':'.$udom;
-    %cachedblockers = &get_commblock_resources($blocks);
+    $cachedcid=$env{'request.course.id'};
+    %cachedblockers = &get_commblock_resources();
+    return;
 }
 
 sub get_comm_blocks {
@@ -8468,14 +8554,23 @@ sub get_commblock_resources {
                             if ($mapsymb) {
                                 if (ref($navmap)) {
                                     my $mapres = $navmap->getBySymb($mapsymb);
-                                    @to_test = $mapres->retrieveResources($mapres,undef,0,0,0,1);
-                                    foreach my $res (@to_test) {
-                                        my $symb = $res->symb();
-                                        next if ($symb eq $mapsymb);
-                                        if ($symb ne '') {
-                                            @interval=&EXT("resource.0.interval",$symb);
-                                            if ($interval[1] eq 'map') {
-                                                last;
+                                    if (ref($mapres)) {
+                                        my $first = $mapres->map_start();
+                                        my $finish = $mapres->map_finish();
+                                        my $it = $navmap->getIterator($first,$finish,undef,0,0);
+                                        if (ref($it)) {
+                                            my $res;
+                                            while ($res = $it->next(undef,1)) {
+                                                next unless (ref($res));
+                                                my $symb = $res->symb();
+                                                next if (($symb eq $mapsymb) || ($symb eq ''));
+                                                @interval=&EXT("resource.0.interval",$symb);
+                                                if ($interval[1] eq 'map') {
+                                                    if ($res->answerable()) {
+                                                        push(@to_test,$res);
+                                                        last;
+                                                    }
+                                                }
                                             }
                                         }
                                     }
@@ -8526,17 +8621,23 @@ sub get_commblock_resources {
 }
 
 sub has_comm_blocking {
-    my ($priv,$symb,$uri,$blocks) = @_;
+    my ($priv,$symb,$uri,$ignoresymbdb,$noenccheck,$blocked,$blocks) = @_;
     my @blockers;
     return unless ($env{'request.course.id'});
     return unless ($priv eq 'bre');
     return if ($env{'user.priv.'.$env{'request.role'}} =~/evb\&([^\:]*)/);
     return if ($env{'request.state'} eq 'construct');
-    &load_all_blockers($env{'user.name'},$env{'user.domain'},$blocks);
-    return unless (keys(%cachedblockers) > 0);
+    my %blockinfo;
+    if (ref($blocks) eq 'HASH') {
+        %blockinfo = &get_commblock_resources($blocks);
+    } else {
+        &load_all_blockers($env{'user.name'},$env{'user.domain'});
+        %blockinfo = %cachedblockers;
+    }
+    return unless (keys(%blockinfo) > 0);
     my (%possibles,@symbs);
     if (!$symb) {
-        $symb = &symbread($uri,1,1,1,\%possibles);
+        $symb = &symbread($uri,1,1,1,\%possibles,$ignoresymbdb,$noenccheck);
     }
     if ($symb) {
         @symbs = ($symb);
@@ -8547,34 +8648,38 @@ sub has_comm_blocking {
     foreach my $symb (@symbs) {
         last if ($noblock);
         my ($map,$resid,$resurl)=&decode_symb($symb);
-        foreach my $block (keys(%cachedblockers)) {
+        foreach my $block (keys(%blockinfo)) {
             if ($block =~ /^firstaccess____(.+)$/) {
                 my $item = $1;
-                if (($item eq $map) || ($item eq $symb)) {
-                    $noblock = 1;
-                    last;
+                unless ($blocked) {
+                    if (($item eq $map) || ($item eq $symb)) {
+                        $noblock = 1;
+                        last;
+                    }
                 }
             }
-            if (ref($cachedblockers{$block}) eq 'HASH') {
-                if (ref($cachedblockers{$block}{'resources'}) eq 'HASH') {
-                    if ($cachedblockers{$block}{'resources'}{$symb}) {
+            if (ref($blockinfo{$block}) eq 'HASH') {
+                if (ref($blockinfo{$block}{'resources'}) eq 'HASH') {
+                    if ($blockinfo{$block}{'resources'}{$symb}) {
                         unless (grep(/^\Q$block\E$/,@blockers)) {
                             push(@blockers,$block);
                         }
                     }
                 }
-            }
-            if (ref($cachedblockers{$block}{'maps'}) eq 'HASH') {
-                if ($cachedblockers{$block}{'maps'}{$map}) {
-                    unless (grep(/^\Q$block\E$/,@blockers)) {
-                        push(@blockers,$block);
+                if (ref($blockinfo{$block}{'maps'}) eq 'HASH') {
+                    if ($blockinfo{$block}{'maps'}{$map}) {
+                        unless (grep(/^\Q$block\E$/,@blockers)) {
+                            push(@blockers,$block);
+                        }
                     }
                 }
             }
         }
     }
-    return if ($noblock);
-    return @blockers;
+    unless ($noblock) {
+        return @blockers;
+    }
+    return;
 }
 }
 
@@ -10220,14 +10325,19 @@ sub writecoursepref {
 
 sub createcourse {
     my ($udom,$description,$url,$course_server,$nonstandard,$inst_code,
-        $course_owner,$crstype,$cnum,$context,$category)=@_;
+        $course_owner,$crstype,$cnum,$context,$category,$callercontext)=@_;
     $url=&declutter($url);
     my $cid='';
     if ($context eq 'requestcourses') {
         my $can_create = 0;
         my ($ownername,$ownerdom) = split(':',$course_owner);
         if ($udom eq $ownerdom) {
-            if (&usertools_access($ownername,$ownerdom,$category,undef,
+            my $reload;
+            if (($callercontext eq 'auto') &&
+               ($ownerdom eq $env{'user.domain'}) && ($ownername eq $env{'user.name'})) {
+                $reload = 'reload';
+            }
+            if (&usertools_access($ownername,$ownerdom,$category,$reload,
                                   $context)) {
                 $can_create = 1;
             }
@@ -11255,42 +11365,47 @@ sub resdata {
     }
     if (!ref($result)) { return $result; }    
     foreach my $item (@which) {
-        if (ref($item) eq 'ARRAY') {
-	    if (defined($result->{$item->[0]})) {
-	        return [$result->{$item->[0]},$item->[1]];
-	    }
+	if (defined($result->{$item->[0]})) {
+	    return [$result->{$item->[0]},$item->[1]];
         }
     }
     return undef;
 }
 
-sub get_domain_ltitools {
-    my ($cdom) = @_;
-    my %ltitools;
-    my ($result,$cached)=&is_cached_new('ltitools',$cdom);
+sub get_domain_lti {
+    my ($cdom,$context) = @_;
+    my ($name,%lti);
+    if ($context eq 'consumer') {
+        $name = 'ltitools';
+    } elsif ($context eq 'provider') {
+        $name = 'lti';
+    } else {
+        return %lti;
+    }
+    my ($result,$cached)=&is_cached_new($name,$cdom);
     if (defined($cached)) {
         if (ref($result) eq 'HASH') {
-            %ltitools = %{$result};
+            %lti = %{$result};
         }
     } else {
-        my %domconfig = &get_dom('configuration',['ltitools'],$cdom);
-        if (ref($domconfig{'ltitools'}) eq 'HASH') {
-            %ltitools = %{$domconfig{'ltitools'}};
-            my %encdomconfig = &get_dom('encconfig',['ltitools'],$cdom);
-            if (ref($encdomconfig{'ltitools'}) eq 'HASH') {
-                foreach my $id (keys(%ltitools)) {
-                    if (ref($encdomconfig{'ltitools'}{$id}) eq 'HASH') {
+        my %domconfig = &get_dom('configuration',[$name],$cdom);
+        if (ref($domconfig{$name}) eq 'HASH') {
+            %lti = %{$domconfig{$name}};
+            my %encdomconfig = &get_dom('encconfig',[$name],$cdom);
+            if (ref($encdomconfig{$name}) eq 'HASH') {
+                foreach my $id (keys(%lti)) {
+                    if (ref($encdomconfig{$name}{$id}) eq 'HASH') {
                         foreach my $item ('key','secret') {
-                            $ltitools{$id}{$item} = $encdomconfig{'ltitools'}{$id}{$item};
+                            $lti{$id}{$item} = $encdomconfig{$name}{$id}{$item};
                         }
                     }
                 }
             }
         }
         my $cachetime = 24*60*60;
-        &do_cache_new('ltitools',$cdom,\%ltitools,$cachetime);
+        &do_cache_new($name,$cdom,\%lti,$cachetime);
     }
-    return %ltitools;
+    return %lti;
 }
 
 sub get_numsuppfiles {
@@ -12335,18 +12450,16 @@ sub symbverify {
 
     if (tie(%bighash,'GDBM_File',$env{'request.course.fn'}.'.db',
                             &GDBM_READER(),0640)) {
-        my $noclutter;
         if (($thisurl =~ m{^/adm/wrapper/ext/}) || ($thisurl =~ m{^ext/})) {
             $thisurl =~ s/\?.+$//;
             if ($map =~ m{^uploaded/.+\.page$}) {
                 $thisurl =~ s{^(/adm/wrapper|)/ext/}{http://};
                 $thisurl =~ s{^\Qhttp://https://\E}{https://};
-                $noclutter = 1;
             }
         }
         my $ids;
-        if ($noclutter) {
-            $ids=$bighash{'ids_'.$thisurl};
+        if ($map =~ m{^uploaded/.+\.page$}) {
+            $ids=$bighash{'ids_'.&clutter_with_no_wrapper($thisurl)};
         } else {
             $ids=$bighash{'ids_'.&clutter($thisurl)};
         }
@@ -12446,13 +12559,16 @@ sub deversion {
 # ------------------------------------------------------ Return symb list entry
 
 sub symbread {
-    my ($thisfn,$donotrecurse,$ignorecachednull,$checkforblock,$possibles)=@_;
+    my ($thisfn,$donotrecurse,$ignorecachednull,$checkforblock,$possibles,
+        $ignoresymbdb,$noenccheck)=@_;
     my $cache_str='request.symbread.cached.'.$thisfn;
     if (defined($env{$cache_str})) {
-        if ($ignorecachednull) {
-            return $env{$cache_str} unless ($env{$cache_str} eq '');
-        } else {
-            return $env{$cache_str};
+        unless (ref($possibles) eq 'HASH') {
+            if ($ignorecachednull) {
+                return $env{$cache_str} unless ($env{$cache_str} eq '');
+            } else {
+                return $env{$cache_str};
+            }
         }
     }
 # no filename provided? try from environment
@@ -12481,10 +12597,18 @@ sub symbread {
 	if ($targetfn =~ m|^adm/wrapper/(ext/.*)|) {
 	    $targetfn=$1;
 	}
-        if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
-                      &GDBM_READER(),0640)) {
-	    $syval=$hash{$targetfn};
-            untie(%hash);
+        unless ($ignoresymbdb) {
+            if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
+                          &GDBM_READER(),0640)) {
+	        $syval=$hash{$targetfn};
+                untie(%hash);
+            }
+            if ($syval && $checkforblock) {
+                my @blockers = &has_comm_blocking('bre',$syval,$thisfn,$ignoresymbdb,$noenccheck);
+                if (@blockers) {
+                    $syval='';
+                }
+            }
         }
 # ---------------------------------------------------------- There was an entry
         if ($syval) {
@@ -12517,13 +12641,18 @@ sub symbread {
 		     $syval=&encode_symb($bighash{'map_id_'.$mapid},
 						    $resid,$thisfn);
                      if (ref($possibles) eq 'HASH') {
-                         $possibles->{$syval} = 1;
+                         unless ($bighash{'randomout_'.$ids} || $env{'request.role.adv'}) {
+                             $possibles->{$syval} = 1;
+                         }
                      }
                      if ($checkforblock) {
-                         my @blockers = &has_comm_blocking('bre',$syval,$bighash{'src_'.$ids});
-                         if (@blockers) {
-                             $syval = '';
-                             return;
+                         unless ($bighash{'randomout_'.$ids} || $env{'request.role.adv'}) {
+                             my @blockers = &has_comm_blocking('bre',$syval,$bighash{'src_'.$ids},'',$noenccheck);
+                             if (@blockers) {
+                                 $syval = '';
+                                 untie(%bighash);
+                                 return $env{$cache_str}='';
+                             }
                          }
                      }
                  } elsif ((!$donotrecurse) || ($checkforblock) || (ref($possibles) eq 'HASH')) {
@@ -12542,12 +12671,13 @@ sub symbread {
                              if ($bighash{'map_type_'.$mapid} ne 'page') {
                                  my $poss_syval=&encode_symb($bighash{'map_id_'.$mapid},
                                                              $resid,$thisfn);
-                                 if (ref($possibles) eq 'HASH') {
-                                     $possibles->{$syval} = 1;
-                                 }
+                                 next if ($bighash{'randomout_'.$id} && !$env{'request.role.adv'});
+                                 next unless (($noenccheck) || ($bighash{'encrypted_'.$id} eq $env{'request.enc'}));
                                  if ($checkforblock) {
-                                     my @blockers = &has_comm_blocking('bre',$poss_syval,$file);
-                                     unless (@blockers > 0) {
+                                     my @blockers = &has_comm_blocking('bre',$poss_syval,$file,'',$noenccheck);
+                                     if (@blockers > 0) {
+                                         $syval = '';
+                                     } else {
                                          $syval = $poss_syval;
                                          $realpossible++;
                                      }
@@ -12555,6 +12685,11 @@ sub symbread {
                                      $syval = $poss_syval;
                                      $realpossible++;
                                  }
+                                 if ($syval) {
+                                     if (ref($possibles) eq 'HASH') {
+                                         $possibles->{$syval} = 1;
+                                     }
+                                 }
                              }
 			 }
                      }
@@ -13092,9 +13227,10 @@ sub repcopy_userfile {
     my $request;
     $uri=~s/^\///;
     my $homeserver = &homeserver($cnum,$cdom);
+    my $hostname = &hostname($homeserver);
     my $protocol = $protocol{$homeserver};
     $protocol = 'http' if ($protocol ne 'https');
-    $request=new HTTP::Request('GET',$protocol.'://'.&hostname($homeserver).'/raw/'.$uri);
+    $request=new HTTP::Request('GET',$protocol.'://'.$hostname.'/raw/'.$uri);
     my $response=$ua->request($request,$transferfile);
 # did it work?
     if ($response->is_error()) {
@@ -13118,9 +13254,10 @@ sub tokenwrapper {
 	$file=~s|(\?\.*)*$||;
         &appenv({"userfile.$udom/$uname/$file" => $env{'request.course.id'}});
         my $homeserver = &homeserver($uname,$udom);
+        my $hostname = &hostname($homeserver);
         my $protocol = $protocol{$homeserver};
         $protocol = 'http' if ($protocol ne 'https');
-        return $protocol.'://'.&hostname($homeserver).'/'.$uri.
+        return $protocol.'://'.$hostname.'/'.$uri.
                (($uri=~/\?/)?'&':'?').'token='.$token.
                                '&tokenissued='.$perlvar{'lonHostID'};
     } else {
@@ -13136,9 +13273,10 @@ sub getuploaded {
     my ($reqtype,$uri,$cdom,$cnum,$info,$rtncode) = @_;
     $uri=~s/^\///;
     my $homeserver = &homeserver($cnum,$cdom);
+    my $hostname = &hostname($homeserver);
     my $protocol = $protocol{$homeserver};
     $protocol = 'http' if ($protocol ne 'https');
-    $uri = $protocol.'://'.&hostname($homeserver).'/raw/'.$uri;
+    $uri = $protocol.'://'.$hostname.'/raw/'.$uri;
     my $ua=new LWP::UserAgent;
     my $request=new HTTP::Request($reqtype,$uri);
     my $response=$ua->request($request);
@@ -13313,6 +13451,45 @@ sub shared_institution {
     return $same_intdom;
 }
 
+sub uses_sts {
+    my ($ignore_cache) = @_;
+    my $lonhost = $perlvar{'lonHostID'};
+    my $hostname = &hostname($lonhost);
+    my $sts_on;
+    if ($protocol{$lonhost} eq 'https') {
+        my $cachetime = 12*3600;
+        if (!$ignore_cache) {
+            ($sts_on,my $cached)=&is_cached_new('stspolicy',$lonhost);
+            if (defined($cached)) {
+                return $sts_on;
+            }
+        }
+        my $ua=new LWP::UserAgent;
+        my $url = $protocol{$lonhost}.'://'.$hostname.'/index.html';
+        my $request=new HTTP::Request('HEAD',$url);
+        my $response=$ua->request($request);
+        if ($response->is_success) {
+            my $has_sts = $response->header('Strict-Transport-Security');
+            if ($has_sts eq '') {
+                $sts_on = 0;
+            } else {
+                if ($has_sts =~ /\Qmax-age=\E(\d+)/) {
+                    my $maxage = $1;
+                    if ($maxage) {
+                        $sts_on = 1;
+                    } else {
+                        $sts_on = 0;
+                    }
+                } else {
+                    $sts_on = 0;
+                }
+            }
+            return &do_cache_new('stspolicy',$lonhost,$sts_on,$cachetime);
+        }
+    }
+    return;
+}
+
 # ------------------------------------------------------------- Declutters URLs
 
 sub declutter {