--- loncom/lonnet/perl/lonnet.pm 2000/10/28 17:26:35 1.52 +++ loncom/lonnet/perl/lonnet.pm 2000/11/07 17:20:10 1.59 @@ -24,6 +24,7 @@ # revokerole (udom,uname,url,role) : Revoke a role for url # revokecustomrole (udom,uname,url,rdom,rnam,rolename) : Revoke a custom role # appenv(hash) : adds hash to session environment +# delenv(varname) : deletes all environment entries starting with varname # store(hash) : stores hash permanently for this url # cstore(hash) : critical store # restore : returns hash for this url @@ -41,7 +42,7 @@ # directcondval(index) : reading condition value of single condition from # state string # condval(index) : value of condition index based on state -# varval(name) : value of a variable +# EXT(name) : value of a variable # refreshstate() : refresh the state information string # symblist(map,hash) : Updates symbolic storage links # symbread([filename]) : returns the data handle (filename optional) @@ -66,8 +67,8 @@ # 08/22,08/28,08/31,09/01,09/02,09/04,09/05,09/25,09/28,09/30 Gerd Kortemeyer # 10/04 Gerd Kortemeyer # 10/04 Guy Albertelli -# 10/06,10/09,10/10,10/11,10/14,10/20,10/23,10/25,10/26,10/27,10/28 -# Gerd Kortemeyer +# 10/06,10/09,10/10,10/11,10/14,10/20,10/23,10/25,10/26,10/27,10/28,10/29, +# 10/30,10/31,11/2 Gerd Kortemeyer package Apache::lonnet; @@ -250,6 +251,35 @@ sub appenv { } return 'ok'; } +# ----------------------------------------------------- Delete from Environment + +sub delenv { + my $delthis=shift; + my %newenv=(); + if (($delthis=~/user\.role/) || ($delthis=~/user\.priv/)) { + &logthis("<font color=blue>WARNING: ". + "Attempt to delete from environment ".$delthis); + return 'error'; + } + my @oldenv; + { + my $fh; + unless ($fh=Apache::File->new("$ENV{'user.environment'}")) { + return 'error'; + } + @oldenv=<$fh>; + } + { + my $fh; + unless ($fh=Apache::File->new(">$ENV{'user.environment'}")) { + return 'error'; + } + map { + unless ($_=~/^$delthis/) { print $fh $_; } + } @oldenv; + } + return 'ok'; +} # ------------------------------ Find server with least workload from spare.tab @@ -499,7 +529,9 @@ sub coursedescription { if ($chome ne 'no_host') { my $rep=reply("dump:$cdomain:$cnum:environment",$chome); if ($rep ne 'con_lost') { - my %cachehash=(); + my $normalid=$courseid; + $normalid=~s/\//\_/g; + my %envhash=(); my %returnhash=('home' => $chome, 'domain' => $cdomain, 'num' => $cnum); @@ -508,14 +540,13 @@ sub coursedescription { $name=&unescape($name); $value=&unescape($value); $returnhash{$name}=$value; - if ($name eq 'description') { - $cachehash{$courseid}=$value; - } + $envhash{'course.'.$normalid.'.'.$name}=$value; } split(/\&/,$rep); $returnhash{'url'}='/res/'.declutter($returnhash{'url'}); $returnhash{'fn'}=$perlvar{'lonDaemons'}.'/tmp/'. $ENV{'user.name'}.'_'.$cdomain.'_'.$cnum; - put ('nohist_coursedescriptions',%cachehash); + $envhash{'course.'.$normalid.'.last_cache'}=time; + &appenv(%envhash); return %returnhash; } } @@ -717,9 +748,9 @@ sub allowed { my ($priv,$uri)=@_; $uri=&declutter($uri); -# Free bre access to adm resources +# Free bre access to adm and meta resources - if (($uri=~/^adm\//) && ($priv eq 'bre')) { + if ((($uri=~/^adm\//) || ($uri=~/\.meta$/)) && ($priv eq 'bre')) { return 'F'; } @@ -776,7 +807,7 @@ sub allowed { my $pathname=$uri; $pathname=~s/\/$filename$//; if ($ENV{'acc.res.'.$ENV{'request.course.id'}.'.'.$pathname}=~ - /\&$filename\:(\d+)\&/) { + /\&$filename\:([\d\|]+)\&/) { $statecond=$1; if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.$courseprivid} =~/$priv\&([^\:]*)/) { @@ -784,18 +815,27 @@ sub allowed { $checkreferer=0; } } + if (($ENV{'HTTP_REFERER'}) && ($checkreferer)) { - my @uriparts=split(/\//,&declutter($ENV{'HTTP_REFERER'})); + my $refuri=$ENV{'HTTP_REFERER'}; + $refuri=~s/^http\:\/\/$ENV{'request.host'}//i; + $refuri=&declutter($refuri); + my @uriparts=split(/\//,$refuri); my $filename=$uriparts[$#uriparts]; - my $pathname=$uri; + my $pathname=$refuri; $pathname=~s/\/$filename$//; - if ($ENV{'acc.res.'.$ENV{'request.course.id'}.'.'.$pathname}=~ - /\&$filename\:(\d+)\&/) { - $statecond=$1; + my @filenameparts=split(/\./,$uri); + if (&fileembstyle($filenameparts[$#filenameparts]) ne 'ssi') { + if ($ENV{'acc.res.'.$ENV{'request.course.id'}.'.'.$pathname}=~ + /\&$filename\:([\d\|]+)\&/) { + my $refstatecond=$1; if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.$courseprivid} =~/$priv\&([^\:]*)/) { $thisallowed.=$1; + $uri=$refuri; + $statecond=$refstatecond; } + } } } } @@ -824,37 +864,43 @@ sub allowed { # # Possibly locked functionality, check all courses +# Locks might take effect only after 10 minutes cache expiration for other +# courses, and 2 minutes for current course my $envkey; if ($thisallowed=~/L/) { foreach $envkey (keys %ENV) { - if ($envkey=~/^user\.role\.st\.([^\.]*)/) { - my ($cdom,$cnum,$csec)=split(/\//,$1); - my %locks=(); - map { - my ($name,$value)=split(/\=/,$_); - $locks{&unescape($name)}=&unescape($value); - } split(/\&/,&reply('get:'.$cdom.':'.$cnum. - ':environment:'.&escape('priv.'.$priv.'.lock.sections'). - ':'.&escape('priv.'.$priv.'.lock.expire'). - ':'.&escape('res.'.$uri.'.lock.sections'). - ':'.&escape('res.'.$uri.'.lock.expire'), - &homeserver($cnum,$cdom))); - if (($locks{'res.'.$uri.'.lock.sections'}=~/\,$csec\,/) || - ($locks{'res.'.$uri.'.lock.sections'} eq 'all')) { - if ($locks{'res.'.$uri.'.lock.expire'}>time) { - &log('Locked by res: '.$priv.' for '.$uri.' due to '. + if ($envkey=~/^user\.role\.(st|ta)\.([^\.]*)/) { + my $courseid=$2; + my $roleid=$1.'.'.$2; + my $expiretime=600; + if ($ENV{'request.role'} eq $roleid) { + $expiretime=120; + } + my ($cdom,$cnum,$csec)=split(/\//,$courseid); + my $prefix='course.'.$cdom.'_'.$cnum.'.'; + if ((time-$ENV{$prefix.'last_cache'})>$expiretime) { + &coursedescription($courseid); + } + if (($ENV{$prefix.'res.'.$uri.'.lock.sections'}=~/\,$csec\,/) + || ($ENV{$prefix.'res.'.$uri.'.lock.sections'} eq 'all')) { + if ($ENV{$prefix.'res.'.$uri.'.lock.expire'}>time) { + &log($ENV{'user.domain'},$ENV{'user.name'}, + $ENV{'user.host'}, + 'Locked by res: '.$priv.' for '.$uri.' due to '. $cdom.'/'.$cnum.'/'.$csec.' expire '. - $locks{'priv.'.$priv.'.lock.expire'}); + $ENV{$prefix.'priv.'.$priv.'.lock.expire'}); return ''; } } - if (($locks{'priv.'.$priv.'.lock.sections'}=~/\,$csec\,/) || - ($locks{'priv.'.$priv.'.lock.sections'} eq 'all')) { - if ($locks{'priv.'.$priv.'.lock.expire'}>time) { - &log('Locked by priv: '.$priv.' for '.$uri.' due to '. + if (($ENV{$prefix.'priv.'.$priv.'.lock.sections'}=~/\,$csec\,/) + || ($ENV{$prefix.'priv.'.$priv.'.lock.sections'} eq 'all')) { + if ($ENV{'priv.'.$priv.'.lock.expire'}>time) { + &log($ENV{'user.domain'},$ENV{'user.name'}, + $ENV{'user.host'}, + 'Locked by priv: '.$priv.' for '.$uri.' due to '. $cdom.'/'.$cnum.'/'.$csec.' expire '. - $locks{'priv.'.$priv.'.lock.expire'}); + $ENV{$prefix.'priv.'.$priv.'.lock.expire'}); return ''; } } @@ -874,6 +920,41 @@ sub allowed { # Now user is definitely in a course # + +# Course preferences + + if ($thisallowed=~/C/) { + my $rolecode=(split(/\./,$ENV{'request.role'}))[0]; + if ($ENV{'course.'.$ENV{'request.course.id'}.'.'.$priv.'.roles.denied'} + =~/\,$rolecode\,/) { + &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.host'}, + 'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode.' in '. + $ENV{'request.course.id'}); + return ''; + } + } + +# Resource preferences + + if ($thisallowed=~/R/) { + my $rolecode=(split(/\./,$ENV{'request.role'}))[0]; + my $filename=$perlvar{'lonDocRoot'}.'/res/'.$uri.'.meta'; + if (-e $filename) { + my @content; + { + my $fh=Apache::File->new($filename); + @content=<$fh>; + } + if (join('',@content)=~ + /\<roledeny[^\>]*\>[^\<]*$rolecode[^\<]*\<\/roledeny\>/) { + &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.host'}, + 'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode); + return ''; + + } + } + } + # Restricted by state? if ($thisallowed=~/X/) { @@ -1071,8 +1152,16 @@ sub directcondval { sub condval { my $condidx=shift; my $result=0; + my $allpathcond=''; + map { + if (defined($ENV{'acc.cond.'.$ENV{'request.course.id'}.'.'.$_})) { + $allpathcond.= + '('.$ENV{'acc.cond.'.$ENV{'request.course.id'}.'.'.$_}.')|'; + } + } split(/\|/,$condidx); + $allpathcond=~s/\|$//; if ($ENV{'request.course.id'}) { - if (defined($ENV{'acc.cond.'.$ENV{'request.course.id'}.'.'.$condidx})) { + if ($allpathcond) { my $operand='|'; my @stack; map { @@ -1095,8 +1184,7 @@ sub condval { $result=$result>$new?$result:$new; } } - } ($ENV{'acc.cond.'.$ENV{'request.course.id'}.'.'.$condidx}=~ - /(\d+|\(|\)|\&|\|)/g); + } ($allpathcond=~/(\d+|\(|\)|\&|\|)/g); } } return $result; @@ -1104,7 +1192,7 @@ sub condval { # --------------------------------------------------------- Value of a Variable -sub varval { +sub EXT { my $varname=shift; my ($realm,$space,$qualifier,@therest)=split(/\./,$varname); my $rest; @@ -1113,15 +1201,21 @@ sub varval { } else { $rest=''; } + my $qualifierrest=$qualifier; + if ($rest) { $qualifierrest.='.'.$rest; } + my $spacequalifierrest=$space; + if ($qualifierrest) { $spacequalifierrest.='.'.$qualifierrest; } if ($realm eq 'user') { # --------------------------------------------------------------- user.resource if ($space eq 'resource') { + my %restored=&restore; + return $restored{$qualifierrest}; # ----------------------------------------------------------------- user.access } elsif ($space eq 'access') { return &allowed($qualifier,$rest); # ------------------------------------------ user.preferences, user.environment } elsif (($space eq 'preferences') || ($space eq 'environment')) { - return $ENV{join('.',('environment',$qualifier,$rest))}; + return $ENV{join('.',('environment',$qualifierrest))}; # ----------------------------------------------------------------- user.course } elsif ($space eq 'course') { return $ENV{join('.',('request.course',$qualifier))}; @@ -1149,33 +1243,42 @@ sub varval { # ------------------------------------------------------------- request.browser if ($space eq 'browser') { return $ENV{'browser.'.$qualifier}; - } elsif ($space eq 'filename') { - return $ENV{'request.filename'}; +# ------------------------------------------------------------ request.filename + } else { + return $ENV{'request.'.$spacequalifierrest}; } } elsif ($realm eq 'course') { # ---------------------------------------------------------- course.description - if ($space eq 'description') { - my %reply=&coursedescription($ENV{'request.course.id'}); - return $reply{'description'}; -# ------------------------------------------------------------------- course.id - } elsif ($space eq 'id') { - return $ENV{'request.course.id'}; -# -------------------------------------------------- Any other course namespace - } else { - my ($cdom,$cnam)=split(/\_/,$ENV{'request.course.id'}); - my $chome=&homeserver($cnam,$cdom); - my $item=join('.',($qualifier,$rest)); - return &unescape - (&reply('get:'.$cdom.':'.$cnam.':'.&escape($space).':'. - &escape($item),$chome)); + my $section=''; + if ($ENV{'request.course.sec'}) { + $section='_'.$ENV{'request.course.sec'}; } + return $ENV{'course.'.$ENV{'request.course.id'}.$section.'.'. + $spacequalifierrest}; + } elsif ($realm eq 'resource') { +# ----------------------------------------------------------- resource metadata + my $uri=&declutter($ENV{'request.filename'}); + my $filename=$perlvar{'lonDocRoot'}.'/res/'.$ENV.'.meta'; + if (-e $filename) { + my @content; + { + my $fh=Apache::File->new($filename); + @content=<$fh>; + } + if (join('',@content)=~ + /\<$space[^\>]*\>([^\<]*)\<\/$space\>/) { + return $1; + } else { + return ''; + } + } } elsif ($realm eq 'userdata') { my $uhome=&homeserver($qualifier,$space); # ----------------------------------------------- userdata.domain.name.resource # ---------------------------------------------------- Any other user namespace } elsif ($realm eq 'environment') { # ----------------------------------------------------------------- environment - return $ENV{join('.',($space,$qualifier,$rest))}; + return $ENV{$spacequalifierrest}; } elsif ($realm eq 'system') { # ----------------------------------------------------------------- system.time if ($space eq 'time') { @@ -1315,12 +1418,17 @@ sub filelocation { my ($dir,$file) = @_; my $location; $file=~ s/^\s*(\S+)\s*$/$1/; ## strip off leading and trailing spaces - $file=~s/^$perlvar{'lonDocRoot'}//; - $file=~s:^/*res::; - if ( !( $file =~ m:^/:) ) { - $location = $dir. '/'.$file; + if ($file=~m:^/~:) { # is a contruction space reference + $location = $file; + $location =~ s:/~(.*?)/(.*):/home/$1/public_html/$2:; } else { - $location = '/home/httpd/html/res'.$file; + $file=~s/^$perlvar{'lonDocRoot'}//; + $file=~s:^/*res::; + if ( !( $file =~ m:^/:) ) { + $location = $dir. '/'.$file; + } else { + $location = '/home/httpd/html/res'.$file; + } } $location=~s://+:/:g; # remove duplicate / while ($location=~m:/\.\./:) {$location=~ s:/[^/]+/\.\./:/:g;} #remove dir/..