--- rat/lonuserstate.pm 2022/01/02 16:30:29 1.149.2.5.2.1 +++ rat/lonuserstate.pm 2016/01/26 14:30:40 1.150 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Construct and maintain state and binary representation of course for user # -# $Id: lonuserstate.pm,v 1.149.2.5.2.1 2022/01/02 16:30:29 raeburn Exp $ +# $Id: lonuserstate.pm,v 1.150 2016/01/26 14:30:40 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -42,7 +42,7 @@ use Safe::Hole; use Opcode; use Apache::lonenc; use Fcntl qw(:flock); -use LONCAPA qw(:DEFAULT :match); +use LONCAPA qw(:DEFAULT :match); use File::Basename; @@ -62,9 +62,6 @@ my %randomorder; # maps to order content my %randomizationcode; # code used to grade folder for bubblesheet exam my %encurl; # URLs in this folder are supposed to be encrypted my %hiddenurl; # this URL (or complete folder) is supposed to be hidden -my %deeplinkout; # this URL (or complete folder) unavailable in deep-link session -my %rescount; # count of unhidden items in each map -my %mapcount; # count of unhidden maps in each map # ----------------------------------- Remove version from URL and store in hash @@ -243,8 +240,6 @@ sub loadmap { my @map_ids; my $codechecked; - $rescount{$lpc} = 0; - $mapcount{$lpc} = 0; while (my $token = $parser->get_token) { next if ($token->[0] ne 'S'); @@ -254,13 +249,6 @@ sub loadmap { my $resource_id = &parse_resource($token,$lpc,$ispage,$uri,$courseid); if (defined $resource_id) { push(@map_ids, $resource_id); - if ($hash{'src_'.$lpc.'.'.$resource_id}) { - $rescount{$lpc} ++; - if (($hash{'src_'.$lpc.'.'.$resource_id}=~/\.sequence$/) || - ($hash{'src_'.$lpc.'.'.$resource_id}=~/\.page$/)) { - $mapcount{$lpc} ++; - } - } unless ($codechecked) { my $startsymb = &Apache::lonnet::encode_symb($hash{'map_id_'.$lpc},$resource_id, @@ -290,10 +278,19 @@ sub loadmap { } undef($codechecked); + # Handle randomization and random selection if ($randomize) { - unless (&is_advanced($courseid)) { + my $advanced; + if ($env{'request.course.id'}) { + $advanced = (&Apache::lonnet::allowed('adv') eq 'F'); + } else { + $env{'request.course.id'} = $courseid; + $advanced = (&Apache::lonnet::allowed('adv') eq 'F'); + $env{'request.course.id'} = ''; + } + unless ($advanced) { # Order of resources is not randomized if user has and advanced role in the course. my $seed; @@ -341,6 +338,7 @@ sub loadmap { @map_ids=&Math::Random::random_permutation(@map_ids); } + my $from = shift(@map_ids); my $from_rid = $lpc.'.'.$from; $hash{'map_start_'.$uri} = $from_rid; @@ -365,7 +363,7 @@ sub loadmap { $parser = HTML::TokeParser->new(\$instr); $parser->attr_encoded(1); - # last parse out the mapalias params. These provide mnemonic + # last parse out the mapalias params. Thes provide mnemonic # tags to resources that can be used in conditions while (my $token = $parser->get_token) { @@ -376,18 +374,6 @@ sub loadmap { } } -sub is_advanced { - my ($courseid) = @_; - my $advanced; - if ($env{'request.course.id'}) { - $advanced = (&Apache::lonnet::allowed('adv') eq 'F'); - } else { - $env{'request.course.id'} = $courseid; - $advanced = (&Apache::lonnet::allowed('adv') eq 'F'); - $env{'request.course.id'} = ''; - } - return $advanced; -} # -------------------------------------------------------------------- Resource # @@ -474,11 +460,7 @@ sub parse_resource { # is not a page. If the resource is a page then it must be # assembled (at fetch time?). - if ($ispage) { - if ($token->[2]->{'external'} eq 'true') { # external - $turi=~s{^http\://}{/ext/}; - } - } else { + unless ($ispage) { $turi=~/\.(\w+)$/; my $embstyle=&Apache::loncommon::fileembstyle($1); if ($token->[2]->{'external'} eq 'true') { # external @@ -493,7 +475,7 @@ sub parse_resource { } elsif ($turi!~/\.(sequence|page)$/) { $turi='/adm/coursedocs/showdoc'.$turi; } - } elsif ($turi=~ m{^/adm/$match_domain/$match_courseid/\d+/ext\.tool$}) { + } elsif ($turi=~ m{^/adm/$match_domain/$match_courseid/\d+/exttools?$}) { $turi='/adm/wrapper'.$turi; } elsif ($turi=~/\S/) { # normal non-empty internal resource my $mapdir=$uri; @@ -570,9 +552,7 @@ sub parse_resource { if (($turi=~/\.sequence$/) || ($turi=~/\.page$/)) { $hash{'is_map_'.$rid}=1; - if ((!$hiddenurl{$rid}) || (&is_advanced($courseid))) { - &loadmap($turi,$rid,$courseid); - } + &loadmap($turi,$rid,$courseid); } return $token->[2]->{'id'}; } @@ -728,7 +708,7 @@ sub parse_condition { # Typical attributes: # to=n - Number of the resource the parameter applies to. # type=xx - Type of parameter value (e.g. string_yesno or int_pos). -# name=xxx - Name of parameter (e.g. parameter_randompick or parameter_randomorder). +# name=xxx - Name ofr parameter (e.g. parameter_randompick or parameter_randomorder). # value=xxx - value of the parameter. sub parse_param { @@ -905,7 +885,7 @@ sub simplify { # new value indicating how far the map has been traversed (the sofar). # sub traceroute { - my ($sofar,$rid,$beenhere,$encflag,$hdnflag,$cid)=@_; + my ($sofar,$rid,$beenhere,$encflag,$hdnflag)=@_; my $newsofar=$sofar=simplify($sofar); unless ($beenhere=~/\&\Q$rid\E\&/) { @@ -929,30 +909,6 @@ sub traceroute { $retfrid=$rid; } - my (@deeplink,@recurseup); - if ($hash{'is_map_'.$rid}) { - my ($cdom,$cnum) = split(/_/,$cid); - my $mapsrc = $hash{'src_'.$rid}; - my $map_pc = $hash{'map_pc_'.$mapsrc}; - my @pcs = split(/,/,$hash{'map_hierarchy_'.$map_pc}); - shift(@pcs); - @recurseup = map { &Apache::lonnet::declutter($hash{'map_id_'.$_}) } reverse(@pcs); - my $mapname = &Apache::lonnet::declutter(&Apache::lonnet::deversion($mapsrc)); - my $deeplinkval = &get_mapparam($env{'user.name'},$env{'user.domain'},$cnum,$cdom, - $rid,$mapname,'0.deeplink',\@recurseup); - if ($deeplinkval ne '') { - @deeplink = ($deeplinkval,'map'); - } - } else { - my @pcs = split(/,/,$hash{'map_hierarchy_'.$mapid}); - shift(@pcs); - @recurseup = map { &Apache::lonnet::declutter($hash{'map_id_'.$_}) } reverse(@pcs); - @deeplink = &Apache::lonnet::EXT('resource.0.deeplink',$symb,'','','','',$cid,\@recurseup); - } - unless (@deeplink < 2) { - $hash{'deeplinkonly_'.$rid}=join(':',map { &escape($_); } @deeplink); - } - if (defined($hash{'conditions_'.$rid})) { $hash{'conditions_'.$rid}=simplify( '('.$hash{'conditions_'.$rid}.')|('.$sofar.')'); @@ -974,8 +930,7 @@ sub traceroute { $hash{'map_start_'.$hash{'src_'.$rid}}, $beenhere, $encflag || $encurl{$rid}, - $hdnflag || $hiddenurl{$rid}, - $cid); + $hdnflag || $hiddenurl{$rid}); } } @@ -1002,7 +957,7 @@ sub traceroute { } # Recurse to resoruces that have to's to us. $newsofar=&traceroute($further,$hash{'goesto_'.$id},$beenhere, - $encflag,$hdnflag,$cid); + $encflag,$hdnflag); } } } @@ -1161,14 +1116,6 @@ sub hiddenurls { if ($currentrids[$k]) { $hash{'randomout_'.$currentrids[$k]}=1; my ($mapid,$resid)=split(/\./,$currentrids[$k]); - if ($rescount{$mapid}) { - $rescount{$mapid} --; - } - if ($hash{'is_map_'.$currentrids[$k]}) { - if ($mapcount{$mapid}) { - $mapcount{$mapid} --; - } - } $randomoutentry.='&'. &Apache::lonnet::encode_symb($hash{'map_id_'.$mapid}, $resid, @@ -1181,14 +1128,6 @@ sub hiddenurls { foreach my $rid (keys(%hiddenurl)) { $hash{'randomout_'.$rid}=1; my ($mapid,$resid)=split(/\./,$rid); - if ($rescount{$mapid}) { - $rescount{$mapid} --; - } - if ($hash{'is_map_'.$rid}) { - if ($mapcount{$mapid}) { - $mapcount{$mapid} --; - } - } $randomoutentry.='&'. &Apache::lonnet::encode_symb($hash{'map_id_'.$mapid},$resid, $hash{'src_'.$rid}).'&'; @@ -1199,53 +1138,10 @@ sub hiddenurls { } } -sub deeplinkouts { - my $deeplinkoutentry; - foreach my $rid (keys(%deeplinkout)) { - $hash{'deeplinkout_'.$rid}=1; - my ($mapid,$resid)=split(/\./,$rid); - $deeplinkoutentry.='&'. - &Apache::lonnet::encode_symb($hash{'map_id_'.$mapid},$resid, - $hash{'src_'.$rid}).'&'; - } -# --------------------------------------- append deeplinkout entry to environment - if ($deeplinkoutentry) { - &Apache::lonnet::appenv({'acc.deeplinkout' => $deeplinkoutentry}); - } -} - -# -------------------------------------- populate big hash with map breadcrumbs - -# Create map_breadcrumbs_$pc from map_hierarchy_$pc by omitting intermediate -# maps not shown in Course Contents table. - -sub mapcrumbs { - my ($cid) = @_; - foreach my $key (keys(%rescount)) { - if ($hash{'map_hierarchy_'.$key}) { - my $skipnext = 0; - foreach my $id (split(/,/,$hash{'map_hierarchy_'.$key}),$key) { - my $rid = $hash{'ids_'.$hash{'map_id_'.$id}}; - unless (($skipnext) || (!&is_advanced($cid) && $hash{'deeplinkout_'.$rid})) { - $hash{'map_breadcrumbs_'.$key} .= "$id,"; - } - unless (($id == 0) || ($id == 1)) { - if ((!$rescount{$id}) || ($rescount{$id} == 1 && $mapcount{$id} == 1)) { - $skipnext = 1; - } else { - $skipnext = 0; - } - } - } - $hash{'map_breadcrumbs_'.$key} =~ s/,$//; - } - } -} - # ---------------------------------------------------- Read map and all submaps sub readmap { - my ($short,$critmsg_check) = @_; + my $short=shift; $short=~s/^\///; # TODO: Hidden dependency on current user: @@ -1262,7 +1158,7 @@ sub readmap { } @cond=('true:normal'); - unless (open(LOCKFILE,">","$fn.db.lock")) { + unless (open(LOCKFILE,">$fn.db.lock")) { # # Most likely a permissions problem on the lockfile or its directory. # @@ -1280,14 +1176,8 @@ sub readmap { &unlink_tmpfiles($fn); } undef %randompick; - undef %randompickseed; - undef %randomorder; - undef %randomizationcode; undef %hiddenurl; undef %encurl; - undef %deeplinkout; - undef %rescount; - undef %mapcount; $retfrid=''; $errtext=''; my ($untiedhash,$untiedparmhash,$tiedhash,$tiedparmhash); # More state flags. @@ -1429,14 +1319,8 @@ sub readmap { $lock=1; } undef %randompick; - undef %randompickseed; - undef %randomorder; - undef %randomizationcode; undef %hiddenurl; undef %encurl; - undef %deeplinkout; - undef %rescount; - undef %mapcount; $errtext=''; $retfrid=''; # @@ -1484,18 +1368,14 @@ sub readmap { # Depends on user must parameterize this as well..or separate as this is: # more part of determining what someone sees on entering a course? -# When lonuserstate::readmap() is called from lonroles.pm, i.e., -# after selecting a role in a course, critical_redirect will be called, -# unless the course has a blocking event in effect, which suppresses -# critical message checking (users without evb priv). -# - if ($critmsg_check) { - my ($redirect,$url) = &Apache::loncommon::critical_redirect(); - if ($redirect) { - $retfurl = $url; + my @what=&Apache::lonnet::dump('critical',$env{'user.domain'}, + $env{'user.name'}); + if ($what[0]) { + if (($what[0] ne 'con_lost') && ($what[0]!~/^error\:/)) { + $retfurl='/adm/email?critical=display'; } - } + } return ($retfurl,$errtext); } @@ -1543,6 +1423,7 @@ sub build_tmp_hashes { # Load the map.. note that loadmap may implicitly recurse if the map contains # sub-maps. + &loadmap($uri,'0.0',$short); # The code below only executes if there is a starting point for the map> @@ -1555,7 +1436,7 @@ sub build_tmp_hashes { "request.course.uri" => $uri, "request.course.tied" => time}); $env{'request.course.id'}=$short; - &traceroute('0',$hash{'map_start_'.$uri},'&','','',$short); + &traceroute('0',$hash{'map_start_'.$uri},'&'); &accinit($uri,$short,$fn); &hiddenurls(); } @@ -1589,7 +1470,7 @@ sub build_tmp_hashes { # ---------------------------------------------------- Store away initial state { my $cfh; - if (open($cfh,">","$fn.state")) { + if (open($cfh,">$fn.state")) { print $cfh join("\n",@cond); $gotstate = 1; } else { @@ -1597,89 +1478,6 @@ sub build_tmp_hashes { "Could not write statemap $fn for $uri."); } } - - # Was initial access via a deep-link? - my ($cdom,$cnum) = split(/_/,$short); - if (($cdom ne '') && ($env{'request.deeplink.login'} ne '')) { - my $deeplink_symb = &Apache::loncommon::deeplink_login_symb($cnum,$cdom); - if ($deeplink_symb) { - my ($loginrid,$deeplink_login_pc,$login_hierarchy); - my ($map,$resid,$url) = &Apache::lonnet::decode_symb($deeplink_symb); - $loginrid = $hash{'map_pc_'.&Apache::lonnet::clutter($map)}.'.'.$resid; - if ($deeplink_symb =~ /\.(page|sequence)$/) { - $deeplink_login_pc = $hash{'map_pc_'.&Apache::lonnet::clutter($url)}; - } else { - $deeplink_login_pc = $hash{'map_pc_'.&Apache::lonnet::clutter($map)}; - } - my $deeplink; - if ($hash{'deeplinkonly_'.$loginrid} ne '') { - my @deeplinkinfo = map { &unescape($_); } split(/:/,$hash{'deeplinkonly_'.$loginrid}); - unless (@deeplinkinfo < 2) { - $deeplink = $deeplinkinfo[0]; - } - } - if ($deeplink) { - my $disallow; - my ($state,$others,$listed,$scope,$protect) = split(/,/,$deeplink); - if (($protect ne 'none') && ($protect ne '')) { - my ($acctype,$item) = split(/:/,$protect); - if ($acctype =~ /lti(c|d)$/) { - unless ($env{'request.linkprot'} eq $item.$1.':'.$env{'request.deeplink.login'}) { - $disallow = 1; - } - } elsif ($acctype eq 'key') { - unless ($env{'request.linkkey'} eq $item) { - $disallow = 1; - } - } - } - if ($disallow) { - &Apache::lonnet::delenv('request.deeplink.login'); - } else { - if ($others eq 'hide') { - my @recfolders; - if ($scope eq 'rec') { - foreach my $key (keys(%hash)) { - if ($key=~/^map_hierarchy_(\d+)$/) { - my $mpc = $1; - my @ids = split(/,/,$hash{$key}); - if (grep(/^$deeplink_login_pc$/,@ids)) { - my $idx; - foreach my $mapid (@ids) { - if ($idx) { - push(@recfolders,$mapid); - } elsif ($mapid == $deeplink_login_pc) { - push(@recfolders,$mapid); - $idx = $mapid; - } - } - push(@recfolders,$mpc); - } - } - } - } - foreach my $key (keys(%hash)) { - if ($key=~/^src_(.+)$/) { - my $rid = $1; - next if ($rid eq '0.0'); - next if ($rid eq $loginrid); - if ($scope ne 'res') { - my $mapid = (split(/\./,$rid))[0]; - next if ($mapid eq $deeplink_login_pc); - if ($scope eq 'rec') { - next if (grep(/^$mapid$/,@recfolders)); - } - } - $deeplinkout{$rid} = 1; - } - } - } - } - &deeplinkouts(); - } - } - } - &mapcrumbs(); return $gotstate; } @@ -1709,7 +1507,7 @@ sub evalstate { if (-e $fn) { my @conditions=(); { - open(my $fh,"<",$fn); + open(my $fh,"<$fn"); @conditions=<$fh>; close($fh); } @@ -1741,165 +1539,6 @@ sub evalstate { return $state; } -sub get_mapparam { - my ($uname,$udom,$cnum,$cdom,$rid,$mapname,$what,$recurseupref) = @_; - unless ($mapname) { return; } - -# ------------------------------------------------- Get coursedata (if present) - my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom); - if (!ref($courseopt)) { - undef($courseopt); - } - -# --------------------------------------------------- Get userdata (if present) - my $useropt=&Apache::lonnet::get_userresdata($uname,$udom); - if (!ref($useropt)) { - undef($useropt); - } - - my @recurseup; - if (ref($recurseupref) eq 'ARRAY') { - @recurseup = @{$recurseupref}; - } - - # Get the section if there is one. - - my $cid = $cdom.'_'.$cnum; - my $csec=$env{'request.course.sec'}; - my $cgroup=''; - my @cgrps=split(/:/,$env{'request.course.groups'}); - if (@cgrps > 0) { - @cgrps = sort(@cgrps); - $cgroup = $cgrps[0]; - } - - my $rwhat=$what; - $what=~s/^parameter\_//; - $what=~s/\_/\./; - - # Build the hash keys for the lookup: - - my $mapparm=$mapname.'___(all).'.$what; - my $recurseparm=$mapname.'___(rec).'.$what; - my $usercourseprefix=$cid; - - my $grplevelm = "$usercourseprefix.[$cgroup].$mapparm"; - my $seclevelm = "$usercourseprefix.[$csec].$mapparm"; - my $courselevelm = "$usercourseprefix.$mapparm"; - - my $grpleveli = "$usercourseprefix.[$cgroup].$recurseparm"; - my $secleveli = "$usercourseprefix.[$csec].$recurseparm"; - my $courseleveli = "$usercourseprefix.$recurseparm"; - - # Check per user - - if ($uname and defined($useropt)) { - if (defined($$useropt{$courselevelm})) { - return $$useropt{$courselevelm}; - } - if (defined($$useropt{$courseleveli})) { - return $$useropt{$courseleveli}; - } - foreach my $item (@recurseup) { - my $norecursechk=$usercourseprefix.'.'.$item.'___(all).'.$what; - if (defined($$useropt{$norecursechk})) { - if ($what =~ /\.(encrypturl|hiddenresource)$/) { - return $$useropt{$norecursechk}; - } else { - last; - } - } - } - } - - # Check course -- group - - if ($cgroup ne '' and defined ($courseopt)) { - if (defined($$courseopt{$grplevelm})) { - return $$courseopt{$grplevelm}; - } - if (defined($$courseopt{$grpleveli})) { - return $$courseopt{$grpleveli}; - } - foreach my $item (@recurseup) { - my $norecursechk=$usercourseprefix.'.['.$cgroup.'].'.$item.'___(all).'.$what; - if (defined($$courseopt{$norecursechk})) { - if ($what =~ /\.(encrypturl|hiddenresource)$/) { - return $$courseopt{$norecursechk}; - } else { - last; - } - } - } - } - - # Check course -- section - - if ($csec ne '' and defined($courseopt)) { - if (defined($$courseopt{$seclevelm})) { - return $$courseopt{$seclevelm}; - } - if (defined($$courseopt{$secleveli})) { - return $$courseopt{$secleveli}; - } - foreach my $item (@recurseup) { - my $norecursechk=$usercourseprefix.'.['.$csec.'].'.$item.'___(all).'.$what; - if (defined($$courseopt{$norecursechk})) { - if ($what =~ /\.(encrypturl|hiddenresource)$/) { - return $$courseopt{$norecursechk}; - } else { - last; - } - } - } - } - - # Check the map parameters themselves: - - if ($hash{'param_'.$rid}) { - my @items = split(/\&/,$hash{'param_'.$rid}); - my $thisparm; - foreach my $item (@items) { - my ($esctype,$escname,$escvalue) = ($item =~ /^([^:]+):([^=]+)=(.*)$/); - my $name = &unescape($escname); - my $value = &unescape($escvalue); - if ($name eq $what) { - $thisparm = $value; - last; - } - } - if (defined($thisparm)) { - return $thisparm; - } - } - - # Additional course parameters: - - if (defined($courseopt)) { - if (defined($$courseopt{$courselevelm})) { - return $$courseopt{$courselevelm}; - } - - if (defined($$courseopt{$courseleveli})) { - return $$courseopt{$courseleveli}; - } - - if (@recurseup) { - foreach my $item (@recurseup) { - my $norecursechk=$usercourseprefix.'.'.$item.'___(all).'.$what; - if (defined($$courseopt{$norecursechk})) { - if ($what =~ /\.(encrypturl|hiddenresource)$/) { - return $$courseopt{$norecursechk}; - } else { - last; - } - } - } - } - } - return undef; -} - # This block seems to have code to manage/detect doubly defined # aliases in maps. 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.