--- loncom/lonnet/perl/lonnet.pm 2000/09/01 21:51:30 1.27 +++ loncom/lonnet/perl/lonnet.pm 2000/09/26 20:07:24 1.32 @@ -6,7 +6,12 @@ # plaintext(short) : plain text explanation of short term # fileembstyle(ext) : embed style in page for file extension # filedescription(ext) : descriptor text for file extension -# allowed(short,url) : returns codes for allowed actions F,R,S,X,C +# allowed(short,url) : returns codes for allowed actions +# F: full access +# U,I,K: authentication modes (cxx only) +# '': forbidden +# 1: user needs to choose course +# 2: browse allowed # definerole(rolename,sys,dom,cou) : define a custom role rolename # set priviledges in format of lonTabs/roles.tab for # system, domain and course level, @@ -30,7 +35,11 @@ # hash # repcopy(filename) : replicate file # dirlist(url) : gets a directory listing -# condval(index) : value of condition index based on state +# condval(index) : value of condition index based on state +# varval(name) : value of a variable +# refreshstate() : refresh the state information string +# symblist(map,hash) : Updates symbolic storage links +# rndseed() : returns a random seed # # 6/1/99,6/2,6/10,6/11,6/12,6/14,6/26,6/28,6/29,6/30, # 7/1,7/2,7/9,7/10,7/12,7/14,7/15,7/19, @@ -42,7 +51,7 @@ # 06/26 Ben Tyszka # 06/30,07/15,07/17,07/18,07/20,07/21,07/22,07/25 Gerd Kortemeyer # 08/14 Ben Tyszka -# 08/22,08/28,08/31,09/01 Gerd Kortemeyer +# 08/22,08/28,08/31,09/01,09/02,09/04,09/05,09/25 Gerd Kortemeyer package Apache::lonnet; @@ -53,6 +62,7 @@ use HTTP::Headers; use vars qw(%perlvar %hostname %homecache %spareid %hostdom %libserv %pr %prp %fe %fd $readit); use IO::Socket; +use GDBM_File; use Apache::Constants qw(:common :http); # --------------------------------------------------------------------- Logging @@ -399,28 +409,45 @@ sub log { # ----------------------------------------------------------------------- Store sub store { - my %storehash=shift; + my %storehash=@_; + my $symb; + unless ($symb=escape(&symbread())) { return ''; } + my $namespace; + unless ($namespace=$ENV{'request.course.uri'}) { return ''; } + $namespace=~s/\//\_\_/g; + $namespace=~s/\./\_/g; + $namespace=escape($namespace); my $namevalue=''; map { $namevalue.=escape($_).'='.escape($storehash{$_}).'&'; } keys %storehash; $namevalue=~s/\&$//; - return reply("store:$ENV{'user.domain'}:$ENV{'user.name'}:" - ."$ENV{'user.class'}:$ENV{'request.filename'}:$namevalue", + return reply( + "store:$ENV{'user.domain'}:$ENV{'user.name'}:$namespace:$symb:$namevalue", "$ENV{'user.home'}"); } # --------------------------------------------------------------------- Restore sub restore { - my $answer=reply("restore:$ENV{'user.domain'}:$ENV{'user.name'}:" - ."$ENV{'user.class'}:$ENV{'request.filename'}", - "$ENV{'user.home'}"); + my $symb; + unless ($symb=escape(&symbread())) { return ''; } + my $namespace; + unless ($namespace=$ENV{'request.course.uri'}) { return ''; } + $namespace=~s/\//\_\_/g; + $namespace=~s/\./\_/g; + $namespace=escape($namespace); + my $answer=reply( + "restore:$ENV{'user.domain'}:$ENV{'user.name'}:$namespace:$symb", + "$ENV{'user.home'}"); my %returnhash=(); map { my ($name,$value)=split(/\=/,$_); $returnhash{&unescape($name)}=&unescape($value); } split(/\&/,$answer); + map { + $returnhash{$_}=$returnhash{$returnhash{'version'}.':'.$_}; + } split(/\:/,$returnhash{$returnhash{'version'}.':keys'}); return %returnhash; } @@ -524,7 +551,7 @@ sub get { my %returnhash=(); map { my ($key,$value)=split(/=/,$_); - $returnhash{unespace($key)}=unescape($value); + $returnhash{unescape($key)}=unescape($value); } @pairs; return %returnhash; } @@ -552,7 +579,7 @@ sub dump { my %returnhash=(); map { my ($key,$value)=split(/=/,$_); - $returnhash{unespace($key)}=unescape($value); + $returnhash{unescape($key)}=unescape($value); } @pairs; return %returnhash; } @@ -585,7 +612,7 @@ sub eget { my %returnhash=(); map { my ($key,$value)=split(/=/,$_); - $returnhash{unespace($key)}=unescape($value); + $returnhash{unescape($key)}=unescape($value); } @pairs; return %returnhash; } @@ -596,9 +623,15 @@ sub allowed { my ($priv,$uri)=@_; $uri=~s/^\/res//; $uri=~s/^\///; - if ($uri=~/^adm\//) { + +# Free bre access to adm resources + + if (($uri=~/^adm\//) && ($priv eq 'bre')) { return 'F'; } + +# Gather priviledges over system and domain + my $thisallowed=''; if ($ENV{'user.priv./'}=~/$priv\&([^\:]*)/) { $thisallowed.=$1; @@ -606,12 +639,95 @@ sub allowed { if ($ENV{'user.priv./'.(split(/\//,$uri))[0].'/'}=~/$priv\&([^\:]*)/) { $thisallowed.=$1; } - if ($ENV{'user.priv./'.$uri}=~/$priv\&([^\:]*)/) { - $thisallowed.=$1; + +# Full access at system or domain level? Exit. + + if ($thisallowed=~/F/) { + return 'F'; + } + +# The user does not have full access at system or domain level +# Course level access control + +# uri itself refering to a course? + + if ($uri=~/\.course$/) { + if ($ENV{'user.priv./'.$uri}=~/$priv\&([^\:]*)/) { + $thisallowed.=$1; + } +# Full access on course level? Exit. + if ($thisallowed=~/F/) { + return 'F'; + } + +# uri is refering to an individual resource; user needs to be in a course + + } else { + + unless(defined($ENV{'request.course.uri'})) { + return '1'; + } + +# Get access priviledges for course + + if ($ENV{'user.priv./'.$ENV{'request.course.uri'}}=~/$priv\&([^\:]*)/) { + $thisallowed.=$1; + } + +# See if resource or referer is part of this course + + my @uriparts=split(/\//,$uri); + my $urifile=$uriparts[$#uriparts]; + $urifile=~/\.(\w+)$/; + my $uritype=$1; + $#uriparts--; + my $uripath=join('/',@uriparts); + my $uricond=-1; + if ($ENV{'acc.res.'.$ENV{'request.course'}.'.'.$uripath}=~ + /\&$urifile\:(\d+)\&/) { + $uricond=$1; + } elsif (($fe{$uritype} eq 'emb') || ($fe{$uritype} eq 'img')) { + my $refuri=$ENV{'HTTP_REFERER'}; + $refuri=~s/^\/res//; + $refuri=~s/^\///; + @uriparts=split(/\//,$refuri); + $urifile=$uriparts[$#uriparts]; + $#uriparts--; + $uripath=join('/',@uriparts); + if ($ENV{'acc.res.'.$ENV{'request.course'}.'.'.$uripath}=~ + /\&$urifile\:(\d+)\&/) { + $uricond=$1; + } + } + + if ($uricond>=0) { + +# The resource is part of the course +# If user had full access on course level, go ahead + + if ($thisallowed=~/F/) { + return 'F'; + } + +# Restricted by state? + + if ($thisallowed=~/X/) { + if (&condval($uricond)>1) { + return '2'; + } else { + return ''; + } + } + } } return $thisallowed; } +# ---------------------------------------------------------- Refresh State Info + +sub refreshstate { +} + # ----------------------------------------------------------------- Define Role sub definerole { @@ -680,6 +796,7 @@ sub filedecription { sub assignrole { my ($udom,$uname,$url,$role,$end,$start)=@_; my $mrole; + $url=declutter($url); if ($role =~ /^cr\//) { unless ($url=~/\.course$/) { return 'invalid'; } unless (allowed('ccr',$url)) { return 'refused'; } @@ -782,7 +899,7 @@ sub condval { my $condidx=shift; my $result=0; if ($ENV{'request.course'}) { - if ($ENV{'acc.cond.'.$ENV{'request.course'}.'.'.$condidx}) { + if (defined($ENV{'acc.cond.'.$ENV{'request.course'}.'.'.$condidx})) { my $operand='|'; my @stack; map { @@ -813,6 +930,109 @@ sub condval { return $result; } +# --------------------------------------------------------- Value of a Variable + +sub varval { + my ($realm,$space,@components)=split(/\./,shift); + my $value=''; + if ($realm eq 'user') { + if ($space=~/^resource/) { + $space=~s/^resource\[//; + $space=~s/\]$//; + + } else { + } + } elsif ($realm eq 'course') { + } elsif ($realm eq 'session') { + } elsif ($realm eq 'system') { + } + return $value; +} + +# ------------------------------------------------- Update symbolic store links + +sub symblist { + my ($mapname,%newhash)=@_; + $mapname=declutter($mapname); + my %hash; + if (($ENV{'request.course.fn'}) && (%newhash)) { + if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.'_symb.db', + &GDBM_WRCREAT,0640)) { + map { + $hash{declutter($_)}=$mapname.'___'.$newhash{$_}; + } keys %newhash; + if (untie(%hash)) { + return 'ok'; + } + } + } + return 'error'; +} + +# ------------------------------------------------------ Return symb list entry + +sub symbread { + my %hash; + my $syval; + if (($ENV{'request.course.fn'}) && ($ENV{'request.filename'})) { + if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.'_symb.db', + &GDBM_READER,0640)) { + my $thisfn=declutter($ENV{'request.filename'}); + $syval=$hash{$thisfn}; + if (untie(%hash)) { + unless ($syval=~/\_\d+$/) { + unless ($ENV{'form.request.prefix'}=~/\.(\d+)\_$/) { + return ''; + } + $syval.=$1; + } + $syval.='___'.$thisfn; + return $syval; + } + } + } + return ''; +} + +# ---------------------------------------------------------- Return random seed + +sub numval { + my $txt=shift; + $txt=~tr/A-J/0-9/; + $txt=~tr/a-j/0-9/; + $txt=~tr/K-T/0-9/; + $txt=~tr/k-t/0-9/; + $txt=~tr/U-Z/0-5/; + $txt=~tr/u-z/0-5/; + $txt=~s/\D//g; + return int($txt); +} + +sub rndseed { + my $symb; + unless ($symb=&symbread()) { return ''; } + my $symbchck=unpack("%32C*",$symb); + my $symbseed=numval($symb)%$symbchck; + my $namechck=unpack("%32C*",$ENV{'user.name'}); + my $nameseed=numval($ENV{'user.name'})%$namechck; + return int( $symbseed + .$nameseed + .unpack("%32C*",$ENV{'user.domain'}) + .unpack("%32C*",$ENV{'request.course.uri'}) + .$namechck + .$symbchck); +} + +# ------------------------------------------------------------- Declutters URLs + +sub declutter { + my $thisfn=shift; + $thisfn=~s/^$perlvar{'lonDocRoot'}//; + $thisfn=~s/^\///; + $thisfn=~s/^res\///; + return $thisfn; +} + # -------------------------------------------------------- Escape Special Chars sub escape {