--- loncom/lonnet/perl/lonnet.pm	2020/07/19 15:12:04	1.1172.2.118.2.5
+++ loncom/lonnet/perl/lonnet.pm	2020/10/01 13:19:14	1.1172.2.118.2.8
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1172.2.118.2.5 2020/07/19 15:12:04 raeburn Exp $
+# $Id: lonnet.pm,v 1.1172.2.118.2.8 2020/10/01 13:19:14 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -3110,12 +3110,7 @@ sub unsubscribe {
     } elsif (grep { $_ eq $home } &current_machine_ids()) {
         $answer = 'home';
     } else {
-        my $defdom = $perlvar{'lonDefDomain'};
-        if (&will_trust('content',$defdom,$udom)) {
-            $answer = reply("unsub:$fname",$home);
-        } else {
-            $answer = 'untrusted';
-        }
+        $answer = reply("unsub:$fname",$home);
     }
     return $answer;
 }
@@ -7836,7 +7831,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;
@@ -8061,7 +8056,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 {
@@ -8081,7 +8076,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 {
@@ -8100,7 +8095,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';
@@ -8154,7 +8149,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 {
@@ -8167,7 +8162,7 @@ sub allowed {
                $checkreferer=0;
            }
        }
-       
+
        if ($checkreferer) {
 	  my $refuri=$env{'httpref.'.$orguri};
             unless ($refuri) {
@@ -8196,7 +8191,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 {
@@ -8282,7 +8277,7 @@ sub allowed {
 	   }
        }
     }
-   
+
 #
 # Rest of the restrictions depend on selected course
 #
@@ -8440,6 +8435,10 @@ sub constructaccess {
 #
 # User for whom data are being temporarily cached.
 my $cacheduser='';
+# Course for which data are being temporarily cached.
+my $cachedcid='';
+# List of blocks passed to &get_commblock_resources();
+my $cachedblocks='';
 # Cached blockers for this user (a hash of blocking items).
 my %cachedblockers=();
 # When the data were last cached.
@@ -8449,13 +8448,22 @@ sub load_all_blockers {
     my ($uname,$udom,$blocks)=@_;
     if (($uname ne '') && ($udom ne '')) {
         if (($cacheduser eq $uname.':'.$udom) &&
-            (abs($cachedlast-time)<5)) {
+            ($cachedcid eq $env{'request.course.id'}) &&
+            (abs($cachedlast-time)<5) &&
+            (((ref($blocks) eq 'HASH') &&
+              ($cachedblocks eq join(',',sort(keys(%{$blocks}))))) ||
+             (!ref($blocks) && $cachedblocks eq ''))) {
             return;
         }
     }
     $cachedlast=time;
     $cacheduser=$uname.':'.$udom;
+    $cachedcid=$env{'request.course.id'};
     %cachedblockers = &get_commblock_resources($blocks);
+    if ((ref($blocks) eq 'HASH') && (keys(%{$blocks}) > 0)) {
+        $cachedblocks = join(',',sort(keys(%{$blocks})));
+    }
+    return;
 }
 
 sub get_comm_blocks {
@@ -8593,7 +8601,7 @@ sub get_commblock_resources {
 }
 
 sub has_comm_blocking {
-    my ($priv,$symb,$uri,$blocks) = @_;
+    my ($priv,$symb,$uri,$nosymbcache,$noenccheck,$blocked,$blocks) = @_;
     my @blockers;
     return unless ($env{'request.course.id'});
     return unless ($priv eq 'bre');
@@ -8603,7 +8611,7 @@ sub has_comm_blocking {
     return unless (keys(%cachedblockers) > 0);
     my (%possibles,@symbs);
     if (!$symb) {
-        $symb = &symbread($uri,1,1,1,\%possibles);
+        $symb = &symbread($uri,1,1,1,\%possibles,$nosymbcache,$noenccheck);
     }
     if ($symb) {
         @symbs = ($symb);
@@ -8617,9 +8625,11 @@ sub has_comm_blocking {
         foreach my $block (keys(%cachedblockers)) {
             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') {
@@ -8630,18 +8640,20 @@ sub has_comm_blocking {
                         }
                     }
                 }
-            }
-            if (ref($cachedblockers{$block}{'maps'}) eq 'HASH') {
-                if ($cachedblockers{$block}{'maps'}{$map}) {
-                    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);
+                        }
                     }
                 }
             }
         }
     }
-    return if ($noblock);
-    return @blockers;
+    unless ($noblock) {
+        return @blockers;
+    }
+    return;
 }
 }
 
@@ -10287,14 +10299,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;
             }
@@ -11322,10 +11339,8 @@ 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;
@@ -12511,19 +12526,26 @@ sub deversion {
 # ------------------------------------------------------ Return symb list entry
 
 sub symbread {
-    my ($thisfn,$donotrecurse,$ignorecachednull,$checkforblock,$possibles)=@_;
+    my ($thisfn,$donotrecurse,$ignorecachednull,$checkforblock,$possibles,
+        $nocache,$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};
+    if (defined($env{$cache_str}) && !$nocache) {
+        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
     unless ($thisfn) {
         if ($env{'request.symb'}) {
-            return $env{$cache_str}=&symbclean($env{'request.symb'});
+            if ($nocache) {
+                return &symbclean($env{'request.symb'});
+            } else {
+                return $env{$cache_str}=&symbclean($env{'request.symb'});
+            }
         }
         $thisfn=$env{'request.filename'};
     }
@@ -12531,7 +12553,11 @@ sub symbread {
 # is that filename actually a symb? Verify, clean, and return
     if ($thisfn=~/\_\_\_\d+\_\_\_(.*)$/) {
 	if (&symbverify($thisfn,$1)) {
-	    return $env{$cache_str}=&symbclean($thisfn);
+            if ($nocache) {
+                return &symbclean($thisfn);
+            } else {
+	        return $env{$cache_str}=&symbclean($thisfn);
+            }
 	}
     }
     $thisfn=declutter($thisfn);
@@ -12546,10 +12572,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 ($nocache) {
+            if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
+                          &GDBM_READER(),0640)) {
+	        $syval=$hash{$targetfn};
+                untie(%hash);
+            }
+            if ($syval) {
+                my @blockers = &has_comm_blocking('bre',$syval,$thisfn,$nocache,$noenccheck);
+                if (@blockers) {
+                    $syval='';
+                }
+            }
         }
 # ---------------------------------------------------------- There was an entry
         if ($syval) {
@@ -12582,13 +12616,19 @@ 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 '' if ($nocache);
+                                 return $env{$cache_str}='';
+                             }
                          }
                      }
                  } elsif ((!$donotrecurse) || ($checkforblock) || (ref($possibles) eq 'HASH')) {
@@ -12607,12 +12647,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++;
                                      }
@@ -12620,6 +12661,11 @@ sub symbread {
                                      $syval = $poss_syval;
                                      $realpossible++;
                                  }
+                                 if ($syval) {
+                                     if (ref($possibles) eq 'HASH') {
+                                         $possibles->{$syval} = 1;
+                                     }
+                                 }
                              }
 			 }
                      }
@@ -12632,10 +12678,15 @@ sub symbread {
            }
         }
         if ($syval) {
-	    return $env{$cache_str}=$syval;
+            if ($nocache) {
+                return $syval;
+            } else {
+	        return $env{$cache_str}=$syval;
+            }
         }
     }
     &appenv({'request.ambiguous' => $thisfn});
+    return '' if ($nocache);
     return $env{$cache_str}='';
 }