--- loncom/lonnet/perl/lonnet.pm 2004/03/31 19:25:08 1.481 +++ loncom/lonnet/perl/lonnet.pm 2004/04/29 17:25:11 1.492 @@ -1,7 +1,7 @@ # The LearningOnline Network # TCP networking package # -# $Id: lonnet.pm,v 1.481 2004/03/31 19:25:08 raeburn Exp $ +# $Id: lonnet.pm,v 1.492 2004/04/29 17:25:11 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -32,7 +32,8 @@ package Apache::lonnet; use strict; use LWP::UserAgent(); use HTTP::Headers; -use Date::Parse; +use HTTP::Date; +# use Date::Parse; use vars qw(%perlvar %hostname %homecache %badServerCache %hostip %iphost %spareid %hostdom %libserv %pr %prp %metacache %packagetab %titlecache %courseresversioncache %resversioncache @@ -616,6 +617,7 @@ sub idput { my ($udom,%ids)=@_; my %servers=(); foreach (keys %ids) { + &cput('environment',{'id'=>$ids{$_}},$udom,$_); my $uhom=&homeserver($_,$udom); if ($uhom ne 'no_host') { my $id=&escape($ids{$_}); @@ -626,7 +628,6 @@ sub idput { } else { $servers{$uhom}=$id.'='.$unam; } - &critical('put:'.$udom.':'.$unam.':environment:id='.$id,$uhom); } } foreach (keys %servers) { @@ -1164,29 +1165,28 @@ sub externalssi { return $response->content; } -# ------- Add a token to a remote URI's query string to vouch for access rights +# -------------------------------- Allow a /uploaded/ URI to be vouched for + +sub allowuploaded { + my ($srcurl,$url)=@_; + $url=&clutter(&declutter($url)); + my $dir=$url; + $dir=~s/\/[^\/]+$//; + my %httpref=(); + my $httpurl=&hreflocation('',$url); + $httpref{'httpref.'.$httpurl}=$srcurl; + &Apache::lonnet::appenv(%httpref); +} sub tokenwrapper { - my $uri=shift; - $uri=~s/^http\:\/\/([^\/]+)//; - $uri=~s/^\///; - $ENV{'user.environment'}=~/\/([^\/]+)\.id/; - my $token=$1; -# 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. - '&tokenissued='.$perlvar{'lonHostID'}; - } else { - return '/adm/notfound.html'; - } + &FIXME_blow_up; } # --------- 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 +# output: url to file (if action was uploaddoc), +# ok if successful, or diagnostic message otherwise (if action was propagate or copy) # # Allows directory structure to be used within lonUsers/../userfiles/ for a # course. @@ -1201,8 +1201,9 @@ sub tokenwrapper { # and will then be copied to # /home/httpd/lonUsers/$domain/1/2/3/$course/userfiles/$file in # course's home server. +# # action = uploaddoc - /home/httpd/html/userfiles/$domain/1/2/3/$course/$file -# will be retrived from $ENV{form.$source} via DOCS interface to +# will be retrived from $ENV{form.uploaddoc} (from DOCS interface) to # /home/httpd/html/userfiles/$domain/1/2/3/$course/$file # and will then be copied to /home/httpd/lonUsers/1/2/3/$course/userfiles/$file # in course's home server. @@ -1255,7 +1256,7 @@ sub process_coursefile { } } } - unless ( ($fetchresult eq 'ok') || ($fetchresult eq 'no source file') ) { + unless ( $fetchresult eq 'ok') { &logthis('Failed to transfer '.$docudom.'/'.$docuname.'/'.$file. ' to host '.$docuhome.': '.$fetchresult); } @@ -1280,7 +1281,6 @@ sub userfileupload { # See if there is anything left unless ($fname) { return 'error: no uploaded file'; } chop($ENV{'form.'.$formname}); - my $url = ''; # Create the directory if not present my $docuname=''; my $docudom=''; @@ -1290,18 +1290,17 @@ sub userfileupload { $docudom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; $docuhome=$ENV{'course.'.$ENV{'request.course.id'}.'.home'}; if ($ENV{'form.folder'} =~ m/^default/) { - $url = &finishuserfileupload($docuname,$docudom,$docuhome,$formname,$fname); + return &finishuserfileupload($docuname,$docudom,$docuhome,$formname,$fname); } else { $fname=$ENV{'form.folder'}.'/'.$fname; - $url = &process_coursefile('uploaddoc',$docuname,$docudom,$docuhome,$fname,$formname); + return &process_coursefile('uploaddoc',$docuname,$docudom,$docuhome,$fname,$formname); } } else { $docuname=$ENV{'user.name'}; $docudom=$ENV{'user.domain'}; $docuhome=$ENV{'user.home'}; + return &finishuserfileupload($docuname,$docudom,$docuhome,$formname,$fname); } - return - &finishuserfileupload($docuname,$docudom,$docuhome,$formname,$fname); } sub finishuserfileupload { @@ -1337,6 +1336,12 @@ sub finishuserfileupload { } } +sub removeuserfile { + my ($docuname,$docudom,$fname)=@_; + my $home=&homeserver($docuname,$docudom); + return &reply("removeuserfile:$docudom/$docuname/$fname",$home); +} + # ------------------------------------------------------------------------- Log sub log { @@ -2681,10 +2686,15 @@ sub allowed { # URI is an uploaded document for this course - if (($priv eq 'bre') && - ($uri=~/^uploaded\/$ENV{'course.'.$ENV{'request.course.id'}.'.domain'}\/$ENV{'course.'.$ENV{'request.course.id'}.'.num'}/)) { - return 'F'; + if (($priv eq 'bre') && ($uri=~m|^uploaded/|)) { + my $refuri=$ENV{'httpref.'.$orguri}; + if ($refuri) { + if ($refuri =~ m|^/adm/|) { + $thisallowed='F'; + } + } } + # Full access at system, domain or course-wide level? Exit. if ($thisallowed=~/F/) { @@ -3306,9 +3316,10 @@ sub modify_student_enrollment { } my $fullname = &Apache::loncoursedata::ProcessFullName($last,$gene, $first,$middle); - my $value=&escape($uname.':'.$udom).'='. - &escape(join(':',$end,$start,$uid,$usec,$fullname,$type)); - my $reply=critical('put:'.$cdom.':'.$cnum.':classlist:'.$value,$chome); + my $reply=cput('classlist', + {"$uname:$udom" => + join(':',$end,$start,$uid,$usec,$fullname,$type) }, + $cdom,$cnum); unless (($reply eq 'ok') || ($reply eq 'delayed')) { return 'error: '.$reply; } @@ -3936,7 +3947,7 @@ 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/|) || ($uri =~ m|^uploaded/|)) { + ($uri =~ m|home/[^/]+/public_html/|)) { return undef; } my $filename=$uri; @@ -3965,7 +3976,10 @@ sub metadata { } my %metathesekeys=(); unless ($filename=~/\.meta$/) { $filename.='.meta'; } - my $metastring=&getfile(&filelocation('',&clutter($filename))); + my $metastring; + if ($uri !~ m|^uploaded/|) { + $metastring=&getfile(&filelocation('',&clutter($filename))); + } my $parser=HTML::LCParser->new(\$metastring); my $token; undef %metathesekeys; @@ -4076,6 +4090,22 @@ sub metadata { # the next is the end of "start tag" } } + my ($extension) = ($uri =~ /\.(\w+)$/); + foreach my $key (sort(keys(%packagetab))) { + #&logthis("extsion1 $extension $key !!"); + #no specific packages #how's our extension + if ($key!~/^extension_\Q$extension\E&/) { next; } + &metadata_create_package_def($uri,$key,'extension_'.$extension, + \%metathesekeys); + } + if (!exists($metacache{$uri}->{':packages'})) { + foreach my $key (sort(keys(%packagetab))) { + #no specific packages well let's get default then + if ($key!~/^default&/) { next; } + &metadata_create_package_def($uri,$key,'default', + \%metathesekeys); + } + } # are there custom rights to evaluate if ($metacache{$uri}->{':copyright'} eq 'custom') { @@ -4104,6 +4134,30 @@ sub metadata { return $metacache{$uri}->{':'.$what}; } +sub metadata_create_package_def { + my ($uri,$key,$package,$metathesekeys)=@_; + my ($pack,$name,$subp)=split(/\&/,$key); + if ($subp eq 'default') { next; } + + if (defined($metacache{$uri}->{':packages'})) { + $metacache{$uri}->{':packages'}.=','.$package; + } else { + $metacache{$uri}->{':packages'}=$package; + } + my $value=$packagetab{$key}; + my $unikey; + $unikey='parameter_0_'.$name; + $metacache{$uri}->{':'.$unikey.'.part'}=0; + $$metathesekeys{$unikey}=1; + unless (defined($metacache{$uri}->{':'.$unikey.'.'.$subp})) { + $metacache{$uri}->{':'.$unikey.'.'.$subp}=$value; + } + if (defined($metacache{$uri}->{':'.$unikey.'.default'})) { + $metacache{$uri}->{':'.$unikey}= + $metacache{$uri}->{':'.$unikey.'.default'}; + } +} + sub metadata_generate_part0 { my ($metadata,$metacache,$uri) = @_; my %allnames; @@ -4378,10 +4432,34 @@ sub numval { return int($txt); } +sub numval2 { + 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; + my @txts=split(/(\d\d\d\d\d\d\d\d\d)/,$txt); + my $total; + foreach my $val (@txts) { $total+=$val; } + return int($total); +} + sub latest_rnd_algorithm_id { return '64bit2'; } +sub getCODE { + if (defined($ENV{'form.CODE'})) { return $ENV{'form.CODE'}; } + if (defined($Apache::lonhomework::parsing_a_problem) && + defined($Apache::lonhomework::history{'resource.CODE'})) { + return $Apache::lonhomework::history{'resource.CODE'}; + } + return undef; +} + sub rndseed { my ($symb,$courseid,$domain,$username)=@_; @@ -4393,9 +4471,8 @@ sub rndseed { if (!$domain) { $domain=$wdomain; } if (!$username) { $username=$wusername } my $which=$ENV{"course.$courseid.rndseed"}; - my $CODE=$ENV{'scantron.CODE'}; - if (defined($CODE)) { - &rndseed_CODE_64bit($symb,$courseid,$domain,$username); + if (defined(&getCODE())) { + return &rndseed_CODE_64bit($symb,$courseid,$domain,$username); } elsif ($which eq '64bit2') { return &rndseed_64bit2($symb,$courseid,$domain,$username); } elsif ($which eq '64bit') { @@ -4468,12 +4545,13 @@ sub rndseed_CODE_64bit { { use integer; my $symbchck=unpack("%32S*",$symb.' ') << 16; - my $symbseed=numval($symb); - my $CODEseed=numval($ENV{'scantron.CODE'}) << 16; + my $symbseed=numval2($symb); + my $CODEchck=unpack("%32S*",&getCODE().' ') << 16; + my $CODEseed=numval(&getCODE()); my $courseseed=unpack("%32S*",$courseid.' '); - my $num1=$symbseed+$CODEseed; - my $num2=$courseseed+$symbchck; - #&Apache::lonxml::debug("$symbseed:$CODEseed|$courseseed:$symbchck"); + my $num1=$symbseed+$CODEchck; + my $num2=$CODEseed+$courseseed+$symbchck; + #&Apache::lonxml::debug("$symbseed:$CODEchck|$CODEseed:$courseseed:$symbchck"); #&Apache::lonxml::debug("rndseed :$num1:$num2:$symb"); return "$num1,$num2"; } @@ -4566,71 +4644,60 @@ sub receipt { sub getfile { my ($file,$caller) = @_; - if ($file=~ m|^/*uploaded/(\w+)/(\w+)/(.+)$|) { # user file - my $info; - my $cdom = $1; - my $cnum = $2; - my $filename = $3; - my $path = $Apache::lonnet::perlvar{'lonDocRoot'}.'/userfiles'; - my ($lwpresp,$rtncode); - my $localfile = $path.'/'.$cdom.'/'.$cnum.'/'.$filename; - if (-e "$localfile") { - my @fileinfo = stat($localfile); - $lwpresp = &getuploaded('HEAD',$file,$cdom,$cnum,\$info,\$rtncode); - if ($lwpresp eq 'ok') { - if ($info > $fileinfo[9]) { - $info = ''; - $lwpresp = &getuploaded('GET',$file,$cdom,$cnum,\$info,\$rtncode); - if ($lwpresp eq 'ok') { - open (FILE,">$localfile"); - print FILE $info; - close(FILE); - if ($caller eq 'uploadrep') { - return 'ok'; - } else { - return $info; - } - } else { - return -1; - } - } else { - return &readfile($localfile); - } - } else { - if ($rtncode eq '404') { - unlink($localfile); - } - return -1; - } - } else { - $lwpresp = &getuploaded('GET',$file,$cdom,$cnum,\$info,\$rtncode); - if ($lwpresp eq 'ok') { - my @parts = ($cdom,$cnum); - if ($filename =~ m|^(.+)/[^/]+$|) { - push @parts, split(/\//,$1); - } - foreach my $part (@parts) { - $path .= '/'.$part; - if (!-e $path) { - mkdir($path,0770); - } - } - open (FILE,">$localfile"); - print FILE $info; - close(FILE); - if ($caller eq 'uploadrep') { - return 'ok'; - } else { - return $info; - } - } else { - return -1; - } - } - } else { # normal file from res space + + if ($file !~ m|^/*uploaded/(\w+)/(\w+)/(.+)$|) { + # normal file from res space &repcopy($file); return &readfile($file); } + + my $info; + my $cdom = $1; + my $cnum = $2; + my $filename = $3; + my $path = $Apache::lonnet::perlvar{'lonDocRoot'}.'/userfiles'; + my ($lwpresp,$rtncode); + my $localfile = $path.'/'.$cdom.'/'.$cnum.'/'.$filename; + if (-e "$localfile") { + my @fileinfo = stat($localfile); + $lwpresp = &getuploaded('HEAD',$file,$cdom,$cnum,\$info,\$rtncode); + if ($lwpresp ne 'ok') { + if ($rtncode eq '404') { + unlink($localfile); + } + return -1; + } + if ($info < $fileinfo[9]) { + return &readfile($localfile); + } + $info = ''; + $lwpresp = &getuploaded('GET',$file,$cdom,$cnum,\$info,\$rtncode); + if ($lwpresp ne 'ok') { + return -1; + } + } else { + $lwpresp = &getuploaded('GET',$file,$cdom,$cnum,\$info,\$rtncode); + if ($lwpresp ne 'ok') { + return -1; + } + my @parts = ($cdom,$cnum); + if ($filename =~ m|^(.+)/[^/]+$|) { + push @parts, split(/\//,$1); + } + foreach my $part (@parts) { + $path .= '/'.$part; + if (!-e $path) { + mkdir($path,0770); + } + } + } + open (FILE,">$localfile"); + print FILE $info; + close(FILE); + if ($caller eq 'uploadrep') { + return 'ok'; + } + return $info; } sub getuploaded { @@ -4641,16 +4708,15 @@ sub getuploaded { my $request=new HTTP::Request($reqtype,$uri); my $response=$ua->request($request); $$rtncode = $response->code; - if ($response->is_success()) { - if ($reqtype eq 'HEAD') { - $$info = &Date::Parse::str2time( $response->header('Last-modified') ); - } elsif ($reqtype eq 'GET') { - $$info = $response->content; - } - return 'ok'; - } else { - return 'failed'; + if (! $response->is_success()) { + return 'failed'; + } + if ($reqtype eq 'HEAD') { + $$info = &HTTP::Date::str2time( $response->header('Last-modified') ); + } elsif ($reqtype eq 'GET') { + $$info = $response->content; } + return 'ok'; } sub readfile { @@ -4803,7 +4869,7 @@ BEGIN { open(my $config,") { - if ($configline =~ /^[^\#]*PerlSetVar/) { + if ($configline=~/\S/ && $configline =~ /^[^\#]*PerlSetVar/) { my ($dummy,$varname,$varvalue)=split(/\s+/,$configline); chomp($varvalue); $perlvar{$varname}=$varvalue; @@ -4921,6 +4987,7 @@ BEGIN { open(my $config,"<$perlvar{'lonTabDir'}/packages.tab"); while (my $configline=<$config>) { + if ($configline !~ /\S/ || $configline=~/^#/) { next; } chomp($configline); my ($short,$plain)=split(/:/,$configline); my ($pack,$name)=split(/\&/,$short);