--- loncom/lonnet/perl/lonnet.pm 2003/11/10 23:57:49 1.446 +++ loncom/lonnet/perl/lonnet.pm 2004/03/30 20:46:24 1.480 @@ -1,7 +1,7 @@ # The LearningOnline Network # TCP networking package # -# $Id: lonnet.pm,v 1.446 2003/11/10 23:57:49 albertel Exp $ +# $Id: lonnet.pm,v 1.480 2004/03/30 20:46:24 www Exp $ # # Copyright Michigan State University Board of Trustees # @@ -30,7 +30,6 @@ package Apache::lonnet; use strict; -use Apache::File; use LWP::UserAgent(); use HTTP::Headers; use vars @@ -52,12 +51,35 @@ use Storable qw(lock_store lock_nstore l use Time::HiRes(); my $readit; +=pod + +=head1 Package Variables + +These are largely undocumented, so if you decipher one please note it here. + +=over 4 + +=item $processmarker + +Contains the time this process was started and this servers host id. + +=item $dumpcount + +Counts the number of times a message log flush has been attempted (regardless +of success) by this process. Used as part of the filename when messages are +delayed. + +=back + +=cut + + # --------------------------------------------------------------------- Logging sub logtouch { my $execdir=$perlvar{'lonDaemons'}; - unless (-e "$execdir/logs/lonnet.log") { - my $fh=Apache::File->new(">>$execdir/logs/lonnet.log"); + unless (-e "$execdir/logs/lonnet.log") { + open(my $fh,">>$execdir/logs/lonnet.log"); close $fh; } my ($wwwuid,$wwwgid)=(getpwnam('www'))[2,3]; @@ -69,8 +91,10 @@ sub logthis { my $execdir=$perlvar{'lonDaemons'}; my $now=time; my $local=localtime($now); - my $fh=Apache::File->new(">>$execdir/logs/lonnet.log"); - print $fh "$local ($$): $message\n"; + if (open(my $fh,">>$execdir/logs/lonnet.log")) { + print $fh "$local ($$): $message\n"; + close($fh); + } return 1; } @@ -79,8 +103,10 @@ sub logperm { my $execdir=$perlvar{'lonDaemons'}; my $now=time; my $local=localtime($now); - my $fh=Apache::File->new(">>$execdir/logs/lonnet.perm.log"); - print $fh "$now:$message:$local\n"; + if (open(my $fh,">>$execdir/logs/lonnet.perm.log")) { + print $fh "$now:$message:$local\n"; + close($fh); + } return 1; } @@ -132,7 +158,7 @@ sub reconlonc { my $peerfile=shift; &logthis("Trying to reconnect for $peerfile"); my $loncfile="$perlvar{'lonDaemons'}/logs/lonc.pid"; - if (my $fh=Apache::File->new("$loncfile")) { + if (open(my $fh,"<$loncfile")) { my $loncpid=<$fh>; chomp($loncpid); if (kill 0 => $loncpid) { @@ -180,18 +206,20 @@ sub critical { "$perlvar{'lonSockDir'}/delayed/$now.$dumpcount.$$.$middlename.$server"; $dumpcount++; { - my $dfh; - if ($dfh=Apache::File->new(">$dfilename")) { - print $dfh "$cmd\n"; - } + my $dfh; + if (open($dfh,">$dfilename")) { + print $dfh "$cmd\n"; + close($dfh); + } } sleep 2; my $wcmd=''; { - my $dfh; - if ($dfh=Apache::File->new("$dfilename")) { - $wcmd=<$dfh>; - } + my $dfh; + if (open($dfh,"<$dfilename")) { + $wcmd=<$dfh>; + close($dfh); + } } chomp($wcmd); if ($wcmd eq $cmd) { @@ -230,10 +258,10 @@ sub transfer_profile_to_env { my ($lonidsdir,$handle)=@_; my @profile; { - my $idf=Apache::File->new("$lonidsdir/$handle.id"); + open(my $idf,"$lonidsdir/$handle.id"); flock($idf,LOCK_SH); @profile=<$idf>; - $idf->close(); + close($idf); } my $envi; my %Remove; @@ -269,47 +297,47 @@ sub appenv { } my $lockfh; - unless ($lockfh=Apache::File->new("$ENV{'user.environment'}")) { - return 'error: '.$!; + unless (open($lockfh,"$ENV{'user.environment'}")) { + return 'error: '.$!; } unless (flock($lockfh,LOCK_EX)) { &logthis("WARNING: ". 'Could not obtain exclusive lock in appenv: '.$!); - $lockfh->close(); + close($lockfh); return 'error: '.$!; } my @oldenv; { - my $fh; - unless ($fh=Apache::File->new("$ENV{'user.environment'}")) { - return 'error: '.$!; - } - @oldenv=<$fh>; - $fh->close(); + my $fh; + unless (open($fh,"$ENV{'user.environment'}")) { + return 'error: '.$!; + } + @oldenv=<$fh>; + close($fh); } for (my $i=0; $i<=$#oldenv; $i++) { chomp($oldenv[$i]); if ($oldenv[$i] ne '') { - my ($name,$value)=split(/=/,$oldenv[$i]); - unless (defined($newenv{$name})) { - $newenv{$name}=$value; - } + my ($name,$value)=split(/=/,$oldenv[$i]); + unless (defined($newenv{$name})) { + $newenv{$name}=$value; + } } } { - my $fh; - unless ($fh=Apache::File->new(">$ENV{'user.environment'}")) { - return 'error'; - } - my $newname; - foreach $newname (keys %newenv) { - print $fh "$newname=$newenv{$newname}\n"; - } - $fh->close(); + my $fh; + unless (open($fh,">$ENV{'user.environment'}")) { + return 'error'; + } + my $newname; + foreach $newname (keys %newenv) { + print $fh "$newname=$newenv{$newname}\n"; + } + close($fh); } - - $lockfh->close(); + + close($lockfh); return 'ok'; } # ----------------------------------------------------- Delete from Environment @@ -324,34 +352,39 @@ sub delenv { } my @oldenv; { - my $fh; - unless ($fh=Apache::File->new("$ENV{'user.environment'}")) { - return 'error'; - } - unless (flock($fh,LOCK_SH)) { - &logthis("WARNING: ". - 'Could not obtain shared lock in delenv: '.$!); - $fh->close(); - return 'error: '.$!; - } - @oldenv=<$fh>; - $fh->close(); + my $fh; + unless (open($fh,"$ENV{'user.environment'}")) { + return 'error'; + } + unless (flock($fh,LOCK_SH)) { + &logthis("WARNING: ". + 'Could not obtain shared lock in delenv: '.$!); + close($fh); + return 'error: '.$!; + } + @oldenv=<$fh>; + close($fh); } { - my $fh; - unless ($fh=Apache::File->new(">$ENV{'user.environment'}")) { - return 'error'; - } - unless (flock($fh,LOCK_EX)) { - &logthis("WARNING: ". - 'Could not obtain exclusive lock in delenv: '.$!); - $fh->close(); - return 'error: '.$!; - } - foreach (@oldenv) { - unless ($_=~/^$delthis/) { print $fh $_; } - } - $fh->close(); + my $fh; + unless (open($fh,">$ENV{'user.environment'}")) { + return 'error'; + } + unless (flock($fh,LOCK_EX)) { + &logthis("WARNING: ". + 'Could not obtain exclusive lock in delenv: '.$!); + close($fh); + return 'error: '.$!; + } + foreach (@oldenv) { + if ($_=~/^$delthis/) { + my ($key,undef) = split('=',$_); + delete($ENV{$key}); + } else { + print $fh $_; + } + } + close($fh); } return 'ok'; } @@ -387,10 +420,11 @@ sub overloaderror { unless ($checkserver) { $checkserver=$perlvar{'lonHostID'}; } my $loadavg; if ($checkserver eq $perlvar{'lonHostID'}) { - my $loadfile=Apache::File->new('/proc/loadavg'); + open(my $loadfile,'/proc/loadavg'); $loadavg=<$loadfile>; $loadavg =~ s/\s.*//g; $loadavg = 100*$loadavg/$perlvar{'lonLoadLim'}; + close($loadfile); } else { $loadavg=&reply('load',$checkserver); } @@ -477,38 +511,16 @@ sub changepass { sub queryauthenticate { my ($uname,$udom)=@_; - if (($perlvar{'lonRole'} eq 'library') && - ($udom eq $perlvar{'lonDefDomain'})) { - my $answer=reply("encrypt:currentauth:$udom:$uname", - $perlvar{'lonHostID'}); - unless ($answer eq 'unknown_user' or $answer eq 'refused') { - if (length($answer)) { - return $answer; - } - else { - &logthis("User $uname at $udom lacks an authentication mechanism"); - return 'no_host'; - } - } - } - - my $tryserver; - foreach $tryserver (keys %libserv) { - if ($hostdom{$tryserver} eq $udom) { - my $answer=reply("encrypt:currentauth:$udom:$uname",$tryserver); - unless ($answer eq 'unknown_user' or $answer eq 'refused') { - if (length($answer)) { - return $answer; - } - else { - &logthis("User $uname at $udom lacks an authentication mechanism"); - return 'no_host'; - } - } - } + my $uhome=&homeserver($uname,$udom); + if (!$uhome) { + &logthis("User $uname at $udom is unknown when looking for authentication mechanism"); + return 'no_host'; + } + my $answer=reply("encrypt:currentauth:$udom:$uname",$uhome); + if ($answer =~ /^(unknown_user|refused|con_lost)/) { + &logthis("User $uname at $udom threw error $answer when checking authentication mechanism"); } - &logthis("User $uname at $udom lacks an authentication mechanism"); - return 'no_host'; + return $answer; } # --------- Try to authenticate user from domain's lib servers (first this one) @@ -517,38 +529,21 @@ sub authenticate { my ($uname,$upass,$udom)=@_; $upass=escape($upass); $uname=~s/\W//g; - if (($perlvar{'lonRole'} eq 'library') && - ($udom eq $perlvar{'lonDefDomain'})) { - my $answer=reply("encrypt:auth:$udom:$uname:$upass",$perlvar{'lonHostID'}); - if ($answer =~ /authorized/) { - if ($answer eq 'authorized') { - &logthis("User $uname at $udom authorized by local server"); - return $perlvar{'lonHostID'}; - } - if ($answer eq 'non_authorized') { - &logthis("User $uname at $udom rejected by local server"); - return 'no_host'; - } - } - } - - my $tryserver; - foreach $tryserver (keys %libserv) { - if ($hostdom{$tryserver} eq $udom) { - my $answer=reply("encrypt:auth:$udom:$uname:$upass",$tryserver); - if ($answer =~ /authorized/) { - if ($answer eq 'authorized') { - &logthis("User $uname at $udom authorized by $tryserver"); - return $tryserver; - } - if ($answer eq 'non_authorized') { - &logthis("User $uname at $udom rejected by $tryserver"); - return 'no_host'; - } - } - } + my $uhome=&homeserver($uname,$udom); + if (!$uhome) { + &logthis("User $uname at $udom is unknown in authenticate"); + return 'no_host'; + } + my $answer=reply("encrypt:auth:$udom:$uname:$upass",$uhome); + if ($answer eq 'authorized') { + &logthis("User $uname at $udom authorized by $uhome"); + return $uhome; + } + if ($answer eq 'non_authorized') { + &logthis("User $uname at $udom rejected by $uhome"); + return 'no_host'; } - &logthis("User $uname at $udom could not be authenticated"); + &logthis("User $uname at $udom threw error $answer when checking authentication mechanism"); return 'no_host'; } @@ -654,7 +649,7 @@ sub assign_access_key { $uname=$ENV{'user.domain'} unless (defined($uname)); my %existing=&get('accesskeys',[$ckey],$cdom,$cnum); if (($existing{$ckey}=~/^\#(.*)$/) || # - new key - ($existing{$ckey}=~/^$uname\:$udom\#(.*)$/)) { + ($existing{$ckey}=~/^\Q$uname\E\:\Q$udom\E\#(.*)$/)) { # assigned to this person # - this should not happen, # unless something went wrong @@ -761,7 +756,7 @@ sub validate_access_key { $udom=$ENV{'user.name'} unless (defined($udom)); $uname=$ENV{'user.domain'} unless (defined($uname)); my %existing=&get('accesskeys',[$ckey],$cdom,$cnum); - return ($existing{$ckey}=~/^$uname\:$udom\#/); + return ($existing{$ckey}=~/^\Q$uname\E\:\Q$udom\E\#/); } # ------------------------------------- Find the section of student in a course @@ -789,7 +784,7 @@ sub getsection { &homeserver($unam,$udom)))) { my ($key,$value)=split(/\=/,$_); $key=&unescape($key); - next if ($key !~/^$courseid(?:\/)*(\w+)*\_st$/); + next if ($key !~/^\Q$courseid\E(?:\/)*(\w+)*\_st$/); my $section=$1; if ($key eq $courseid.'_st') { $section=''; } my ($dummy,$end,$start)=split(/\_/,&unescape($value)); @@ -819,10 +814,14 @@ sub getsection { return '-1'; } + +my $disk_caching_disabled=1; + sub devalidate_cache { my ($cache,$id,$name) = @_; delete $$cache{$id.'.time'}; delete $$cache{$id}; + if ($disk_caching_disabled) { return; } my $filename=$perlvar{'lonDaemons'}.'/tmp/lonnet_internal_cache_'.$name.".db"; open(DB,"$filename.lock"); flock(DB,LOCK_EX); @@ -878,6 +877,7 @@ sub do_cache { sub save_cache_item { my ($cache,$name,$id)=@_; + if ($disk_caching_disabled) { return; } my $starttime=&Time::HiRes::time(); # &logthis("Saving :$name:$id"); my %hash; @@ -907,6 +907,7 @@ EVALBLOCK sub load_cache_item { my ($cache,$name,$id)=@_; + if ($disk_caching_disabled) { return; } my $starttime=&Time::HiRes::time(); # &logthis("Before Loading $name for $id size is ".scalar(%$cache)); my %hash; @@ -962,7 +963,7 @@ sub usection { &homeserver($unam,$udom)))) { my ($key,$value)=split(/\=/,$_); $key=&unescape($key); - if ($key=~/^$courseid(?:\/)*(\w+)*\_st$/) { + if ($key=~/^\Q$courseid\E(?:\/)*(\w+)*\_st$/) { my $section=$1; if ($key eq $courseid.'_st') { $section=''; } my ($dummy,$end,$start)=split(/\_/,&unescape($value)); @@ -1124,8 +1125,8 @@ sub ssi_body { my ($filelink,%form)=@_; my $output=($filelink=~/^http\:/?&externalssi($filelink): &ssi($filelink,%form)); - $output=~s/^.*\]*\>//si; - $output=~s/\<\/body\s*\>.*$//si; + $output=~s/^.*?\]*\>//si; + $output=~s/(.*)\<\/body\s*\>.*?$/$1/si; $output=~ s/\/\/ BEGIN LON\-CAPA Internal.+\/\/ END LON\-CAPA Internal\s//gs; return $output; @@ -1170,7 +1171,8 @@ sub tokenwrapper { $uri=~s/^\///; $ENV{'user.environment'}=~/\/([^\/]+)\.id/; my $token=$1; - if ($uri=~/^uploaded\/([^\/]+)\/([^\/]+)\/([^\/]+)(\?\.*)*$/) { +# if ($uri=~/^uploaded\/([^\/]+)\/([^\/]+)\/([^\/]+)(\?\.*)*$/) { + if ($uri=~m|^uploaded/([^/]+)/([^/]+)/(.+)(\?\.*)*$|) { &appenv('userfile.'.$1.'/'.$2.'/'.$3 => $ENV{'request.course.id'}); return 'http://'.$hostname{ &homeserver($2,$1)}.'/'.$uri. (($uri=~/\?/)?'&':'?').'token='.$token. @@ -1179,7 +1181,65 @@ sub tokenwrapper { return '/adm/notfound.html'; } } - + +# --------- File operations in /home/httpd/html/userfiles/$domain/1/2/3/$course +# input: action, courseID, current domain, home server for course, intended +# path to file, source of file. +# output: ok if successful, diagnostic message otherwise +# +# Allows directory structure to be used within lonUsers/../userfiles/ for a +# course. +# +# action = propagate - /home/httpd/html/userfiles/$domain/1/2/3/$course/$file +# will be copied to /home/httpd/lonUsers/1/2/3/$course/userfiles in +# course's home server. +# +# action = copy - /home/httpd/html/userfiles/$domain/1/2/3/$course/$file will +# be copied from $source (current location) to +# /home/httpd/html/userfiles/$domain/1/2/3/$course/$file +# and will then be copied to +# /home/httpd/lonUsers/$domain/1/2/3/$course/userfiles/$file in +# course's home server. + +sub process_coursefile { + my ($action,$docuname,$docudom,$docuhome,$file,$source)=@_; + my $fetchresult; + if ($action eq 'propagate') { + $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file + ,$docuhome); + } elsif ($action eq 'copy') { + my $fetchresult = ''; + my $fpath = ''; + my $fname = $file; + ($fpath,$fname) = ($file =~ m|^(.*)/([^/]+)$|); + $fpath=$docudom.'/'.$docuname.'/'.$fpath; + my $filepath=$perlvar{'lonDocRoot'}.'/userfiles'; + unless ($fpath eq '') { + my @parts=split('/',$fpath); + foreach my $part (@parts) { + $filepath.= '/'.$part; + if ((-e $filepath)!=1) { + mkdir($filepath,0777); + } + } + } + if ($source eq '') { + $fetchresult = 'no source file'; + } else { + my $destination = $filepath.'/'.$fname; + print STDERR "Getting ready to rename $source to $destination\n"; + rename($source,$destination); + $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file, + $docuhome); + } + } + unless ( ($fetchresult eq 'ok') || ($fetchresult eq 'no source file') ) { + &logthis('Failed to transfer '.$docudom.'/'.$docuname.'/'.$file. + ' to host '.$docuhome.': '.$fetchresult); + } + return $fetchresult; +} + # --------------- Take an uploaded file and put it into the userfiles directory # input: name of form element, coursedoc=1 means this is for the course # output: url of file in userspace @@ -1229,14 +1289,14 @@ sub finishuserfileupload { } # Save the file { - my $fh=Apache::File->new('>'.$filepath.'/'.$fname); + open(my $fh,'>'.$filepath.'/'.$fname); print $fh $ENV{'form.'.$formname}; + close($fh); } # Notify homeserver to grep it # - - my $fetchresult= - &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$fname,$docuhome); + my $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$fname, + $docuhome); if ($fetchresult eq 'ok') { # # Return the URL to it @@ -1304,12 +1364,35 @@ sub flushcourselogs { # File accesses # Writes to the dynamic metadata of resources to get hit counts, etc. # - foreach (keys %accesshash) { - my $entry=$_; - $entry=~/\_\_\_(\w+)\/(\w+)\/(.*)\_\_\_(\w+)$/; - my %temphash=($entry => $accesshash{$entry}); - if (&Apache::lonnet::put('nohist_resevaldata',\%temphash,$1,$2) eq 'ok') { - delete $accesshash{$entry}; + foreach my $entry (keys(%accesshash)) { + if ($entry =~ /___count$/) { + my ($dom,$name); + ($dom,$name,undef)=($entry=~m:___(\w+)/(\w+)/(.*)___count$:); + if (! defined($dom) || $dom eq '' || + ! defined($name) || $name eq '') { + my $cid = $ENV{'request.course.id'}; + $dom = $ENV{'request.'.$cid.'.domain'}; + $name = $ENV{'request.'.$cid.'.num'}; + } + my $value = $accesshash{$entry}; + my (undef,$url,undef) = ($entry =~ /^(.*)___(.*)___count$/); + my %temphash=($url => $value); + my $result = &inc('nohist_accesscount',\%temphash,$dom,$name); + if ($result eq 'ok') { + delete $accesshash{$entry}; + } elsif ($result eq 'unknown_cmd') { + # Target server has old code running on it. + my %temphash=($entry => $value); + if (&put('nohist_resevaldata',\%temphash,$dom,$name) eq 'ok') { + delete $accesshash{$entry}; + } + } + } else { + my ($dom,$name) = ($entry=~m:___(\w+)/(\w+)/(.*)___(\w+)$:); + my %temphash=($entry => $accesshash{$entry}); + if (&put('nohist_resevaldata',\%temphash,$dom,$name) eq 'ok') { + delete $accesshash{$entry}; + } } } # @@ -1368,14 +1451,11 @@ sub courseacclog { sub countacc { my $url=&declutter(shift); + return if (! defined($url) || $url eq ''); unless ($ENV{'request.course.id'}) { return ''; } $accesshash{$ENV{'request.course.id'}.'___'.$url.'___course'}=1; my $key=$$.$processmarker.'_'.$dumpcount.'___'.$url.'___count'; - if (defined($accesshash{$key})) { - $accesshash{$key}++; - } else { - $accesshash{$key}=1; - } + $accesshash{$key}++; } sub linklog { @@ -1390,7 +1470,7 @@ sub userrolelog { my ($trole,$username,$domain,$area,$tstart,$tend)=@_; if (($trole=~/^ca/) || ($trole=~/^in/) || ($trole=~/^cc/) || ($trole=~/^ep/) || - ($trole=~/^cr/)) { + ($trole=~/^cr/) || ($trole=~/^ta/)) { my (undef,$rudom,$runame,$rsec)=split(/\//,$area); $userrolehash {$trole.':'.$username.':'.$domain.':'.$runame.':'.$rudom.':'.$rsec} @@ -1402,6 +1482,10 @@ sub get_course_adv_roles { my $cid=shift; $cid=$ENV{'request.course.id'} unless (defined($cid)); my %coursehash=&coursedescription($cid); + my %nothide=(); + foreach (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) { + $nothide{join(':',split(/[\@\:]/,$_))}=1; + } my %returnhash=(); my %dumphash= &dump('nohist_userroles',$coursehash{'domain'},$coursehash{'num'}); @@ -1412,6 +1496,8 @@ sub get_course_adv_roles { if (($tend) && ($tend<$now)) { next; } if (($tstart) && ($now<$tstart)) { next; } my ($role,$username,$domain,$section)=split(/\:/,$_); + if ((&privileged($username,$domain)) && + (!$nothide{$username.':'.$domain})) { next; } my $key=&plaintext($role); if ($section) { $key.=' (Sec/Grp '.$section.')'; } if ($returnhash{$key}) { @@ -1454,10 +1540,11 @@ sub postannounce { } sub getannounce { - if (my $fh=Apache::File->new($perlvar{'lonDocRoot'}.'/announcement.txt')) { + + if (open(my $fh,$perlvar{'lonDocRoot'}.'/announcement.txt')) { my $announcement=''; while (<$fh>) { $announcement .=$_; } - $fh->close(); + close($fh); if ($announcement=~/\w/) { return ''. @@ -1970,6 +2057,10 @@ sub store { } } if (!$home) { $home=$ENV{'user.home'}; } + + $$storehash{'ip'}=$ENV{'REMOTE_ADDR'}; + $$storehash{'host'}=$perlvar{'lonHostID'}; + my $namevalue=''; foreach (keys %$storehash) { $namevalue.=escape($_).'='.escape($$storehash{$_}).'&'; @@ -2003,6 +2094,9 @@ sub cstore { } if (!$home) { $home=$ENV{'user.home'}; } + $$storehash{'ip'}=$ENV{'REMOTE_ADDR'}; + $$storehash{'host'}=$perlvar{'lonHostID'}; + my $namevalue=''; foreach (keys %$storehash) { $namevalue.=escape($_).'='.escape($$storehash{$_}).'&'; @@ -2085,6 +2179,36 @@ sub coursedescription { return %returnhash; } +# -------------------------------------------------See if a user is privileged + +sub privileged { + my ($username,$domain)=@_; + my $rolesdump=&reply("dump:$domain:$username:roles", + &homeserver($username,$domain)); + if (($rolesdump eq 'con_lost') || ($rolesdump eq '')) { return 0; } + my $now=time; + if ($rolesdump ne '') { + foreach (split(/&/,$rolesdump)) { + if ($_!~/^rolesdef\&/) { + my ($area,$role)=split(/=/,$_); + $area=~s/\_\w\w$//; + my ($trole,$tend,$tstart)=split(/_/,$role); + if (($trole eq 'dc') || ($trole eq 'su')) { + my $active=1; + if ($tend) { + if ($tend<$now) { $active=0; } + } + if ($tstart) { + if ($tstart>$now) { $active=0; } + } + if ($active) { return 1; } + } + } + } + } + return 0; +} + # -------------------------------------------------------- Get user privileges sub rolesinit { @@ -2337,6 +2461,30 @@ sub convert_dump_to_currentdump{ return \%returnhash; } +# --------------------------------------------------------------- inc interface + +sub inc { + my ($namespace,$store,$udomain,$uname) = @_; + if (!$udomain) { $udomain=$ENV{'user.domain'}; } + if (!$uname) { $uname=$ENV{'user.name'}; } + my $uhome=&homeserver($uname,$udomain); + my $items=''; + if (! ref($store)) { + # got a single value, so use that instead + $items = &escape($store).'=&'; + } elsif (ref($store) eq 'SCALAR') { + $items = &escape($$store).'=&'; + } elsif (ref($store) eq 'ARRAY') { + $items = join('=&',map {&escape($_);} @{$store}); + } elsif (ref($store) eq 'HASH') { + while (my($key,$value) = each(%{$store})) { + $items.= &escape($key).'='.&escape($value).'&'; + } + } + $items=~s/\&$//; + return &reply("inc:$udomain:$uname:$namespace:$items",$uhome); +} + # --------------------------------------------------------------- put interface sub put { @@ -2481,14 +2629,14 @@ sub allowed { # Course - if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'}=~/$priv\&([^\:]*)/) { + if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'}=~/\Q$priv\E\&([^\:]*)/) { $thisallowed.=$1; } # Domain if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.(split(/\//,$uri))[0].'/'} - =~/$priv\&([^\:]*)/) { + =~/\Q$priv\E\&([^\:]*)/) { $thisallowed.=$1; } @@ -2498,7 +2646,7 @@ sub allowed { $courseuri=~s/^([^\/])/\/$1/; if ($ENV{'user.priv.'.$ENV{'request.role'}.'.'.$courseuri} - =~/$priv\&([^\:]*)/) { + =~/\Q$priv\E\&([^\:]*)/) { $thisallowed.=$1; } @@ -2516,7 +2664,7 @@ sub allowed { # If this is generating or modifying users, exit with special codes - if (':csu:cdc:ccc:cin:cta:cep:ccr:cst:cad:cli:cau:cdg:cca:'=~/\:$priv\:/) { + if (':csu:cdc:ccc:cin:cta:cep:ccr:cst:cad:cli:cau:cdg:cca:'=~/\:\Q$priv\E\:/) { return $thisallowed; } # @@ -2537,7 +2685,7 @@ sub allowed { if ($match) { $statecond=$cond; if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.$courseprivid} - =~/$priv\&([^\:]*)/) { + =~/\Q$priv\E\&([^\:]*)/) { $thisallowed.=$1; $checkreferer=0; } @@ -2565,7 +2713,7 @@ sub allowed { if ($match) { my $refstatecond=$cond; if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.$courseprivid} - =~/$priv\&([^\:]*)/) { + =~/\Q$priv\E\&([^\:]*)/) { $thisallowed.=$1; $uri=$refuri; $statecond=$refstatecond; @@ -2618,7 +2766,7 @@ sub allowed { if ((time-$ENV{$prefix.'last_cache'})>$expiretime) { &coursedescription($courseid); } - if (($ENV{$prefix.'res.'.$uri.'.lock.sections'}=~/\,$csec\,/) + if (($ENV{$prefix.'res.'.$uri.'.lock.sections'}=~/\,\Q$csec\E\,/) || ($ENV{$prefix.'res.'.$uri.'.lock.sections'} eq 'all')) { if ($ENV{$prefix.'res.'.$uri.'.lock.expire'}>time) { &log($ENV{'user.domain'},$ENV{'user.name'}, @@ -2629,7 +2777,7 @@ sub allowed { return ''; } } - if (($ENV{$prefix.'priv.'.$priv.'.lock.sections'}=~/\,$csec\,/) + if (($ENV{$prefix.'priv.'.$priv.'.lock.sections'}=~/\,\Q$csec\E\,/) || ($ENV{$prefix.'priv.'.$priv.'.lock.sections'} eq 'all')) { if ($ENV{'priv.'.$priv.'.lock.expire'}>time) { &log($ENV{'user.domain'},$ENV{'user.name'}, @@ -2663,7 +2811,7 @@ sub allowed { my $rolecode=(split(/\./,$ENV{'request.role'}))[0]; my $unamedom=$ENV{'user.name'}.':'.$ENV{'user.domain'}; if ($ENV{'course.'.$ENV{'request.course.id'}.'.'.$priv.'.roles.denied'} - =~/$rolecode/) { + =~/\Q$rolecode\E/) { &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.host'}, 'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode.' in '. $ENV{'request.course.id'}); @@ -2671,7 +2819,7 @@ sub allowed { } if ($ENV{'course.'.$ENV{'request.course.id'}.'.'.$priv.'.users.denied'} - =~/$unamedom/) { + =~/\Q$unamedom\E/) { &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.host'}, 'Denied by user: '.$priv.' for '.$uri.' as '.$unamedom.' in '. $ENV{'request.course.id'}); @@ -2683,7 +2831,7 @@ sub allowed { if ($thisallowed=~/R/) { my $rolecode=(split(/\./,$ENV{'request.role'}))[0]; - if (&metadata($uri,'roledeny')=~/$rolecode/) { + if (&metadata($uri,'roledeny')=~/\Q$rolecode\E/) { &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.host'}, 'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode); return ''; @@ -2695,7 +2843,7 @@ sub allowed { if ($thisallowed=~/X/) { if ($ENV{'acc.randomout'}) { my $symb=&symbread($uri,1); - if (($symb) && ($ENV{'acc.randomout'}=~/\&$symb\&/)) { + if (($symb) && ($ENV{'acc.randomout'}=~/\&\Q$symb\E\&/)) { return ''; } } @@ -2759,27 +2907,27 @@ sub definerole { my ($rolename,$sysrole,$domrole,$courole)=@_; foreach (split(':',$sysrole)) { my ($crole,$cqual)=split(/\&/,$_); - if ($pr{'cr:s'}!~/$crole/) { return "refused:s:$crole"; } - if ($pr{'cr:s'}=~/$crole\&/) { - if ($pr{'cr:s'}!~/$crole\&\w*$cqual/) { + if ($pr{'cr:s'}!~/\Q$crole\E/) { return "refused:s:$crole"; } + if ($pr{'cr:s'}=~/\Q$crole\E\&/) { + if ($pr{'cr:s'}!~/\Q$crole\E\&\w*\Q$cqual\E/) { return "refused:s:$crole&$cqual"; } } } foreach (split(':',$domrole)) { my ($crole,$cqual)=split(/\&/,$_); - if ($pr{'cr:d'}!~/$crole/) { return "refused:d:$crole"; } - if ($pr{'cr:d'}=~/$crole\&/) { - if ($pr{'cr:d'}!~/$crole\&\w*$cqual/) { + if ($pr{'cr:d'}!~/\Q$crole\E/) { return "refused:d:$crole"; } + if ($pr{'cr:d'}=~/\Q$crole\E\&/) { + if ($pr{'cr:d'}!~/\Q$crole\W\&\w*\Q$cqual\E/) { return "refused:d:$crole&$cqual"; } } } foreach (split(':',$courole)) { my ($crole,$cqual)=split(/\&/,$_); - if ($pr{'cr:c'}!~/$crole/) { return "refused:c:$crole"; } - if ($pr{'cr:c'}=~/$crole\&/) { - if ($pr{'cr:c'}!~/$crole\&\w*$cqual/) { + if ($pr{'cr:c'}!~/\Q$crole\E/) { return "refused:c:$crole"; } + if ($pr{'cr:c'}=~/\Q$crole\E\&/) { + if ($pr{'cr:c'}!~/\Q$crole\E\&\w*\Q$cqual\E/) { return "refused:c:$crole&$cqual"; } } @@ -2826,7 +2974,7 @@ sub log_query { my $command=&escape(join(':',map{$_.'='.$filters{$_}} keys %filters)); my $queryid=&reply("querysend:".$query.':'.$udom.':'.$uname.':'.$command, $uhome); - unless ($queryid=~/^$uhost\_/) { return 'error: '.$queryid; } + unless ($queryid=~/^\Q$uhost\E\_/) { return 'error: '.$queryid; } return get_query_reply($queryid); } @@ -2837,9 +2985,9 @@ sub get_query_reply { for (1..100) { sleep 2; if (-e $replyfile.'.end') { - if (my $fh=Apache::File->new($replyfile)) { + if (open(my $fh,$replyfile)) { $reply.=<$fh>; - $fh->close; + close($fh); } else { return 'error: reply_file_error'; } return &unescape($reply); } @@ -3064,10 +3212,11 @@ sub modifyuser { sub modifystudent { my ($udom,$uname,$uid,$umode,$upass,$first,$middle,$last,$gene,$usec, - $end,$start,$forceid,$desiredhome,$email)=@_; - my $cid=''; - unless ($cid=$ENV{'request.course.id'}) { - return 'not_in_class'; + $end,$start,$forceid,$desiredhome,$email,$type,$cid)=@_; + if (!$cid) { + unless ($cid=$ENV{'request.course.id'}) { + return 'not_in_class'; + } } # --------------------------------------------------------------- Make the user my $reply=&modifyuser @@ -3077,24 +3226,34 @@ sub modifystudent { # This will cause &modify_student_enrollment to get the uid from the # students environment $uid = undef if (!$forceid); - $reply = &modify_student_enrollment($udom,$uname,$uid,$first,$middle, - $last,$gene,$usec,$end,$start); + $reply = &modify_student_enrollment($udom,$uname,$uid,$first,$middle,$last, + $gene,$usec,$end,$start,$type,$cid); return $reply; } sub modify_student_enrollment { - my ($udom,$uname,$uid,$first,$middle,$last,$gene,$usec,$end,$start) = @_; - # Get the course id from the environment - my $cid=''; - unless ($cid=$ENV{'request.course.id'}) { - return 'not_in_class'; + my ($udom,$uname,$uid,$first,$middle,$last,$gene,$usec,$end,$start,$type, + $cid) = @_; + my ($cdom,$cnum,$chome); + if (!$cid) { + unless ($cid=$ENV{'request.course.id'}) { + return 'not_in_class'; + } + $cdom=$ENV{'course.'.$cid.'.domain'}; + $cnum=$ENV{'course.'.$cid.'.num'}; + } else { + ($cdom,$cnum)=split(/_/,$cid); } + $chome=$ENV{'course.'.$cid.'.home'}; + if (!$chome) { + $chome=&homeserver($cnum,$cdom); + } + if (!$chome) { return 'unknown_course'; } # Make sure the user exists my $uhome=&homeserver($uname,$udom); if (($uhome eq '') || ($uhome eq 'no_host')) { return 'error: no such user'; } - # # Get student data if we were not given enough information if (!defined($first) || $first eq '' || !defined($last) || $last eq '' || @@ -3107,9 +3266,9 @@ sub modify_student_enrollment { ['firstname','middlename','lastname', 'generation','id'] ,$udom,$uname); - foreach (keys(%tmp)) { - &logthis("key $_ = ".$tmp{$_}); - } + #foreach (keys(%tmp)) { + # &logthis("key $_ = ".$tmp{$_}); + #} $first = $tmp{'firstname'} if (!defined($first) || $first eq ''); $middle = $tmp{'middlename'} if (!defined($middle) || $middle eq ''); $last = $tmp{'lastname'} if (!defined($last) || $last eq ''); @@ -3118,11 +3277,9 @@ sub modify_student_enrollment { } my $fullname = &Apache::loncoursedata::ProcessFullName($last,$gene, $first,$middle); - my $reply=critical('put:'.$ENV{'course.'.$cid.'.domain'}.':'. - $ENV{'course.'.$cid.'.num'}.':classlist:'. - &escape($uname.':'.$udom).'='. - &escape(join(':',$end,$start,$uid,$usec,$fullname)), - $ENV{'course.'.$cid.'.home'}); + my $value=&escape($uname.':'.$udom).'='. + &escape(join(':',$end,$start,$uid,$usec,$fullname,$type)); + my $reply=critical('put:'.$cdom.':'.$cnum.':classlist:'.$value,$chome); unless (($reply eq 'ok') || ($reply eq 'delayed')) { return 'error: '.$reply; } @@ -3614,10 +3771,8 @@ sub EXT { my $hashid="$udom:$uname"; my ($result,$cached)=&is_cached(\%userresdatacache,$hashid, 'userres'); - if (!defined($cached)) { - my %resourcedata=&get('resourcedata', - [$courselevelr,$courselevelm, - $courselevel],$udom,$uname); + if (!defined($cached)) { + my %resourcedata=&dump('resourcedata',$udom,$uname); $result=\%resourcedata; &do_cache(\%userresdatacache,$hashid,$result,'userres'); } @@ -3630,12 +3785,13 @@ sub EXT { if ($$result{$courselevel}) { return $$result{$courselevel}; } } else { - if ($tmp!~/No such file/) { + #error 2 occurs when the .db doesn't exist + if ($tmp!~/error: 2 /) { &logthis("WARNING:". " Trying to get resource data for ". $uname." at ".$udom.": ". $tmp.""); - } elsif ($tmp=~/error:No such file/) { + } elsif ($tmp=~/error: 2 /) { &EXT_cache_set($udom,$uname); } elsif ($tmp =~ /^(con_lost|no_such_host)/) { return $tmp; @@ -3717,9 +3873,12 @@ sub packages_tab_default { my $packages=&metadata($uri,'packages'); foreach my $package (split(/,/,$packages)) { my ($pack_type,$pack_part)=split(/_/,$package,2); - if ($pack_part eq $part) { + if (defined($packagetab{"$pack_type&$name&default"})) { return $packagetab{"$pack_type&$name&default"}; } + if (defined($packagetab{$pack_type."_".$pack_part."&$name&default"})) { + return $packagetab{$pack_type."_".$pack_part."&$name&default"}; + } } return undef; } @@ -3748,8 +3907,8 @@ sub metadata { # if it is a non metadata possible uri return quickly if (($uri eq '') || (($uri =~ m|^/*adm/|) && ($uri !~ m|^adm/includes|)) || ($uri =~ m|/$|) || ($uri =~ m|/.meta$|) || ($uri =~ /^~/) || - ($uri =~ m|home/[^/]+/public_html/|)) { - return ''; + ($uri =~ m|home/[^/]+/public_html/|) || ($uri =~ m|^uploaded/|)) { + return undef; } my $filename=$uri; $uri=~s/\.meta$//; @@ -3766,7 +3925,9 @@ sub metadata { # # Is this a recursive call for a library? # - my %lcmetacache; + if (! exists($metacache{$uri})) { + $metacache{$uri}={}; + } if ($liburi) { $liburi=&declutter($liburi); $filename=$liburi; @@ -3790,10 +3951,10 @@ sub metadata { if (defined($token->[2]->{'id'})) { $keyroot.='_'.$token->[2]->{'id'}; } - if ($lcmetacache{':packages'}) { - $lcmetacache{':packages'}.=','.$package.$keyroot; + if ($metacache{$uri}->{':packages'}) { + $metacache{$uri}->{':packages'}.=','.$package.$keyroot; } else { - $lcmetacache{':packages'}=$package.$keyroot; + $metacache{$uri}->{':packages'}=$package.$keyroot; } foreach (keys %packagetab) { my $part=$keyroot; @@ -3815,14 +3976,14 @@ sub metadata { if ($subp eq 'display') { $value.=' [Part: '.$part.']'; } - $lcmetacache{':'.$unikey.'.part'}=$part; + $metacache{$uri}->{':'.$unikey.'.part'}=$part; $metathesekeys{$unikey}=1; - unless (defined($lcmetacache{':'.$unikey.'.'.$subp})) { - $lcmetacache{':'.$unikey.'.'.$subp}=$value; + unless (defined($metacache{$uri}->{':'.$unikey.'.'.$subp})) { + $metacache{$uri}->{':'.$unikey.'.'.$subp}=$value; } - if (defined($lcmetacache{':'.$unikey.'.default'})) { - $lcmetacache{':'.$unikey}= - $lcmetacache{':'.$unikey.'.default'}; + if (defined($metacache{$uri}->{':'.$unikey.'.default'})) { + $metacache{$uri}->{':'.$unikey}= + $metacache{$uri}->{':'.$unikey.'.default'}; } } } @@ -3855,6 +4016,7 @@ sub metadata { foreach (sort(split(/\,/,&metadata($uri,'keys', $location,$unikey, $depthcount+1)))) { + $metacache{$uri}->{':'.$_}=$metacache{$uri}->{':'.$_}; $metathesekeys{$_}=1; } } @@ -3865,18 +4027,18 @@ sub metadata { } $metathesekeys{$unikey}=1; foreach (@{$token->[3]}) { - $lcmetacache{':'.$unikey.'.'.$_}=$token->[2]->{$_}; + $metacache{$uri}->{':'.$unikey.'.'.$_}=$token->[2]->{$_}; } my $internaltext=&HTML::Entities::decode($parser->get_text('/'.$entry)); - my $default=$lcmetacache{':'.$unikey.'.default'}; + my $default=$metacache{$uri}->{':'.$unikey.'.default'}; if ( $internaltext =~ /^\s*$/ && $default !~ /^\s*$/) { # only ws inside the tag, and not in default, so use default # as value - $lcmetacache{':'.$unikey}=$default; + $metacache{$uri}->{':'.$unikey}=$default; } else { # either something interesting inside the tag or default # uninteresting - $lcmetacache{':'.$unikey}=$internaltext; + $metacache{$uri}->{':'.$unikey}=$internaltext; } # end of not-a-package not-a-library import } @@ -3886,27 +4048,28 @@ sub metadata { } } # are there custom rights to evaluate - if ($lcmetacache{':copyright'} eq 'custom') { + if ($metacache{$uri}->{':copyright'} eq 'custom') { # # Importing a rights file here # unless ($depthcount) { - my $location=$lcmetacache{':customdistributionfile'}; + my $location=$metacache{$uri}->{':customdistributionfile'}; my $dir=$filename; $dir=~s|[^/]*$||; $location=&filelocation($dir,$location); foreach (sort(split(/\,/,&metadata($uri,'keys', $location,'_rights', $depthcount+1)))) { + $metacache{$uri}->{':'.$_}=$metacache{$uri}->{':'.$_}; $metathesekeys{$_}=1; } } } - $lcmetacache{':keys'}=join(',',keys %metathesekeys); - &metadata_generate_part0(\%metathesekeys,\%lcmetacache,$uri); - $lcmetacache{':allpossiblekeys'}=join(',',keys %metathesekeys); - &do_cache(\%metacache,$uri,\%lcmetacache,'meta'); + $metacache{$uri}->{':keys'}=join(',',keys %metathesekeys); + &metadata_generate_part0(\%metathesekeys,$metacache{$uri},$uri); + $metacache{$uri}->{':allpossiblekeys'}=join(',',keys %metathesekeys); + &do_cache(\%metacache,$uri,$metacache{$uri},'meta'); # this is the end of "was not already recently cached } return $metacache{$uri}->{':'.$what}; @@ -3935,7 +4098,7 @@ sub metadata_generate_part0 { my $olddis=$$metacache{':parameter_'.$allnames{$name}.'_'.$name. '.display'}; my $expr='\\[Part: '.$allnames{$name}.'\\]'; - $olddis=~s/$expr/\[Part: 0\]/; + $olddis=~s/\Q$expr\E/\[Part: 0\]/; $$metacache{"$key.display"}=$olddis; } } @@ -4293,48 +4456,105 @@ sub setup_random_from_rndseed { } } +sub latest_receipt_algorithm_id { + return 'receipt2'; +} + +sub recunique { + my $fucourseid=shift; + my $unique; + if ($ENV{"course.$fucourseid.receiptalg"} eq 'receipt2') { + $unique=$ENV{"course.$fucourseid.internal.encseed"}; + } else { + $unique=$perlvar{'lonReceipt'}; + } + return unpack("%32C*",$unique); +} + +sub recprefix { + my $fucourseid=shift; + my $prefix; + if ($ENV{"course.$fucourseid.receiptalg"} eq 'receipt2') { + $prefix=$ENV{"course.$fucourseid.internal.encpref"}; + } else { + $prefix=$perlvar{'lonHostID'}; + } + return unpack("%32C*",$prefix); +} + sub ireceipt { - my ($funame,$fudom,$fucourseid,$fusymb)=@_; + my ($funame,$fudom,$fucourseid,$fusymb,$part)=@_; my $cuname=unpack("%32C*",$funame); my $cudom=unpack("%32C*",$fudom); my $cucourseid=unpack("%32C*",$fucourseid); my $cusymb=unpack("%32C*",$fusymb); - my $cunique=unpack("%32C*",$perlvar{'lonReceipt'}); - return unpack("%32C*",$perlvar{'lonHostID'}).'-'. - ($cunique%$cuname+ - $cunique%$cudom+ - $cusymb%$cuname+ - $cusymb%$cudom+ - $cucourseid%$cuname+ - $cucourseid%$cudom); + my $cunique=&recunique($fucourseid); + my $cpart=unpack("%32S*",$part); + my $return =&recprefix($fucourseid).'-'; + if ($ENV{"course.$fucourseid.receiptalg"} eq 'receipt2' || + $ENV{'request.state'} eq 'construct') { + &Apache::lonxml::debug("doing receipt2 using parts $cpart, uname $cuname and udom $cudom gets ".($cpart%$cuname). + " and ".($cpart%$cudom)); + + $return.= ($cunique%$cuname+ + $cunique%$cudom+ + $cusymb%$cuname+ + $cusymb%$cudom+ + $cucourseid%$cuname+ + $cucourseid%$cudom+ + $cpart%$cuname+ + $cpart%$cudom); + } else { + $return.= ($cunique%$cuname+ + $cunique%$cudom+ + $cusymb%$cuname+ + $cusymb%$cudom+ + $cucourseid%$cuname+ + $cucourseid%$cudom); + } + return $return; } sub receipt { - my ($symb,$courseid,$domain,$name) = &Apache::lonxml::whichuser(); - return &ireceipt($name,$domain,$courseid,$symb); + my ($part)=@_; + my ($symb,$courseid,$domain,$name) = &Apache::lonxml::whichuser(); + return &ireceipt($name,$domain,$courseid,$symb,$part); } # ------------------------------------------------------------ Serves up a file -# returns either the contents of the file or a -1 +# returns either the contents of the file or +# -1 if the file doesn't exist +# -2 if an error occured when trying to aqcuire the file + sub getfile { - my $file=shift; - if ($file=~/^\/*uploaded\//) { # user file - my $ua=new LWP::UserAgent; - my $request=new HTTP::Request('GET',&tokenwrapper($file)); - my $response=$ua->request($request); - if ($response->is_success()) { - return $response->content; - } else { - return -1; - } - } else { # normal file from res space - &repcopy($file); - if (! -e $file ) { return -1; }; - my $fh=Apache::File->new($file); - my $a=''; - while (<$fh>) { $a .=$_; } - return $a; - } + my $file=shift; + if ($file=~/^\/*uploaded\//) { # user file + my $ua=new LWP::UserAgent; + my $request=new HTTP::Request('GET',&tokenwrapper($file)); + my $response=$ua->request($request); + if ($response->is_success()) { + return $response->content; + } else { + #&logthis("Return Code is ".$response->code." for $file ". + # &tokenwrapper($file)); + # 500 for ISE when tokenwrapper can't figure out what server to + # contact + # 503 when lonuploadacc can't contact the requested server + if ($response->code eq 503 || $response->code eq 500) { + return -2; + } else { + return -1; + } + } + } else { # normal file from res space + &repcopy($file); + if (! -e $file ) { return -1; }; + my $fh; + open($fh,"<$file"); + my $a=''; + while (<$fh>) { $a .=$_; } + return $a; + } } sub filelocation { @@ -4347,8 +4567,8 @@ sub filelocation { } elsif ($file=~/^\/*uploaded/) { # is an uploaded file $location=$file; } else { - $file=~s/^$perlvar{'lonDocRoot'}//; - $file=~s:^/*res::; + $file=~s/^\Q$perlvar{'lonDocRoot'}\E//; + $file=~s:^/res/:/:; if ( !( $file =~ m:^/:) ) { $location = $dir. '/'.$file; } else { @@ -4357,26 +4577,54 @@ sub filelocation { } $location=~s://+:/:g; # remove duplicate / while ($location=~m:/\.\./:) {$location=~ s:/[^/]+/\.\./:/:g;} #remove dir/.. + while ($location=~m:/\./:) {$location=~ s:/\./:/:g;} #remove /./ return $location; } sub hreflocation { my ($dir,$file)=@_; - unless (($file=~/^http:\/\//i) || ($file=~/^\//)) { - my $finalpath=filelocation($dir,$file); - $finalpath=~s/^\/home\/httpd\/html//; - $finalpath=~s-/home/(\w+)/public_html/-/~$1/-; - return $finalpath; - } else { - return $file; + unless (($file=~m-^http://-i) || ($file=~m-^/-)) { + my $finalpath=filelocation($dir,$file); + $finalpath=~s-^/home/httpd/html--; + $finalpath=~s-^/home/(\w+)/public_html/-/~$1/-; + return $finalpath; + } elsif ($file=~m-^/home-) { + $file=~s-^/home/httpd/html--; + $file=~s-^/home/(\w+)/public_html/-/~$1/-; + return $file; + } + return $file; +} + +sub current_machine_domains { + my $hostname=$hostname{$perlvar{'lonHostID'}}; + my @domains; + while( my($id, $name) = each(%hostname)) { +# &logthis("-$id-$name-$hostname-"); + if ($hostname eq $name) { + push(@domains,$hostdom{$id}); + } + } + return @domains; +} + +sub current_machine_ids { + my $hostname=$hostname{$perlvar{'lonHostID'}}; + my @ids; + while( my($id, $name) = each(%hostname)) { +# &logthis("-$id-$name-$hostname-"); + if ($hostname eq $name) { + push(@ids,$id); + } } + return @ids; } # ------------------------------------------------------------- Declutters URLs sub declutter { my $thisfn=shift; - $thisfn=~s/^$perlvar{'lonDocRoot'}//; + $thisfn=~s/^\Q$perlvar{'lonDocRoot'}\E//; $thisfn=~s/^\///; $thisfn=~s/^res\///; $thisfn=~s/\?.+$//; @@ -4446,7 +4694,7 @@ BEGIN { # ----------------------------------- Read loncapa.conf and loncapa_apache.conf unless ($readit) { { - my $config=Apache::File->new("/etc/httpd/conf/loncapa.conf"); + open(my $config,") { if ($configline =~ /^[^\#]*PerlSetVar/) { @@ -4455,9 +4703,10 @@ BEGIN { $perlvar{$varname}=$varvalue; } } + close($config); } { - my $config=Apache::File->new("/etc/httpd/conf/loncapa_apache.conf"); + open(my $config,") { if ($configline =~ /^[^\#]*PerlSetVar/) { @@ -4466,16 +4715,16 @@ BEGIN { $perlvar{$varname}=$varvalue; } } + close($config); } # ------------------------------------------------------------ Read domain file { - my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}. - '/domain.tab'); %domaindescription = (); %domain_auth_def = (); %domain_auth_arg_def = (); - if ($fh) { + my $fh; + if (open($fh,"<".$Apache::lonnet::perlvar{'lonTabDir'}.'/domain.tab')) { while (<$fh>) { next if (/^(\#|\s*$)/); # next if /^\#/; @@ -4490,16 +4739,17 @@ BEGIN { $domain_longi{$domain}=$longi; $domain_lati{$domain}=$lati; -# &logthis("Domain.tab: $domain, $domain_auth_def{$domain}, $domain_auth_arg_def{$domain},$domaindescription{$domain}"); + # &logthis("Domain.tab: $domain, $domain_auth_def{$domain}, $domain_auth_arg_def{$domain},$domaindescription{$domain}"); # &logthis("Domain.tab: $domain ".$domaindescription{$domain} ); - } + } } + close ($fh); } # ------------------------------------------------------------- Read hosts file { - my $config=Apache::File->new("$perlvar{'lonTabDir'}/hosts.tab"); + open(my $config,"<$perlvar{'lonTabDir'}/hosts.tab"); while (my $configline=<$config>) { next if ($configline =~ /^(\#|\s*$)/); @@ -4517,11 +4767,12 @@ BEGIN { } } } + close($config); } # ------------------------------------------------------ Read spare server file { - my $config=Apache::File->new("$perlvar{'lonTabDir'}/spare.tab"); + open(my $config,"<$perlvar{'lonTabDir'}/spare.tab"); while (my $configline=<$config>) { chomp($configline); @@ -4529,46 +4780,50 @@ BEGIN { $spareid{$configline}=1; } } + close($config); } # ------------------------------------------------------------ Read permissions { - my $config=Apache::File->new("$perlvar{'lonTabDir'}/roles.tab"); + open(my $config,"<$perlvar{'lonTabDir'}/roles.tab"); while (my $configline=<$config>) { - chomp($configline); - if ($configline) { - my ($role,$perm)=split(/ /,$configline); - if ($perm ne '') { $pr{$role}=$perm; } - } + chomp($configline); + if ($configline) { + my ($role,$perm)=split(/ /,$configline); + if ($perm ne '') { $pr{$role}=$perm; } + } } + close($config); } # -------------------------------------------- Read plain texts for permissions { - my $config=Apache::File->new("$perlvar{'lonTabDir'}/rolesplain.tab"); + open(my $config,"<$perlvar{'lonTabDir'}/rolesplain.tab"); while (my $configline=<$config>) { - chomp($configline); - if ($configline) { - my ($short,$plain)=split(/:/,$configline); - if ($plain ne '') { $prp{$short}=$plain; } - } + chomp($configline); + if ($configline) { + my ($short,$plain)=split(/:/,$configline); + if ($plain ne '') { $prp{$short}=$plain; } + } } + close($config); } # ---------------------------------------------------------- Read package table { - my $config=Apache::File->new("$perlvar{'lonTabDir'}/packages.tab"); + open(my $config,"<$perlvar{'lonTabDir'}/packages.tab"); while (my $configline=<$config>) { - chomp($configline); - my ($short,$plain)=split(/:/,$configline); - my ($pack,$name)=split(/\&/,$short); - if ($plain ne '') { - $packagetab{$pack.'&'.$name.'&name'}=$name; - $packagetab{$short}=$plain; - } + chomp($configline); + my ($short,$plain)=split(/:/,$configline); + my ($pack,$name)=split(/\&/,$short); + if ($plain ne '') { + $packagetab{$pack.'&'.$name.'&name'}=$name; + $packagetab{$short}=$plain; + } } + close($config); } # ------------- set up temporary directory @@ -5187,6 +5442,14 @@ dumps the complete (or key matching rege =item * +inc($namespace,$store,$udom,$uname) : increments $store in $namespace. +$store can be a scalar, an array reference, or if the amount to be +incremented is > 1, a hash reference. + +($udom and $uname are optional) + +=item * + put($namespace,$storehash,$udom,$uname) : stores hash in namesp ($udom and $uname are optional)