--- loncom/lonnet/perl/lonnet.pm 2004/05/11 06:49:58 1.500
+++ loncom/lonnet/perl/lonnet.pm 2004/09/20 21:10:00 1.523.2.6
@@ -1,7 +1,7 @@
# The LearningOnline Network
# TCP networking package
#
-# $Id: lonnet.pm,v 1.500 2004/05/11 06:49:58 albertel Exp $
+# $Id: lonnet.pm,v 1.523.2.6 2004/09/20 21:10:00 albertel Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -38,7 +38,7 @@ use vars
qw(%perlvar %hostname %homecache %badServerCache %hostip %iphost %spareid %hostdom
%libserv %pr %prp %metacache %packagetab %titlecache %courseresversioncache %resversioncache
%courselogs %accesshash %userrolehash $processmarker $dumpcount
- %coursedombuf %coursenumbuf %coursehombuf %coursedescrbuf %courseresdatacache
+ %coursedombuf %coursenumbuf %coursehombuf %coursedescrbuf %courseinstcodebuf %courseresdatacache
%userresdatacache %usectioncache %domaindescription %domain_auth_def %domain_auth_arg_def
%domain_lang_def %domain_city %domain_longi %domain_lati $tmpdir);
@@ -50,7 +50,7 @@ use Fcntl qw(:flock);
use Apache::loncoursedata;
use Apache::lonlocal;
use Storable qw(lock_store lock_nstore lock_retrieve freeze thaw);
-use Time::HiRes();
+use Time::HiRes qw( gettimeofday tv_interval );
my $readit;
=pod
@@ -434,7 +434,7 @@ sub overloaderror {
if ($overload>0) {
$r->err_headers_out->{'Retry-After'}=$overload;
$r->log_error('Overload of '.$overload.' on '.$checkserver);
- return 413;
+ return 409;
}
return '';
}
@@ -826,10 +826,12 @@ my $disk_caching_disabled=1;
sub devalidate_cache {
my ($cache,$id,$name) = @_;
delete $$cache{$id.'.time'};
+ delete $$cache{$id.'.file'};
delete $$cache{$id};
- if ($disk_caching_disabled) { return; }
+ if (1 || $disk_caching_disabled) { return; }
my $filename=$perlvar{'lonDaemons'}.'/tmp/lonnet_internal_cache_'.$name.".db";
- open(DB,"$filename.lock");
+ if (!-e $filename) { return; }
+ open(DB,">$filename.lock");
flock(DB,LOCK_EX);
my %hash;
if (tie(%hash,'GDBM_File',$filename,&GDBM_WRCREAT(),0640)) {
@@ -856,16 +858,32 @@ sub is_cached {
my ($cache,$id,$name,$time) = @_;
if (!$time) { $time=300; }
if (!exists($$cache{$id.'.time'})) {
- &load_cache_item($cache,$name,$id);
+ &load_cache_item($cache,$name,$id,$time);
}
if (!exists($$cache{$id.'.time'})) {
# &logthis("Didn't find $id");
return (undef,undef);
} else {
if (time-($$cache{$id.'.time'})>$time) {
-# &logthis("Devalidating $id - ".time-($$cache{$id.'.time'}));
- &devalidate_cache($cache,$id,$name);
- return (undef,undef);
+ if (exists($$cache{$id.'.file'})) {
+ foreach my $filename (@{ $$cache{$id.'.file'} }) {
+ my $mtime=(stat($filename))[9];
+ #+1 is to take care of edge effects
+ if ($mtime && (($mtime+1) < ($$cache{$id.'.time'}))) {
+# &logthis("Upping $mtime - ".$$cache{$id.'.time'}.
+# "$id because of $filename");
+ } else {
+# &logthis("Devalidating $filename $id - ".(time-($$cache{$id.'.time'})));
+ &devalidate_cache($cache,$id,$name);
+ return (undef,undef);
+ }
+ }
+ $$cache{$id.'.time'}=time;
+ } else {
+# &logthis("Devalidating $id - ".time-($$cache{$id.'.time'}));
+ &devalidate_cache($cache,$id,$name);
+ return (undef,undef);
+ }
}
}
return ($$cache{$id},1);
@@ -881,44 +899,69 @@ sub do_cache {
$$cache{$id};
}
+my %do_save_item;
+my %do_save;
sub save_cache_item {
my ($cache,$name,$id)=@_;
if ($disk_caching_disabled) { return; }
- my $starttime=&Time::HiRes::time();
-# &logthis("Saving :$name:$id");
- my %hash;
- my $filename=$perlvar{'lonDaemons'}.'/tmp/lonnet_internal_cache_'.$name.".db";
- open(DB,"$filename.lock");
- flock(DB,LOCK_EX);
- if (tie(%hash,'GDBM_File',$filename,&GDBM_WRCREAT(),0640)) {
- eval <<'EVALBLOCK';
- $hash{$id.'.time'}=$$cache{$id.'.time'};
- $hash{$id}=freeze({'item'=>$$cache{$id}});
+ $do_save{$name}=$cache;
+ if (!exists($do_save_item{$name})) { $do_save_item{$name}={} }
+ $do_save_item{$name}->{$id}=1;
+ return;
+}
+
+sub save_cache {
+ if ($disk_caching_disabled) { return; }
+ my ($cache,$name,$id);
+ foreach $name (keys(%do_save)) {
+ $cache=$do_save{$name};
+
+ my $starttime=&Time::HiRes::time();
+ &logthis("Saving :$name:");
+ my %hash;
+ my $filename=$perlvar{'lonDaemons'}.'/tmp/lonnet_internal_cache_'.$name.".db";
+ open(DB,">$filename.lock");
+ flock(DB,LOCK_EX);
+ if (tie(%hash,'GDBM_File',$filename,&GDBM_WRCREAT(),0640)) {
+ foreach $id (keys(%{ $do_save_item{$name} })) {
+ eval <<'EVALBLOCK';
+ $hash{$id.'.time'}=$$cache{$id.'.time'};
+ $hash{$id}=freeze({'item'=>$$cache{$id}});
+ if (exists($$cache{$id.'.file'})) {
+ $hash{$id.'.file'}=freeze({'item'=>$$cache{$id.'.file'}});
+ }
EVALBLOCK
- if ($@) {
- &logthis("save_cache blew up :$@:$name");
- unlink($filename);
- }
- } else {
- if (-e $filename) {
- &logthis("Unable to tie hash (save cache item): $name ($!)");
- unlink($filename);
+ if ($@) {
+ &logthis("save_cache blew up :$@:$name");
+ unlink($filename);
+ last;
+ }
+ }
+ } else {
+ if (-e $filename) {
+ &logthis("Unable to tie hash (save cache): $name ($!)");
+ unlink($filename);
+ }
}
+ untie(%hash);
+ flock(DB,LOCK_UN);
+ close(DB);
+ &logthis("save_cache $name took ".(&Time::HiRes::time()-$starttime));
}
- untie(%hash);
- flock(DB,LOCK_UN);
- close(DB);
-# &logthis("save_cache_item $name took ".(&Time::HiRes::time()-$starttime));
+ undef(%do_save);
+ undef(%do_save_item);
+
}
sub load_cache_item {
- my ($cache,$name,$id)=@_;
+ my ($cache,$name,$id,$time)=@_;
if ($disk_caching_disabled) { return; }
my $starttime=&Time::HiRes::time();
# &logthis("Before Loading $name for $id size is ".scalar(%$cache));
my %hash;
my $filename=$perlvar{'lonDaemons'}.'/tmp/lonnet_internal_cache_'.$name.".db";
- open(DB,"$filename.lock");
+ if (!-e $filename) { return; }
+ open(DB,">$filename.lock");
flock(DB,LOCK_SH);
if (tie(%hash,'GDBM_File',$filename,&GDBM_READER(),0640)) {
eval <<'EVALBLOCK';
@@ -935,9 +978,17 @@ sub load_cache_item {
}
# &logthis("Initial load: $count");
} else {
- my $hashref=thaw($hash{$id});
- $$cache{$id}=$hashref->{'item'};
- $$cache{$id.'.time'}=$hash{$id.'.time'};
+ if (($$cache{$id.'.time'}+$time) < time) {
+ $$cache{$id.'.time'}=$hash{$id.'.time'};
+ {
+ my $hashref=thaw($hash{$id});
+ $$cache{$id}=$hashref->{'item'};
+ }
+ if (exists($hash{$id.'.file'})) {
+ my $hashref=thaw($hash{$id.'.file'});
+ $$cache{$id.'.file'}=$hashref->{'item'};
+ }
+ }
}
EVALBLOCK
if ($@) {
@@ -1047,6 +1098,7 @@ sub currentversion {
sub subscribe {
my $fname=shift;
if ($fname=~/\/(aboutme|syllabus|bulletinboard|smppg)$/) { return ''; }
+ $fname=~s/[\n\r]//g;
my $author=$fname;
$author=~s/\/home\/httpd\/html\/res\/([^\/]*)\/([^\/]*).*/$1\/$2/;
my ($udom,$uname)=split(/\//,$author);
@@ -1067,6 +1119,7 @@ sub repcopy {
my $filename=shift;
$filename=~s/\/+/\//g;
if ($filename=~/^\/home\/httpd\/html\/adm\//) { return OK; }
+ $filename=~s/[\n\r]//g;
my $transname="$filename.in.transfer";
if ((-e $filename) || (-e $transname)) { return OK; }
my $remoteurl=subscribe($filename);
@@ -1282,6 +1335,22 @@ sub userfileupload {
# See if there is anything left
unless ($fname) { return 'error: no uploaded file'; }
chop($ENV{'form.'.$formname});
+ if (($formname eq 'screenshot') && ($subdir eq 'helprequests')) { #files uploaded to help request form are handled differently
+ my $now = time;
+ my $filepath = 'tmp/helprequests/'.$now;
+ my @parts=split(/\//,$filepath);
+ my $fullpath = $perlvar{'lonDaemons'};
+ for (my $i=0;$i<@parts;$i++) {
+ $fullpath .= '/'.$parts[$i];
+ if ((-e $fullpath)!=1) {
+ mkdir($fullpath,0777);
+ }
+ }
+ open(my $fh,'>'.$fullpath.'/'.$fname);
+ print $fh $ENV{'form.'.$formname};
+ close($fh);
+ return $fullpath.'/'.$fname;
+ }
# Create the directory if not present
my $docuname='';
my $docudom='';
@@ -1395,10 +1464,12 @@ sub flushcourselogs {
}
if ($courseidbuffer{$coursehombuf{$crsid}}) {
$courseidbuffer{$coursehombuf{$crsid}}.='&'.
- &escape($crsid).'='.&escape($coursedescrbuf{$crsid});
+ &escape($crsid).'='.&escape($coursedescrbuf{$crsid}).
+ '='.&escape($courseinstcodebuf{$crsid});
} else {
$courseidbuffer{$coursehombuf{$crsid}}=
- &escape($crsid).'='.&escape($coursedescrbuf{$crsid});
+ &escape($crsid).'='.&escape($coursedescrbuf{$crsid}).
+ '='.&escape($courseinstcodebuf{$crsid});
}
}
#
@@ -1472,6 +1543,8 @@ sub courselog {
$ENV{'course.'.$ENV{'request.course.id'}.'.home'};
$coursedescrbuf{$ENV{'request.course.id'}}=
$ENV{'course.'.$ENV{'request.course.id'}.'.description'};
+ $courseinstcodebuf{$ENV{'request.course.id'}}=
+ $ENV{'course.'.$ENV{'request.course.id'}.'.internal.coursecode'};
if (defined $courselogs{$ENV{'request.course.id'}}) {
$courselogs{$ENV{'request.course.id'}}.='&'.$what;
} else {
@@ -1596,7 +1669,7 @@ sub getannounce {
if ($announcement=~/\w/) {
return
'
';
+ ''.$announcement.' |
';
} else {
return '';
}
@@ -1615,21 +1688,22 @@ sub courseidput {
}
sub courseiddump {
- my ($domfilter,$descfilter,$sincefilter)=@_;
+ my ($domfilter,$descfilter,$sincefilter,$hostidflag,$hostidref)=@_;
my %returnhash=();
unless ($domfilter) { $domfilter=''; }
foreach my $tryserver (keys %libserv) {
- if ((!$domfilter) || ($hostdom{$tryserver} eq $domfilter)) {
- foreach (
- split(/\&/,&reply('courseiddump:'.$hostdom{$tryserver}.':'.
+ if ( ($hostidflag == 1 && grep/^$tryserver$/,@{$hostidref}) || (!defined($hostidflag)) ) {
+ if ((!$domfilter) || ($hostdom{$tryserver} eq $domfilter)) {
+ foreach (
+ split(/\&/,&reply('courseiddump:'.$hostdom{$tryserver}.':'.
$sincefilter.':'.&escape($descfilter),
$tryserver))) {
- my ($key,$value)=split(/\=/,$_);
- if (($key) && ($value)) {
- $returnhash{&unescape($key)}=&unescape($value);
+ my ($key,$value)=split(/\=/,$_);
+ if (($key) && ($value)) {
+ $returnhash{&unescape($key)}=$value;
+ }
}
}
-
}
}
return %returnhash;
@@ -1638,6 +1712,28 @@ sub courseiddump {
#
# ----------------------------------------------------------- Check out an item
+sub get_first_access {
+ my ($type,$argsymb)=@_;
+ my ($symb,$courseid,$udom,$uname)=&Apache::lonxml::whichuser();
+ if ($argsymb) { $symb=$argsymb; }
+ my ($map,$id,$res)=&decode_symb($symb);
+ if ($type eq 'map') { $res=$map; }
+ my %times=&get('firstaccesstimes',[$res],$udom,$uname);
+ return $times{$res};
+}
+
+sub set_first_access {
+ my ($type)=@_;
+ my ($symb,$courseid,$udom,$uname)=&Apache::lonxml::whichuser();
+ my ($map,$id,$res)=&decode_symb($symb);
+ if ($type eq 'map') { $res=$map; }
+ my $firstaccess=&get_first_access($type);
+ if (!$firstaccess) {
+ return &put('firstaccesstimes',{$res=>time},$udom,$uname);
+ }
+ return 'already_set';
+}
+
sub checkout {
my ($symb,$tuname,$tudom,$tcrsid)=@_;
my $now=time;
@@ -3031,6 +3127,59 @@ sub log_query {
return get_query_reply($queryid);
}
+# ------- Request retrieval of institutional classlists for course(s)
+
+sub fetch_enrollment_query {
+ my ($context,$affiliatesref,$replyref,$dom,$cnum) = @_;
+ my $homeserver;
+ if ($context eq 'automated') {
+ $homeserver = $perlvar{'lonHostID'};
+ } else {
+ $homeserver = &homeserver($cnum,$dom);
+ }
+ my $host=$hostname{$homeserver};
+ my $cmd = '';
+ foreach (keys %{$affiliatesref}) {
+ $cmd .= $_.'='.join(",",@{$$affiliatesref{$_}}).'%%';
+ }
+ $cmd =~ s/%%$//;
+ $cmd = &escape($cmd);
+ my $query = 'fetchenrollment';
+ my $queryid=&reply("querysend:".$query.':'.$dom.':'.$ENV{'user.name'}.':'.$cmd,$homeserver);
+ unless ($queryid=~/^\Q$host\E\_/) { return 'error: '.$queryid; }
+ my $reply = &get_query_reply($queryid);
+ unless ( ($reply =~/^timeout/) || ($reply =~/^error/) ) {
+ my @responses = split/:/,$reply;
+ if ($homeserver eq $perlvar{'lonHostID'}) {
+ foreach (@responses) {
+ my ($key,$value) = split/=/,$_;
+ $$replyref{$key} = $value;
+ }
+ } else {
+ my $pathname = $perlvar{'lonDaemons'}.'/tmp';
+ foreach (@responses) {
+ my ($key,$value) = split/=/,$_;
+ $$replyref{$key} = $value;
+ if ($value > 0) {
+ foreach (@{$$affiliatesref{$key}}) {
+ my $filename = $dom.'_'.$key.'_'.$_.'_classlist.xml';
+ my $destname = $pathname.'/'.$filename;
+ my $xml_classlist = &reply("autoretrieve:".$filename,$homeserver);
+ unless ($xml_classlist =~ /^error/) {
+ if ( open(FILE,">$destname") ) {
+ print FILE &unescape($xml_classlist);
+ close(FILE);
+ }
+ }
+ }
+ }
+ }
+ }
+ return 'ok';
+ }
+ return 'error';
+}
+
sub get_query_reply {
my $queryid=shift;
my $replyfile=$perlvar{'lonDaemons'}.'/tmp/'.$queryid;
@@ -3075,6 +3224,80 @@ sub userlog_query {
return &log_query($uname,$udom,'userlog',%filters);
}
+#--------- Call auto-enrollment subs in localenroll.pm for homeserver for course
+
+sub auto_run {
+ my ($cnum,$cdom) = @_;
+ my $homeserver = &homeserver($cnum,$cdom);
+ my $response = &reply('autorun:'.$cdom,$homeserver);
+ return $response;
+}
+
+sub auto_get_sections {
+ my ($cnum,$cdom,$inst_coursecode) = @_;
+ my $homeserver = &homeserver($cnum,$cdom);
+ my @secs = ();
+ my $response=&unescape(&reply('autogetsections:'.$inst_coursecode.':'.$cdom,$homeserver));
+ unless ($response eq 'refused') {
+ @secs = split/:/,$response;
+ }
+ return @secs;
+}
+
+sub auto_new_course {
+ my ($cnum,$cdom,$inst_course_id,$owner) = @_;
+ my $homeserver = &homeserver($cnum,$cdom);
+ my $response=&unescape(&reply('autonewcourse:'.$inst_course_id.':'.$owner.':'.$cdom,$homeserver));
+ return $response;
+}
+
+sub auto_validate_courseID {
+ my ($cnum,$cdom,$inst_course_id) = @_;
+ my $homeserver = &homeserver($cnum,$cdom);
+ my $response=&unescape(&reply('autovalidatecourse:'.$inst_course_id.':'.$cdom,$homeserver));
+ return $response;
+}
+
+sub auto_create_password {
+ my ($cnum,$cdom,$authparam) = @_;
+ my $homeserver = &homeserver($cnum,$cdom);
+ my $create_passwd = 0;
+ my $authchk = '';
+ my $response=&unescape(&reply('autocreatepassword:'.$authparam.':'.$cdom,$homeserver));
+ if ($response eq 'refused') {
+ $authchk = 'refused';
+ } else {
+ ($authparam,$create_passwd,$authchk) = split/:/,$response;
+ }
+ return ($authparam,$create_passwd,$authchk);
+}
+
+sub auto_instcode_format {
+ my ($caller,$codedom,$instcodes,$codes,$codetitles,$cat_titles,$cat_order) = @_;
+ my $courses = '';
+ my $homeserver;
+ if ($caller eq 'global') {
+ $homeserver = $perlvar{'lonHostID'};
+ } else {
+ $homeserver = &homeserver($caller,$codedom);
+ }
+ my $host=$hostname{$homeserver};
+ foreach (keys %{$instcodes}) {
+ $courses .= &escape($_).'='.&escape($$instcodes{$_}).'&';
+ }
+ chop($courses);
+ my $response=&reply('autoinstcodeformat:'.$codedom.':'.$courses,$homeserver);
+ unless ($response =~ /(con_lost|error|no_such_host|refused)/) {
+ my ($codes_str,$codetitles_str,$cat_titles_str,$cat_order_str) = split/:/,$response;
+ %{$codes} = &str2hash($codes_str);
+ @{$codetitles} = &str2array($codetitles_str);
+ %{$cat_titles} = &str2hash($cat_titles_str);
+ %{$cat_order} = &str2hash($cat_order_str);
+ return 'ok';
+ }
+ return $response;
+}
+
# ------------------------------------------------------------------ Plain Text
sub plaintext {
@@ -3265,7 +3488,7 @@ sub modifyuser {
sub modifystudent {
my ($udom,$uname,$uid,$umode,$upass,$first,$middle,$last,$gene,$usec,
- $end,$start,$forceid,$desiredhome,$email,$type,$cid)=@_;
+ $end,$start,$forceid,$desiredhome,$email,$type,$locktype,$cid)=@_;
if (!$cid) {
unless ($cid=$ENV{'request.course.id'}) {
return 'not_in_class';
@@ -3280,13 +3503,12 @@ sub modifystudent {
# students environment
$uid = undef if (!$forceid);
$reply = &modify_student_enrollment($udom,$uname,$uid,$first,$middle,$last,
- $gene,$usec,$end,$start,$type,$cid);
+ $gene,$usec,$end,$start,$type,$locktype,$cid);
return $reply;
}
sub modify_student_enrollment {
- my ($udom,$uname,$uid,$first,$middle,$last,$gene,$usec,$end,$start,$type,
- $cid) = @_;
+ my ($udom,$uname,$uid,$first,$middle,$last,$gene,$usec,$end,$start,$type,$locktype,$cid) = @_;
my ($cdom,$cnum,$chome);
if (!$cid) {
unless ($cid=$ENV{'request.course.id'}) {
@@ -3332,7 +3554,7 @@ sub modify_student_enrollment {
$first,$middle);
my $reply=cput('classlist',
{"$uname:$udom" =>
- join(':',$end,$start,$uid,$usec,$fullname,$type) },
+ join(':',$end,$start,$uid,$usec,$fullname,$type,$locktype) },
$cdom,$cnum);
unless (($reply eq 'ok') || ($reply eq 'delayed')) {
return 'error: '.$reply;
@@ -3368,7 +3590,7 @@ sub writecoursepref {
# ---------------------------------------------------------- Make/modify course
sub createcourse {
- my ($udom,$description,$url,$course_server,$nonstandard)=@_;
+ my ($udom,$description,$url,$course_server,$nonstandard,$inst_code)=@_;
$url=&declutter($url);
my $cid='';
unless (&allowed('ccc',$udom)) {
@@ -3401,9 +3623,9 @@ sub createcourse {
return 'error: no such course';
}
# ----------------------------------------------------------------- Course made
-# log existance
- &courseidput($udom,&escape($udom.'_'.$uname).'='.&escape($description),
- $uhome);
+# log existence
+ &courseidput($udom,&escape($udom.'_'.$uname).'='.&escape($description).
+ '='.&escape($inst_code),$uhome);
&flushcourselogs();
# set toplevel url
my $topurl=$url;
@@ -3456,6 +3678,42 @@ sub revokecustomrole {
$deleteflag);
}
+
+# ------------------------------------------------------------ Portfolio Director Lister
+# returns listing of contents of user's /userfiles/portfolio/ directory
+#
+
+sub portfoliolist {
+ my ($currentPath, $currentFile) = @_;
+ my ($udom, $uname, $portfolioRoot);
+ $uname=$ENV{'user.name'};
+ $udom=$ENV{'user.domain'};
+ # really should interrogate the system for home directory information, but . . .
+ $portfolioRoot = '/home/httpd/lonUsers/'.$udom.'/';
+ $uname =~ /^(.?)(.?)(.?)/;
+ $portfolioRoot = $portfolioRoot.$1.'/'.$2.'/'.$3.'/'.$uname.'/userfiles/portfolio';
+ my $listing = &reply('ls:'.$portfolioRoot.$currentPath, &homeserver($uname,$udom));
+ return $listing;
+}
+
+sub portfoliomanage {
+
+#FIXME please user the existing remove userfile function instead and
+#add a userfilerename functions.
+#FIXME uhome should never be an argument to any lonnet functions
+
+ # handles deleting and renaming files in user's userfiles/portfolio/ directory
+ #
+ my ($filename, $fileaction, $filenewname) = @_;
+ my ($udom, $uname, $uhome);
+ $uname=$ENV{'user.name'};
+ $udom=$ENV{'user.domain'};
+ $uhome=$ENV{'user.home'};
+ my $listing = reply('portfoliomanage:'.$uname.':'.$udom.':'.$filename.':'.$fileaction.':'.$filenewname, $uhome);
+ return $listing;
+}
+
+
# ------------------------------------------------------------ Directory lister
sub dirlist {
@@ -3789,11 +4047,14 @@ sub EXT {
my $section;
if (defined($courseid) && $courseid eq $ENV{'request.course.id'}) {
+ if (!$symbparm) { $symbparm=&symbread(); }
+ }
+ if ($symbparm && defined($courseid) &&
+ $courseid eq $ENV{'request.course.id'}) {
#print '
'.$space.' - '.$qualifier.' - '.$spacequalifierrest;
# ----------------------------------------------------- Cascading lookup scheme
- if (!$symbparm) { $symbparm=&symbread(); }
my $symbp=$symbparm;
my $mapp=(&decode_symb($symbp))[0];
@@ -3804,11 +4065,11 @@ sub EXT {
($ENV{'user.domain'} eq $udom)) {
$section=$ENV{'request.course.sec'};
} else {
- if (! defined($usection)) {
- $section=&usection($udom,$uname,$courseid);
- } else {
- $section = $usection;
- }
+ if (! defined($usection)) {
+ $section=&usection($udom,$uname,$courseid);
+ } else {
+ $section = $usection;
+ }
}
my $seclevel=$courseid.'.['.$section.'].'.$spacequalifierrest;
@@ -3846,7 +4107,7 @@ sub EXT {
$uname." at ".$udom.": ".
$tmp."");
} elsif ($tmp=~/error: 2 /) {
- &EXT_cache_set($udom,$uname);
+ &EXT_cache_set($udom,$uname);
} elsif ($tmp =~ /^(con_lost|no_such_host)/) {
return $tmp;
}
@@ -3856,10 +4117,10 @@ sub EXT {
# -------------------------------------------------------- second, check course
my $coursereply=&courseresdata($ENV{'course.'.$courseid.'.num'},
- $ENV{'course.'.$courseid.'.domain'},
- ($seclevelr,$seclevelm,$seclevel,
- $courselevelr,$courselevelm,
- $courselevel));
+ $ENV{'course.'.$courseid.'.domain'},
+ ($seclevelr,$seclevelm,$seclevel,
+ $courselevelr,$courselevelm,
+ $courselevel));
if (defined($coursereply)) { return $coursereply; }
# ------------------------------------------------------ third, check map parms
@@ -3992,7 +4253,9 @@ sub metadata {
unless ($filename=~/\.meta$/) { $filename.='.meta'; }
my $metastring;
if ($uri !~ m|^uploaded/|) {
- $metastring=&getfile(&filelocation('',&clutter($filename)));
+ my $file=&filelocation('',&clutter($filename));
+ push(@{$metacache{$uri.'.file'}},$file);
+ $metastring=&getfile($file);
}
my $parser=HTML::LCParser->new(\$metastring);
my $token;
@@ -4251,7 +4514,10 @@ sub symblist {
# --------------------------------------------------------------- Verify a symb
sub symbverify {
- my ($symb,$thisfn)=@_;
+ my ($symb,$thisurl)=@_;
+ my $thisfn=$thisurl;
+# wrapper not part of symbs
+ $thisfn=~s/^\/adm\/wrapper//;
$thisfn=&declutter($thisfn);
# direct jump to resource in page or to a sequence - will construct own symbs
if ($thisfn=~/\.(page|sequence)$/) { return 1; }
@@ -4261,6 +4527,7 @@ sub symbverify {
unless ($url eq $thisfn) { return 0; }
$symb=&symbclean($symb);
+ $thisurl=&deversion($thisurl);
$thisfn=&deversion($thisfn);
my %bighash;
@@ -4268,9 +4535,9 @@ sub symbverify {
if (tie(%bighash,'GDBM_File',$ENV{'request.course.fn'}.'.db',
&GDBM_READER(),0640)) {
- my $ids=$bighash{'ids_'.&clutter($thisfn)};
+ my $ids=$bighash{'ids_'.&clutter($thisurl)};
unless ($ids) {
- $ids=$bighash{'ids_/'.$thisfn};
+ $ids=$bighash{'ids_/'.$thisurl};
}
if ($ids) {
# ------------------------------------------------------------------- Has ID(s)
@@ -4299,6 +4566,9 @@ sub symbclean {
# remove version from URL
$symb=~s/\.(\d+)\.(\w+)$/\.$2/;
+# remove wrapper
+
+ $symb=~s/(\_\_\_\d+\_\_\_)adm\/wrapper\/(res\/)*/$1/;
return $symb;
}
@@ -4350,14 +4620,20 @@ sub deversion {
sub symbread {
my ($thisfn,$donotrecurse)=@_;
+ my $cache_str='request.symbread.cached.'.$thisfn;
+ if (defined($ENV{$cache_str})) { return $ENV{$cache_str}; }
# no filename provided? try from environment
unless ($thisfn) {
- if ($ENV{'request.symb'}) { return &symbclean($ENV{'request.symb'}); }
+ if ($ENV{'request.symb'}) {
+ return $ENV{$cache_str}=&symbclean($ENV{'request.symb'});
+ }
$thisfn=$ENV{'request.filename'};
}
# is that filename actually a symb? Verify, clean, and return
if ($thisfn=~/\_\_\_\d+\_\_\_(.*)$/) {
- if (&symbverify($thisfn,$1)) { return &symbclean($thisfn); }
+ if (&symbverify($thisfn,$1)) {
+ return $ENV{$cache_str}=&symbclean($thisfn);
+ }
}
$thisfn=declutter($thisfn);
my %hash;
@@ -4378,7 +4654,7 @@ sub symbread {
unless ($syval=~/\_\d+$/) {
unless ($ENV{'form.request.prefix'}=~/\.(\d+)\_$/) {
&appenv('request.ambiguous' => $thisfn);
- return '';
+ return $ENV{$cache_str}='';
}
$syval.=$1;
}
@@ -4425,11 +4701,11 @@ sub symbread {
}
}
if ($syval) {
- return &symbclean($syval.'___'.$thisfn);
+ return $ENV{$cache_str}=&symbclean($syval.'___'.$thisfn);
}
}
&appenv('request.ambiguous' => $thisfn);
- return '';
+ return $ENV{$cache_str}='';
}
# ---------------------------------------------------------- Return random seed
@@ -4462,7 +4738,16 @@ sub numval2 {
}
sub latest_rnd_algorithm_id {
- return '64bit2';
+ return '64bit3';
+}
+
+sub get_rand_alg {
+ my ($courseid)=@_;
+ if (!$courseid) { $courseid=(&Apache::lonxml::whichuser())[1]; }
+ if ($courseid) {
+ return $ENV{"course.$courseid.rndseed"};
+ }
+ return &latest_rnd_algorithm_id();
}
sub getCODE {
@@ -4484,9 +4769,11 @@ sub rndseed {
if (!$courseid) { $courseid=$wcourseid; }
if (!$domain) { $domain=$wdomain; }
if (!$username) { $username=$wusername }
- my $which=$ENV{"course.$courseid.rndseed"};
+ my $which=&get_rand_alg();
if (defined(&getCODE())) {
return &rndseed_CODE_64bit($symb,$courseid,$domain,$username);
+ } elsif ($which eq '64bit3') {
+ return &rndseed_64bit3($symb,$courseid,$domain,$username);
} elsif ($which eq '64bit2') {
return &rndseed_64bit2($symb,$courseid,$domain,$username);
} elsif ($which eq '64bit') {
@@ -4554,6 +4841,28 @@ sub rndseed_64bit2 {
}
}
+sub rndseed_64bit3 {
+ my ($symb,$courseid,$domain,$username)=@_;
+ {
+ use integer;
+ # strings need to be an even # of cahracters long, it it is odd the
+ # last characters gets thrown away
+ my $symbchck=unpack("%32S*",$symb.' ') << 21;
+ my $symbseed=numval2($symb) << 10;
+ my $namechck=unpack("%32S*",$username.' ');
+
+ my $nameseed=numval2($username) << 21;
+ my $domainseed=unpack("%32S*",$domain.' ') << 10;
+ my $courseseed=unpack("%32S*",$courseid.' ');
+
+ my $num1=$symbchck+$symbseed+$namechck;
+ my $num2=$nameseed+$domainseed+$courseseed;
+ #&Apache::lonxml::debug("$symbseed:$nameseed;$domainseed|$courseseed;$namechck:$symbchck");
+ #&Apache::lonxml::debug("rndseed :$num:$symb");
+ return "$num1:$num2";
+ }
+}
+
sub rndseed_CODE_64bit {
my ($symb,$courseid,$domain,$username)=@_;
{
@@ -4567,14 +4876,14 @@ sub rndseed_CODE_64bit {
my $num2=$CODEseed+$courseseed+$symbchck;
#&Apache::lonxml::debug("$symbseed:$CODEchck|$CODEseed:$courseseed:$symbchck");
#&Apache::lonxml::debug("rndseed :$num1:$num2:$symb");
- return "$num1,$num2";
+ return "$num1:$num2";
}
}
sub setup_random_from_rndseed {
my ($rndseed)=@_;
- if ($rndseed =~/,/) {
- my ($num1,$num2)=split(/,/,$rndseed);
+ if ($rndseed =~/([,:])/) {
+ my ($num1,$num2)=split(/[,:]/,$rndseed);
&Math::Random::random_set_seed(abs($num1),abs($num2));
} else {
&Math::Random::random_set_seed_from_phrase($rndseed);
@@ -4679,6 +4988,14 @@ sub getfile {
if ($rtncode eq '404') {
unlink($localfile);
}
+ #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;
+ # }
return -1;
}
if ($info < $fileinfo[9]) {
@@ -4692,12 +5009,19 @@ sub getfile {
} else {
$lwpresp = &getuploaded('GET',$file,$cdom,$cnum,\$info,\$rtncode);
if ($lwpresp ne 'ok') {
- return -1;
+ 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;
+ }
}
my @parts = ($cdom,$cnum);
if ($filename =~ m|^(.+)/[^/]+$|) {
push @parts, split(/\//,$1);
- }
+ }
foreach my $part (@parts) {
$path .= '/'.$part;
if (!-e $path) {
@@ -4714,6 +5038,22 @@ sub getfile {
return $info;
}
+sub tokenwrapper {
+ my $uri=shift;
+ $uri=~s/^http\:\/\/([^\/]+)//;
+ $uri=~s/^\///;
+ $ENV{'user.environment'}=~/\/([^\/]+)\.id/;
+ my $token=$1;
+ if ($uri=~/^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';
+ }
+}
+
sub getuploaded {
my ($reqtype,$uri,$cdom,$cnum,$info,$rtncode) = @_;
$uri=~s/^\///;
@@ -4821,7 +5161,7 @@ sub declutter {
sub clutter {
my $thisfn='/'.&declutter(shift);
- unless ($thisfn=~/^\/(uploaded|adm|userfiles|ext|raw|priv)\//) {
+ unless ($thisfn=~/^\/(uploaded|adm|userfiles|ext|raw|priv|public)\//) {
$thisfn='/res'.$thisfn;
}
return $thisfn;