Annotation of rat/lonuserstate.pm, revision 1.83

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Construct and maintain state and binary representation of course for user
                      3: #
1.83    ! albertel    4: # $Id: lonuserstate.pm,v 1.82 2004/11/10 21:30:48 albertel Exp $
1.25      www         5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
1.26      harris41   28: ###
1.1       www        29: 
                     30: package Apache::lonuserstate;
                     31: 
1.26      harris41   32: # ------------------------------------------------- modules used by this module
1.1       www        33: use strict;
                     34: use Apache::Constants qw(:common :http);
                     35: use Apache::File;
                     36: use HTML::TokeParser;
                     37: use Apache::lonnet();
1.26      harris41   38: use Apache::loncommon();
1.1       www        39: use GDBM_File;
1.12      www        40: use Apache::lonmsg;
1.15      www        41: use Safe;
1.21      www        42: use Safe::Hole;
1.15      www        43: use Opcode;
1.73      www        44: use Apache::lonenc;
1.15      www        45: 
1.1       www        46: # ---------------------------------------------------- Globals for this package
                     47: 
                     48: my $pc;      # Package counter
                     49: my %hash;    # The big tied hash
1.19      www        50: my %parmhash;# The hash with the parameters
1.1       www        51: my @cond;    # Array with all of the conditions
                     52: my $errtext; # variable with all errors
1.21      www        53: my $retfurl; # variable with the very first URL in the course
1.29      www        54: my %randompick; # randomly picked resources
1.51      www        55: my %randompickseed; # optional seed for randomly picking resources
1.73      www        56: my %encurl; # URLs in this folder are supposed to be encrypted
                     57: my %hiddenurl; # this URL (or complete folder) is supposed to be hidden
1.61      www        58: 
                     59: # ----------------------------------- Remove version from URL and store in hash
                     60: 
                     61: sub versiontrack {
                     62:     my $uri=shift;
                     63:     if ($uri=~/\.(\d+)\.\w+$/) {
                     64: 	my $version=$1;
                     65: 	$uri=~s/\.\d+\.(\w+)$/\.$1/;
1.62      www        66:         unless ($hash{'version_'.$uri}) {
                     67: 	    $hash{'version_'.$uri}=$version;
                     68: 	}
1.61      www        69:     }
                     70:     return $uri;
                     71: }
                     72: 
                     73: # -------------------------------------------------------------- Put in version
                     74: 
                     75: sub putinversion {
                     76:     my $uri=shift;
                     77:     if ($hash{'version_'.$uri}) {
                     78: 	my $version=$hash{'version_'.$uri};
1.65      www        79: 	if ($version eq 'mostrecent') { return $uri; }
1.66      www        80: 	if ($version eq &Apache::lonnet::getversion(
                     81: 			&Apache::lonnet::filelocation('',$uri))) 
                     82: 	             { return $uri; }
1.61      www        83: 	$uri=~s/\.(\w+)$/\.$version\.$1/;
                     84:     }
                     85:     return $uri;
                     86: }
                     87: 
                     88: # ----------------------------------------- Processing versions file for course
                     89: 
                     90: sub processversionfile {
1.64      www        91:     my %cenv=@_;
1.61      www        92:     my %versions=&Apache::lonnet::dump('resourceversions',
                     93: 				       $cenv{'domain'},
                     94: 				       $cenv{'num'});
                     95:     foreach (keys %versions) {
                     96: 	if ($_=~/^error\:/) { return; }
1.62      www        97: 	$hash{'version_'.$_}=$versions{$_};
1.61      www        98:     }
                     99: }
1.45      www       100: 
1.1       www       101: # --------------------------------------------------------- Loads map from disk
                    102: 
                    103: sub loadmap { 
                    104:     my $uri=shift;
                    105:     if ($hash{'map_pc_'.$uri}) { return OK; }
                    106: 
                    107:     $pc++;
                    108:     my $lpc=$pc;
                    109:     $hash{'map_pc_'.$uri}=$lpc;
                    110:     $hash{'map_id_'.$lpc}=$uri;
                    111: 
1.37      www       112: # Determine and check filename
1.62      www       113:     my $fn=&Apache::lonnet::filelocation('',&putinversion($uri));
1.37      www       114: 
                    115:     my $ispage=($fn=~/\.page$/);
1.1       www       116: 
1.10      www       117:     unless (($fn=~/\.sequence$/) ||
1.1       www       118:             ($fn=~/\.page$/)) { 
                    119:        $errtext.="Invalid map: $fn\n";
                    120:        return OK; 
                    121:     }
                    122: 
1.37      www       123:     my $instr=&Apache::lonnet::getfile($fn);
                    124: 
1.57      albertel  125:     unless ($instr eq -1) {
1.22      www       126: 
1.37      www       127: # Successfully got file, parse it
1.1       www       128: 
                    129:         my $parser = HTML::TokeParser->new(\$instr);
                    130:         my $token;
                    131: 
                    132:         my $linkpc=0;
                    133: 
                    134:         $fn=~/\.(\w+)$/;
                    135: 
                    136:         $hash{'map_type_'.$lpc}=$1;
                    137: 
                    138:         while ($token = $parser->get_token) {
                    139: 	    if ($token->[0] eq 'S') {
                    140:                 if ($token->[1] eq 'resource') {
                    141: # -------------------------------------------------------------------- Resource
                    142: 
                    143:                     my $rid=$lpc.'.'.$token->[2]->{'id'};
                    144: 
                    145:                     $hash{'kind_'.$rid}='res';
                    146:                     $hash{'title_'.$rid}=$token->[2]->{'title'};
1.61      www       147:                     my $turi=&versiontrack($token->[2]->{'src'});
                    148:                     if ($token->[2]->{'version'}) {
1.62      www       149: 			unless ($hash{'version_'.$turi}) {
                    150: 			    $hash{'version_'.$turi}=$1;
                    151: 			}
1.61      www       152: 		    }
1.83    ! albertel  153: 		    my $title=$token->[2]->{'title'};
        !           154: 		    $title=~s/\&colon\;/\:/gs;
1.60      albertel  155: 		    &Apache::lonnet::do_cache(\%Apache::lonnet::titlecache,
1.63      albertel  156: 		       &Apache::lonnet::encode_symb($uri,$token->[2]->{'id'},
1.83    ! albertel  157: 						    $turi),$title,'title');
1.22      www       158:                     unless ($ispage) {
                    159:                         $turi=~/\.(\w+)$/;
1.26      harris41  160:                         my $embstyle=&Apache::loncommon::fileembstyle($1);
1.40      www       161:                         if ($token->[2]->{'external'} eq 'true') { # external
1.22      www       162:                             $turi=~s/^http\:\/\//\/adm\/wrapper\/ext\//;
1.40      www       163:                         } elsif ($turi=~/^\/*uploaded\//) { # uploaded
1.76      albertel  164: 			    if (($embstyle eq 'img') || ($embstyle eq 'emb')) {
                    165:                                 $turi='/adm/wrapper'.$turi;
1.78      albertel  166: 			    } elsif ($embstyle eq 'ssi') {
                    167: 				#do nothing with these
                    168: 			    } elsif ($turi!~/\.(sequence|page)$/) {
1.42      www       169: 				$turi='/adm/coursedocs/showdoc'.$turi;
1.40      www       170:                             }
1.70      www       171:                         } elsif ($turi=~/\S/) { # normal non-empty internal resource
1.68      www       172: 			    my $mapdir=$uri;
                    173: 			    $mapdir=~s/[^\/]+$//;
                    174: 			    $turi=&Apache::lonnet::hreflocation($mapdir,$turi);
                    175: 			    if (($embstyle eq 'img') || ($embstyle eq 'emb')) {
                    176: 				$turi='/adm/wrapper'.$turi;
                    177: 			    }
1.22      www       178:                         }
                    179: 		    }
1.71      www       180: # Store reverse lookup, remove query string
                    181: 		    my $idsuri=$turi;
                    182: 		    $idsuri=~s/\?.+$//;
                    183:                     if (defined($hash{'ids_'.$idsuri})) {
                    184:                         $hash{'ids_'.$idsuri}.=','.$rid;
1.1       www       185:                     } else {
1.71      www       186:                         $hash{'ids_'.$idsuri}=''.$rid;
1.1       www       187:                     }
1.53      www       188:                
                    189:                     if
                    190: 	        ($turi=~/\/(syllabus|aboutme|navmaps|smppg|bulletinboard)$/) {
                    191: 			$turi.='?register=1';
                    192: 		    }
                    193: 
                    194:                     $hash{'src_'.$rid}=$turi;
1.1       www       195: 
1.22      www       196:                     if ($token->[2]->{'external'} eq 'true') {
1.1       www       197:                         $hash{'ext_'.$rid}='true:';
                    198:                     } else {
                    199:                         $hash{'ext_'.$rid}='false:';
                    200:                     }
                    201:                     if ($token->[2]->{'type'}) {
                    202: 			$hash{'type_'.$rid}=$token->[2]->{'type'};
1.2       www       203:                         if ($token->[2]->{'type'} eq 'start') {
                    204: 			    $hash{'map_start_'.$uri}="$rid";
                    205:                         }
                    206:                         if ($token->[2]->{'type'} eq 'finish') {
                    207: 			    $hash{'map_finish_'.$uri}="$rid";
                    208:                         }
1.1       www       209:                     }  else {
                    210:                         $hash{'type_'.$rid}='normal';
                    211:                     }
                    212: 
1.10      www       213:                     if (($turi=~/\.sequence$/) ||
1.1       www       214:                         ($turi=~/\.page$/)) {
1.2       www       215:                         $hash{'is_map_'.$rid}=1;
1.1       www       216:                         &loadmap($turi);
                    217:                     } 
                    218:                     
                    219:                 } elsif ($token->[1] eq 'condition') {
                    220: # ------------------------------------------------------------------- Condition
                    221: 
                    222:                     my $rid=$lpc.'.'.$token->[2]->{'id'};
                    223: 
                    224:                     $hash{'kind_'.$rid}='cond';
1.2       www       225:                     $cond[$#cond+1]=$token->[2]->{'value'};
                    226:                     $hash{'condid_'.$rid}=$#cond;
1.1       www       227:                     if ($token->[2]->{'type'}) {
1.2       www       228:                         $cond[$#cond].=':'.$token->[2]->{'type'};
1.1       www       229:                     }  else {
1.2       www       230:                         $cond[$#cond].=':normal';
1.1       www       231:                     }
                    232: 
                    233:                 } elsif ($token->[1] eq 'link') {
                    234: # ----------------------------------------------------------------------- Links
                    235: 
                    236:                     $linkpc++;
                    237:                     my $linkid=$lpc.'.'.$linkpc;
                    238: 
                    239:                     my $goesto=$lpc.'.'.$token->[2]->{'to'};
                    240:                     my $comesfrom=$lpc.'.'.$token->[2]->{'from'};
                    241:                     my $undercond=0;
                    242: 
                    243:                     if ($token->[2]->{'condition'}) {
                    244: 			$undercond=$lpc.'.'.$token->[2]->{'condition'};
                    245:                     }
                    246: 
                    247:                     $hash{'goesto_'.$linkid}=$goesto;
                    248:                     $hash{'comesfrom_'.$linkid}=$comesfrom;
                    249:                     $hash{'undercond_'.$linkid}=$undercond;
                    250: 
                    251:                     if (defined($hash{'to_'.$comesfrom})) {
                    252:                         $hash{'to_'.$comesfrom}.=','.$linkid;
                    253:                     } else {
                    254:                         $hash{'to_'.$comesfrom}=''.$linkid;
                    255:                     }
                    256:                     if (defined($hash{'from_'.$goesto})) {
                    257:                         $hash{'from_'.$goesto}.=','.$linkid;
                    258:                     } else {
                    259:                         $hash{'from_'.$goesto}=''.$linkid;
                    260:                     }
1.18      www       261:                 } elsif ($token->[1] eq 'param') {
                    262: # ------------------------------------------------------------------- Parameter
                    263: 
                    264:                     my $referid=$lpc.'.'.$token->[2]->{'to'};
1.63      albertel  265: 		    my $name=$token->[2]->{'name'};
                    266: 		    my $part;
                    267: 		    if ($name=~/^parameter_(.*)_/) {
                    268: 			$part=$1;
                    269: 		    } else {
                    270: 			$part=0;
                    271: 		    }
                    272: 		    $name=~s/^.*_([^_]*)$/$1/;
1.18      www       273:                     my $newparam=
                    274: 			&Apache::lonnet::escape($token->[2]->{'type'}).':'.
1.63      albertel  275: 			&Apache::lonnet::escape($part.'.'.$name).'='.
1.18      www       276: 			&Apache::lonnet::escape($token->[2]->{'value'});
                    277:                     if (defined($hash{'param_'.$referid})) {
                    278:                         $hash{'param_'.$referid}.='&'.$newparam;
                    279:                     } else {
                    280:                         $hash{'param_'.$referid}=''.$newparam;
                    281:                     }
1.75      www       282:                     if ($token->[2]->{'name'}=~/^parameter_(0_)*mapalias$/) {
1.28      www       283: 			$hash{'mapalias_'.$token->[2]->{'value'}}=$referid;
                    284:                     }
1.75      www       285:                     if ($token->[2]->{'name'}=~/^parameter_(0_)*randompick$/) {
1.29      www       286: 			$randompick{$referid}=$token->[2]->{'value'};
                    287:                     }
1.75      www       288:                     if ($token->[2]->{'name'}=~/^parameter_(0_)*randompickseed$/) {
1.51      www       289: 			$randompick{$referid}=$token->[2]->{'value'};
                    290:                     }
1.75      www       291:                     if ($token->[2]->{'name'}=~/^parameter_(0_)*encrypturl$/) {
1.74      www       292: 			if ($token->[2]->{'value'}=~/^yes$/i) {
                    293: 			    $encurl{$referid}=1;
                    294: 			}
1.73      www       295:                     }
1.75      www       296:                     if ($token->[2]->{'name'}=~/^parameter_(0_)*hiddenresource$/) {
1.74      www       297: 			if ($token->[2]->{'value'}=~/^yes$/i) {
                    298: 			    $hiddenurl{$referid}=1;
                    299: 			}
1.73      www       300:                     }
1.1       www       301:                 } 
                    302: 
                    303:             }
                    304:         }
                    305: 
                    306:     } else {
                    307:         $errtext.='Map not loaded: The file does not exist. ';
                    308:     }
                    309: }
                    310: 
1.3       www       311: # --------------------------------------------------------- Simplify expression
                    312: 
                    313: sub simplify {
                    314:    my $expression=shift;
                    315: # (8)=8
                    316:    $expression=~s/\((\d+)\)/$1/g;
                    317: # 8&8=8
1.7       www       318:    $expression=~s/(\D)(\d+)\&\2(\D)/$1$2$3/g;
1.3       www       319: # 8|8=8
1.7       www       320:    $expression=~s/(\D)(\d+)\|\2(\D)/$1$2$3/g;
1.3       www       321: # (5&3)&4=5&3&4
1.7       www       322:    $expression=~s/\((\d+)((?:\&\d+)+)\)\&(\d+\D)/$1$2\&$3/g;
1.3       www       323: # (((5&3)|(4&6)))=((5&3)|(4&6))
                    324:    $expression=~
                    325:        s/\((\(\(\d+(?:\&\d+)*\)(?:\|\(\d+(?:\&\d+)*\))+\))\)/$1/g;
                    326: # ((5&3)|(4&6))|(1&2)=(5&3)|(4&6)|(1&2)
                    327:    $expression=~
                    328:        s/\((\(\d+(?:\&\d+)*\))((?:\|\(\d+(?:\&\d+)*\))+)\)\|(\(\d+(?:\&\d+)*\))/\($1$2\|$3\)/g;
                    329:    return $expression;
                    330: }
                    331: 
1.2       www       332: # -------------------------------------------------------- Build condition hash
                    333: 
                    334: sub traceroute {
1.77      www       335:     my ($sofar,$rid,$beenhere,$encflag,$hdnflag)=@_;
1.81      albertel  336:     my $newsofar=$sofar=simplify($sofar);
1.2       www       337:     unless ($beenhere=~/\&$rid\&/) {
                    338:        $beenhere.=$rid.'&';  
1.79      albertel  339:        my ($mapid,$resid)=split(/\./,$rid);
                    340:        my $symb=&Apache::lonnet::encode_symb($hash{'map_id_'.$mapid},$resid,$hash{'src_'.$rid});
1.81      albertel  341:        my $hidden=&Apache::lonnet::EXT('resource.0.hiddenresource',$symb);
                    342:        if ($hdnflag || lc($hidden) eq 'yes') { $hiddenurl{$rid}=1; }
1.79      albertel  343:        my $encrypt=&Apache::lonnet::EXT('resource.0.encrypturl',$symb);
                    344:        if ($encflag || lc($encrypt) eq 'yes') { $encurl{$rid}=1; }
1.48      www       345:        if (($retfurl eq '') && ($hash{'src_'.$rid})
1.79      albertel  346: 	   && ($hash{'src_'.$rid}!~/\.sequence$/)) {
                    347:            $retfurl=$hash{'src_'.$rid}.(($hash{'src_'.$rid}=~/\?/)?'&':'?').
                    348: 	       'symb='.$symb;
1.21      www       349:        }
1.2       www       350:        if (defined($hash{'conditions_'.$rid})) {
1.3       www       351: 	   $hash{'conditions_'.$rid}=simplify(
                    352:            '('.$hash{'conditions_'.$rid}.')|('.$sofar.')');
1.2       www       353:        } else {
                    354:            $hash{'conditions_'.$rid}=$sofar;
                    355:        }
1.81      albertel  356:        $newsofar=$hash{'conditions_'.$rid};
1.2       www       357:        if (defined($hash{'is_map_'.$rid})) {
1.3       www       358:            if (defined($hash{'map_start_'.$hash{'src_'.$rid}})) {
1.81      albertel  359: 	       $sofar=$newsofar=
                    360: 		   &traceroute($sofar,
                    361: 			       $hash{'map_start_'.$hash{'src_'.$rid}},'&',
                    362: 			       $encflag || $encurl{$rid},
                    363: 			       $hdnflag || $hiddenurl{$rid});
1.2       www       364:            }
                    365:        }
                    366:        if (defined($hash{'to_'.$rid})) {
1.26      harris41  367:           foreach (split(/\,/,$hash{'to_'.$rid})) {
1.2       www       368: 		my $further=$sofar;
                    369:                 if ($hash{'undercond_'.$_}) {
                    370: 		   if (defined($hash{'condid_'.$hash{'undercond_'.$_}})) {
1.3       www       371:   		       $further=simplify('('.$further.')&('.
                    372:                               $hash{'condid_'.$hash{'undercond_'.$_}}.')');
1.2       www       373: 		   } else {
                    374:                        $errtext.='Undefined condition ID: '
                    375:                                  .$hash{'undercond_'.$_}.'. ';
                    376:                    }
                    377:                 }
1.81      albertel  378:                 $newsofar=&traceroute($further,$hash{'goesto_'.$_},$beenhere,
                    379: 				      $encflag,$hdnflag);
1.26      harris41  380:           }
1.2       www       381:        }
                    382:     }
1.81      albertel  383:     return $newsofar;
1.2       www       384: }
1.1       www       385: 
1.19      www       386: # ------------------------------ Cascading conditions, quick access, parameters
1.4       www       387: 
                    388: sub accinit {
                    389:     my ($uri,$short,$fn)=@_;
                    390:     my %acchash=();
                    391:     my %captured=();
                    392:     my $condcounter=0;
1.5       www       393:     $acchash{'acc.cond.'.$short.'.0'}=0;
1.26      harris41  394:     foreach (keys %hash) {
1.4       www       395:        if ($_=~/^conditions/) {
                    396: 	  my $expr=$hash{$_};
1.26      harris41  397:          foreach ($expr=~m/(\(\(\d+(?:\&\d+)+\)(?:\|\(\d+(?:\&\d+)+\))+\))/g) {
1.4       www       398:              my $sub=$_;
                    399:              my $orig=$_;
1.13      www       400:       $sub=~/\(\((\d+\&(:?\d+\&)*)(?:\d+\&*)+\)(?:\|\(\1(?:\d+\&*)+\))+\)/;
1.4       www       401:              my $factor=$1;
1.7       www       402:              $sub=~s/$factor//g;
                    403:              $sub=~s/^\(/\($factor\(/;
1.4       www       404: 	     $sub.=')';
                    405:              $sub=simplify($sub);
                    406:              $orig=~s/(\W)/\\$1/g;
1.7       www       407:  	     $expr=~s/$orig/$sub/;
1.26      harris41  408: 	  }
1.4       www       409:           $hash{$_}=$expr;
                    410:           unless (defined($captured{$expr})) {
                    411: 	      $condcounter++;
                    412:               $captured{$expr}=$condcounter;
1.5       www       413:               $acchash{'acc.cond.'.$short.'.'.$condcounter}=$expr;
1.4       www       414:           } 
1.19      www       415:        } elsif ($_=~/^param_(\d+)\.(\d+)/) {
                    416:           my $prefix=&Apache::lonnet::declutter($hash{'map_id_'.$1}).
                    417:       '___'.$2.'___'.&Apache::lonnet::declutter($hash{'src_'.$1.'.'.$2});
1.26      harris41  418:           foreach (split(/\&/,$hash{$_})) {
1.19      www       419: 	     my ($typename,$value)=split(/\=/,$_);
                    420:              my ($type,$name)=split(/\:/,$typename);
                    421:              $parmhash{$prefix.'.'.&Apache::lonnet::unescape($name)}=
                    422:                                    &Apache::lonnet::unescape($value);
                    423: 	     $parmhash{$prefix.'.'.&Apache::lonnet::unescape($name).'.type'}=
                    424:                                    &Apache::lonnet::unescape($type);
1.26      harris41  425:           }
1.19      www       426:        }
1.26      harris41  427:     }
                    428:     foreach (keys %hash) {
1.4       www       429: 	if ($_=~/^ids/) {
1.26      harris41  430: 	  foreach (split(/\,/,$hash{$_})) {
1.13      www       431: 	    my $resid=$_;
1.4       www       432:             my $uri=$hash{'src_'.$resid};
1.22      www       433:             $uri=~s/^\/adm\/wrapper//;
1.55      www       434:             $uri=&Apache::lonnet::declutter($uri);
1.4       www       435:             my @uriparts=split(/\//,$uri);
                    436:             my $urifile=$uriparts[$#uriparts];
                    437:             $#uriparts--;
                    438:             my $uripath=join('/',@uriparts);
1.23      www       439:            if ($uripath) {
1.13      www       440:             my $uricond='0';
1.4       www       441:             if (defined($hash{'conditions_'.$resid})) {
1.13      www       442:  		$uricond=$captured{$hash{'conditions_'.$resid}};
1.4       www       443:             }
1.5       www       444:             if (defined($acchash{'acc.res.'.$short.'.'.$uripath})) {
1.13      www       445:                 if ($acchash{'acc.res.'.$short.'.'.$uripath}=~
1.56      albertel  446:                    /(\&\Q$urifile\E\:[^\&]*)/) {
1.13      www       447: 		    my $replace=$1;
1.27      www       448:                     my $regexp=$replace;
1.78      albertel  449:                     #$regexp=~s/\|/\\\|/g;
1.13      www       450:                     $acchash{'acc.res.'.$short.'.'.$uripath}
1.78      albertel  451:                      =~s/\Q$regexp\E/$replace\|$uricond/;
1.13      www       452:                 } else {
                    453: 		   $acchash{'acc.res.'.$short.'.'.$uripath}.=
                    454:                      $urifile.':'.$uricond.'&';
                    455: 	        }
1.4       www       456:             } else {
1.13      www       457:                 $acchash{'acc.res.'.$short.'.'.$uripath}=
                    458:                  '&'.$urifile.':'.$uricond.'&';
1.23      www       459:             }
                    460:            } 
1.26      harris41  461:          }
1.13      www       462:       }
1.26      harris41  463:     }
1.24      www       464:     $acchash{'acc.res.'.$short.'.'}='&:0&';
1.8       www       465:     my $courseuri=$uri;
                    466:     $courseuri=~s/^\/res\///;
1.19      www       467:     &Apache::lonnet::delenv('(acc\.|httpref\.)');
1.79      albertel  468:     &Apache::lonnet::appenv(%acchash);
1.4       www       469: }
                    470: 
1.73      www       471: # ---------------- Selectively delete from randompick maps and hidden url parms
1.29      www       472: 
1.73      www       473: sub hiddenurls {
1.31      www       474:     my $randomoutentry='';
1.29      www       475:     foreach my $rid (keys %randompick) {
                    476:         my $rndpick=$randompick{$rid};
                    477:         my $mpc=$hash{'map_pc_'.$hash{'src_'.$rid}};
                    478: # ------------------------------------------- put existing resources into array
                    479:         my @currentrids=();
1.50      albertel  480:         foreach (sort(keys(%hash))) {
1.29      www       481: 	    if ($_=~/^src_($mpc\.\d+)/) {
                    482: 		if ($hash{'src_'.$1}) { push @currentrids, $1; }
                    483:             }
                    484:         }
1.50      albertel  485: 	# rids are number.number and we want to numercially sort on 
                    486:         # the second number
                    487: 	@currentrids=sort {
                    488: 	    my (undef,$aid)=split(/\./,$a);
                    489: 	    my (undef,$bid)=split(/\./,$b);
                    490: 	    $aid <=> $bid;
                    491: 	} @currentrids;
1.29      www       492:         next if ($#currentrids<$rndpick);
                    493: # -------------------------------- randomly eliminate the ones that should stay
1.50      albertel  494: 	my (undef,$id)=split(/\./,$rid);
1.51      www       495:         if ($randompickseed{$rid}) { $id=$randompickseed{$rid}; }
1.50      albertel  496: 	my $rndseed=&Apache::lonnet::rndseed($id); # use id instead of symb
1.58      albertel  497: 	&Apache::lonnet::setup_random_from_rndseed($rndseed);
1.50      albertel  498: 	my @whichids=&Math::Random::random_permuted_index($#currentrids+1);
                    499:         for (my $i=1;$i<=$rndpick;$i++) { $currentrids[$whichids[$i]]=''; }
                    500: 	#&Apache::lonnet::logthis("$id,$rndseed,".join(':',@whichids));
1.29      www       501: # -------------------------------------------------------- delete the leftovers
                    502:         for (my $k=0; $k<=$#currentrids; $k++) {
                    503:             if ($currentrids[$k]) {
                    504: 		$hash{'randomout_'.$currentrids[$k]}=1;
1.32      www       505:                 my ($mapid,$resid)=split(/\./,$currentrids[$k]);
                    506:                 $randomoutentry.='&'.
                    507:                  &Apache::lonnet::symbclean(
                    508: 		    &Apache::lonnet::declutter($hash{'map_id_'.$mapid}).
                    509:                     '___'.$resid.'___'.
                    510: 		    &Apache::lonnet::declutter($hash{'src_'.$currentrids[$k]})
                    511:                  ).'&';
1.29      www       512:             }
                    513:         }
1.31      www       514:     }
1.73      www       515: # ------------------------------ take care of explicitly hidden urls or folders
                    516:     foreach my $rid (keys %hiddenurl) {
                    517: 	$hash{'randomout_'.$rid}=1;
                    518: 	my ($mapid,$resid)=split(/\./,$rid);
                    519: 	$randomoutentry.='&'.
                    520: 	    &Apache::lonnet::symbclean(
                    521: 		         &Apache::lonnet::declutter($hash{'map_id_'.$mapid}).
                    522: 				       '___'.$resid.'___'.
                    523: 		    &Apache::lonnet::declutter($hash{'src_'.$rid})
                    524: 				       ).'&';
                    525:     }
                    526: # --------------------------------------- append randomout entry to environment
1.31      www       527:     if ($randomoutentry) {
                    528: 	&Apache::lonnet::appenv('acc.randomout' => $randomoutentry);
1.29      www       529:     }
                    530: }
                    531: 
1.1       www       532: # ---------------------------------------------------- Read map and all submaps
                    533: 
                    534: sub readmap {
1.9       www       535:    my $short=shift;
                    536:    $short=~s/^\///;
                    537:    my %cenv=&Apache::lonnet::coursedescription($short);
                    538:    my $fn=$cenv{'fn'};
                    539:    my $uri;
                    540:    $short=~s/\//\_/g;
                    541:    unless ($uri=$cenv{'url'}) { 
                    542:       &Apache::lonnet::logthis("<font color=blue>WARNING: ".
                    543:                        "Could not load course $short.</font>"); 
                    544:       return 'No course data available.';
                    545:    }
1.3       www       546:    @cond=('true:normal');
1.11      www       547:    unlink($fn.'.db');
                    548:    unlink($fn.'_symb.db');
                    549:    unlink($fn.'.state');
1.19      www       550:    unlink($fn.'parms.db');
1.29      www       551:    undef %randompick;
1.73      www       552:    undef %hiddenurl;
                    553:    undef %encurl;
1.21      www       554:    $retfurl='';
1.36      albertel  555:    if ((tie(%hash,'GDBM_File',"$fn.db",&GDBM_WRCREAT(),0640)) &&
                    556:        (tie(%parmhash,'GDBM_File',$fn.'_parms.db',&GDBM_WRCREAT(),0640))) {
1.4       www       557:     %hash=();
1.19      www       558:     %parmhash=();
1.4       www       559:     $errtext='';
                    560:     $pc=0;
1.62      www       561:     &processversionfile(%cenv);
1.38      www       562:     my $furi=&Apache::lonnet::clutter($uri);
1.61      www       563:     $hash{'src_0.0'}=&versiontrack($furi);
1.30      www       564:     $hash{'title_0.0'}=&Apache::lonnet::metadata($uri,'title');
                    565:     $hash{'ids_'.$furi}='0.0';
                    566:     $hash{'is_map_0.0'}=1;
1.4       www       567:     loadmap($uri);
                    568:     if (defined($hash{'map_start_'.$uri})) {
1.79      albertel  569: 	&Apache::lonnet::appenv("request.course.id"  => $short,
                    570: 				"request.course.fn"  => $fn,
                    571: 				"request.course.uri" => $uri);
1.4       www       572:         &traceroute('0',$hash{'map_start_'.$uri},'&');
                    573:         &accinit($uri,$short,$fn);
1.73      www       574:         &hiddenurls();
1.45      www       575:     }
1.62      www       576: # ------------------------------------------------------- Put versions into src
1.61      www       577:     foreach (keys %hash) {
                    578: 	if ($_=~/^src\_/) {
                    579: 	    $hash{$_}=&putinversion($hash{$_});
                    580: 	}
                    581:     }
1.74      www       582: # ---------------------------------------------------------------- Encrypt URLs
                    583:     foreach (keys %encurl) {
1.82      albertel  584: #	$hash{'src_'.$_}=&Apache::lonenc::encrypted($hash{'src_'.$_});
                    585: 	$hash{'encrypted_'.$_}=1;
1.74      www       586:     }
                    587: # ----------------------------------------------- Close hashes to finally store
                    588: # --------------------------------- Routine must pass this point, no early outs
1.19      www       589:     unless ((untie(%hash)) && (untie(%parmhash))) {
1.4       www       590:       &Apache::lonnet::logthis("<font color=blue>WARNING: ".
                    591:                        "Could not untie coursemap $fn for $uri.</font>"); 
1.1       www       592:     }
1.74      www       593: # ---------------------------------------------------- Store away initial state
1.4       www       594:     {
                    595:      my $cfh;
                    596:      if ($cfh=Apache::File->new(">$fn.state")) {
                    597:         print $cfh join("\n",@cond);
                    598:      } else {
1.6       www       599:       &Apache::lonnet::logthis("<font color=blue>WARNING: ".
1.4       www       600:                        "Could not write statemap $fn for $uri.</font>"); 
                    601:      }
                    602:     }  
                    603:    } else {
1.6       www       604:       &Apache::lonnet::logthis("<font color=blue>WARNING: ".
1.4       www       605:                        "Could not tie coursemap $fn for $uri.</font>"); 
                    606:    }
1.12      www       607:    &Apache::lonmsg::author_res_msg($ENV{'request.course.uri'},$errtext);
1.46      www       608: # ------------------------------------------------- Check for critical messages
                    609: 
                    610:     my @what=&Apache::lonnet::dump('critical',$ENV{'user.domain'},
                    611:                                               $ENV{'user.name'});
                    612:     if ($what[0]) {
                    613: 	if (($what[0] ne 'con_lost') && ($what[0]!~/^error\:/)) {
                    614: 	    $retfurl='/adm/email?critical=display';
                    615:         }
                    616:     }
1.21      www       617:    return ($retfurl,$errtext);
1.1       www       618: }
1.15      www       619: 
                    620: # ------------------------------------------------------- Evaluate state string
                    621: 
                    622: sub evalstate {
                    623:     my $fn=$ENV{'request.course.fn'}.'.state';
1.80      albertel  624:     my $state='';
1.15      www       625:     if (-e $fn) {
1.80      albertel  626: 	my @conditions=();
                    627: 	{
                    628: 	    my $fh=Apache::File->new($fn);
                    629: 	    @conditions=<$fh>;
                    630: 	}  
                    631: 	my $safeeval = new Safe;
                    632: 	my $safehole = new Safe::Hole;
                    633: 	$safeeval->permit("entereval");
                    634: 	$safeeval->permit(":base_math");
                    635: 	$safeeval->deny(":base_io");
                    636: 	$safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT');
                    637: 	foreach my $line (@conditions) {
                    638: 	    chomp($line);
                    639: 	    my ($condition,$weight)=split(/\:/,$line);
                    640: 	    if ($safeeval->reval($condition)) {
                    641: 		if ($weight eq 'force') {
                    642: 		    $state.='3';
                    643: 		} else {
                    644: 		    $state.='2';
                    645: 		}
                    646: 	    } else {
                    647: 		if ($weight eq 'stop') {
                    648: 		    $state.='0';
                    649: 		} else {
                    650: 		    $state.='1';
                    651: 		}
                    652: 	    }
                    653: 	}
1.15      www       654:     }
                    655:     &Apache::lonnet::appenv('user.state.'.$ENV{'request.course.id'} => $state);
                    656:     return $state;
                    657: }
                    658: 
1.1       www       659: 1;
                    660: __END__
                    661: 
1.26      harris41  662: =head1 NAME
                    663: 
                    664: Apache::lonuserstate - Construct and maintain state and binary representation
                    665: of course for user
                    666: 
                    667: =head1 SYNOPSIS
                    668: 
                    669: Invoked by lonroles.pm.
                    670: 
                    671: &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
                    672: 
                    673: =head1 INTRODUCTION
                    674: 
                    675: This module constructs and maintains state and binary representation
                    676: of course for user.
                    677: 
                    678: This is part of the LearningOnline Network with CAPA project
                    679: described at http://www.lon-capa.org.
                    680: 
                    681: =head1 HANDLER SUBROUTINE
                    682: 
                    683: There is no handler subroutine.
                    684: 
                    685: =head1 OTHER SUBROUTINES
                    686: 
                    687: =over 4
                    688: 
                    689: =item *
                    690: 
                    691: loadmap() : Loads map from disk
                    692: 
                    693: =item *
                    694: 
                    695: simplify() : Simplify expression
                    696: 
                    697: =item *
                    698: 
                    699: traceroute() : Build condition hash
                    700: 
                    701: =item *
                    702: 
                    703: accinit() : Cascading conditions, quick access, parameters
1.1       www       704: 
1.26      harris41  705: =item *
1.1       www       706: 
1.26      harris41  707: readmap() : Read map and all submaps
1.1       www       708: 
1.26      harris41  709: =item *
1.1       www       710: 
1.26      harris41  711: evalstate() : Evaluate state string
1.1       www       712: 
1.26      harris41  713: =back
1.1       www       714: 
1.26      harris41  715: =cut

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
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.