--- loncom/lonnet/perl/lonnet.pm	2021/11/09 21:04:30	1.1172.2.140.2.3
+++ loncom/lonnet/perl/lonnet.pm	2021/06/20 16:39:27	1.1172.2.141
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1172.2.140.2.3 2021/11/09 21:04:30 raeburn Exp $
+# $Id: lonnet.pm,v 1.1172.2.141 2021/06/20 16:39:27 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -5470,10 +5470,9 @@ my %cachedtimes=();
 my $cachedtime='';
 
 sub load_all_first_access {
-    my ($uname,$udom,$ignorecache)=@_;
+    my ($uname,$udom)=@_;
     if (($cachedkey eq $uname.':'.$udom) &&
-        (abs($cachedtime-time)<5) && (!$env{'form.markaccess'}) &&
-        (!$ignorecache)) {
+        (abs($cachedtime-time)<5) && (!$env{'form.markaccess'})) {
         return;
     }
     $cachedtime=time;
@@ -5482,7 +5481,7 @@ sub load_all_first_access {
 }
 
 sub get_first_access {
-    my ($type,$argsymb,$argmap,$ignorecache)=@_;
+    my ($type,$argsymb,$argmap)=@_;
     my ($symb,$courseid,$udom,$uname)=&whichuser();
     if ($argsymb) { $symb=$argsymb; }
     my ($map,$id,$res)=&decode_symb($symb);
@@ -5494,7 +5493,7 @@ sub get_first_access {
     } else {
 	$res=$symb;
     }
-    &load_all_first_access($uname,$udom,$ignorecache);
+    &load_all_first_access($uname,$udom);
     return $cachedtimes{"$courseid\0$res"};
 }
 
@@ -8481,11 +8480,7 @@ sub get_commblock_resources {
     my ($blocks) = @_;
     my %blockers = ();
     return %blockers unless ($env{'request.course.id'});
-    my $courseurl = &courseid_to_courseurl($env{'request.course.id'});
-    if ($env{'request.course.sec'}) {
-        $courseurl .= '/'.$env{'request.course.sec'};
-    }
-    return %blockers if ($env{'user.priv.'.$env{'request.role'}.'.'.$courseurl} =~/evb\&([^\:]*)/);
+    return %blockers if ($env{'user.priv.'.$env{'request.role'}} =~/evb\&([^\:]*)/);
     my %commblocks;
     if (ref($blocks) eq 'HASH') {
         %commblocks = %{$blocks};
@@ -8517,9 +8512,10 @@ sub get_commblock_resources {
             }
         } elsif ($block =~ /^firstaccess____(.+)$/) {
             my $item = $1;
+            my @to_test;
             if (ref($commblocks{$block}{'blocks'}) eq 'HASH') {
                 if (ref($commblocks{$block}{'blocks'}{'docs'}) eq 'HASH') {
-                    my (@interval,$mapname);
+                    my @interval;
                     my $type = 'map';
                     if ($item eq 'course') {
                         $type = 'course';
@@ -8528,16 +8524,40 @@ sub get_commblock_resources {
                         if ($item =~ /___\d+___/) {
                             $type = 'resource';
                             @interval=&EXT("resource.0.interval",$item);
-                        } else {
-                            $mapname = &deversion($item);
                             if (ref($navmap)) {
-                                my $timelimit = $navmap->get_mapparam(undef,$mapname,'0.interval');
-                                @interval = ($timelimit,'map');
+                                my $res = $navmap->getBySymb($item);
+                                push(@to_test,$res);
+                            }
+                        } else {
+                            my $mapsymb = &symbread($item,1);
+                            if ($mapsymb) {
+                                if (ref($navmap)) {
+                                    my $mapres = $navmap->getBySymb($mapsymb);
+                                    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;
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
                             }
                         }
                     }
-                    if ($interval[0] =~ /^(\d+)/) {
-                        my $timelimit = $1;
+                    if ($interval[0] =~ /^\d+$/) {
                         my $first_access;
                         if ($type eq 'resource') {
                             $first_access=&get_first_access($interval[1],$item);
@@ -8547,40 +8567,13 @@ sub get_commblock_resources {
                             $first_access=&get_first_access($interval[1]);
                         }
                         if ($first_access) {
-                            my $timesup = $first_access+$timelimit;
+                            my $timesup = $first_access+$interval[0];
                             if ($timesup > $now) {
                                 my $activeblock;
-                                if ($type eq 'resource') {
-                                    if (ref($navmap)) {
-                                        my $res = $navmap->getBySymb($item);
-                                        if ($res->answerable()) {
-                                            $activeblock = 1;
-                                        }
-                                    }
-                                } elsif ($type eq 'map') {
-                                    my $mapsymb = &symbread($mapname,1);
-                                    if (($mapsymb) && (ref($navmap))) {
-                                        my $mapres = $navmap->getBySymb($mapsymb);
-                                        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()) {
-                                                            $activeblock = 1;
-                                                            last;
-                                                        }
-                                                    }
-                                                }
-                                            }
-                                        }
+                                foreach my $res (@to_test) {
+                                    if ($res->answerable()) {
+                                        $activeblock = 1;
+                                        last;
                                     }
                                 }
                                 if ($activeblock) {
@@ -8610,12 +8603,8 @@ sub has_comm_blocking {
     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');
-    my $courseurl = &courseid_to_courseurl($env{'request.course.id'});
-    if ($env{'request.course.sec'}) {
-        $courseurl .= '/'.$env{'request.course.sec'};
-    }
-    return if ($env{'user.priv.'.$env{'request.role'}.'.'.$courseurl} =~/evb\&([^\:]*)/);
     my %blockinfo;
     if (ref($blocks) eq 'HASH') {
         %blockinfo = &get_commblock_resources($blocks);
@@ -9066,6 +9055,25 @@ sub auto_validate_instcode {
     return ($outcome,$description,$defaultcredits);
 }
 
+sub auto_validate_inst_crosslist {
+    my ($cnum,$cdom,$instcode,$inst_xlist,$coowner) = @_;
+    my ($homeserver,$response);
+    if (($cdom =~ /^$match_domain$/) && ($cnum =~ /^$match_courseid$/)) {
+        $homeserver = &homeserver($cnum,$cdom);
+    }
+    if (!defined($homeserver)) {
+        if ($cdom =~ /^$match_domain$/) {
+            $homeserver = &domain($cdom,'primary');
+        }
+    }
+    unless (($homeserver eq '') || ($homeserver eq 'no_host')) {
+        $response=&reply('autovalidateinstcrosslist:'.$cdom.':'.
+                         &escape($instcode).':'.&escape($inst_xlist).':'.
+                         &escape($coowner),$homeserver);
+    }
+    return $response;
+}
+
 sub auto_create_password {
     my ($cnum,$cdom,$authparam,$udom) = @_;
     my ($homeserver,$response);
@@ -9337,6 +9345,38 @@ sub auto_validate_class_sec {
     return $response;
 }
 
+sub auto_instsec_reformat {
+    my ($cdom,$action,$instsecref) = @_;
+    return unless(($action eq 'clutter') || ($action eq 'declutter'));
+    my @homeservers;
+    if (defined(&domain($cdom,'primary'))) {
+        push(@homeservers,&domain($cdom,'primary'));
+    } else {
+        my %servers = &get_servers($cdom,'library');
+        foreach my $tryserver (keys(%servers)) {
+            if (!grep(/^\Q$tryserver\E$/,@homeservers)) {
+                push(@homeservers,$tryserver);
+            }
+        }
+    }
+    my $response;
+    my %reformatted = %{$instsecref};
+    foreach my $server (@homeservers) {
+        if (ref($instsecref) eq 'HASH') {
+            my $info = &freeze_escape($instsecref);
+            my $response=&reply('autoinstsecreformat:'.$cdom.':'.
+                                $action.':'.$info,$server);
+            next if ($response =~ /(con_lost|error|no_such_host|refused|unknown_command)/);
+            my @items = split(/&/,$response);
+            foreach my $item (@items) {
+                my ($key,$value) = split(/=/,$item);
+                $reformatted{&unescape($key)} = &thaw_unescape($value);
+            }
+        }
+    }
+    return %reformatted;
+}
+
 sub auto_validate_instclasses {
     my ($cdom,$cnum,$owners,$classesref) = @_;
     my ($homeserver,%validations);
@@ -9881,11 +9921,23 @@ sub autoupdate_coowners {
         if ($domdesign{$cdom.'.autoassign.co-owners'}) {
             my %coursehash = &coursedescription($cdom.'_'.$cnum);
             my $instcode = $coursehash{'internal.coursecode'};
+            my $xlists = $coursehash{'internal.crosslistings'};
             if ($instcode ne '') {
                 if (($start && $start <= $now) && ($end == 0) || ($end > $now)) {
                     unless ($coursehash{'internal.courseowner'} eq $uname.':'.$udom) {
                         my ($delcoowners,@newcoowners,$putresult,$delresult,$coowners);
                         my ($result,$desc) = &auto_validate_instcode($cnum,$cdom,$instcode,$uname.':'.$udom);
+                        unless ($result eq 'valid') {
+                            if ($xlists ne '') {
+                                foreach my $xlist (split(',',$xlists)) {
+                                    my ($inst_crosslist,$lcsec) = split(':',$xlist);
+                                    $result =
+                                        &auto_validate_inst_crosslist($cnum,$cdom,$instcode,
+                                                                      $inst_crosslist,$uname.':'.$udom);
+                                    last if ($result eq 'valid');
+                                }
+                            }
+                        }
                         if ($result eq 'valid') {
                             if ($coursehash{'internal.co-owners'}) {
                                 foreach my $coowner (split(',',$coursehash{'internal.co-owners'})) {
@@ -9898,18 +9950,16 @@ sub autoupdate_coowners {
                             } else {
                                 push(@newcoowners,$uname.':'.$udom);
                             }
-                        } else {
-                            if ($coursehash{'internal.co-owners'}) {
-                                foreach my $coowner (split(',',$coursehash{'internal.co-owners'})) {
-                                    unless ($coowner eq $uname.':'.$udom) {
-                                        push(@newcoowners,$coowner);
-                                    }
-                                }
-                                unless (@newcoowners > 0) {
-                                    $delcoowners = 1;
-                                    $coowners = '';
+                        } elsif ($coursehash{'internal.co-owners'}) {
+                            foreach my $coowner (split(',',$coursehash{'internal.co-owners'})) {
+                                unless ($coowner eq $uname.':'.$udom) {
+                                    push(@newcoowners,$coowner);
                                 }
                             }
+                            unless (@newcoowners > 0) {
+                                $delcoowners = 1;
+                                $coowners = '';
+                            }
                         }
                         if (@newcoowners || $delcoowners) {
                             &store_coowners($cdom,$cnum,$coursehash{'home'},