--- loncom/lonnet/perl/lonnet.pm 2006/05/15 23:42:52 1.683.2.21
+++ loncom/lonnet/perl/lonnet.pm 2006/03/04 06:03:30 1.717
@@ -1,7 +1,7 @@
# The LearningOnline Network
# TCP networking package
#
-# $Id: lonnet.pm,v 1.683.2.21 2006/05/15 23:42:52 albertel Exp $
+# $Id: lonnet.pm,v 1.717 2006/03/04 06:03:30 albertel Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -124,7 +124,7 @@ sub logperm {
# -------------------------------------------------- Non-critical communication
sub subreply {
my ($cmd,$server)=@_;
- my $peerfile="$perlvar{'lonSockDir'}/$server";
+ my $peerfile="$perlvar{'lonSockDir'}/".$hostname{$server};
#
# With loncnew process trimming, there's a timing hole between lonc server
# process exit and the master server picking up the listen on the AF_UNIX
@@ -152,7 +152,7 @@ sub subreply {
}
my $answer;
if ($client) {
- print $client "$cmd\n";
+ print $client "sethost:$server:$cmd\n";
$answer=<$client>;
if (!$answer) { $answer="con_lost"; }
chomp($answer);
@@ -272,8 +272,6 @@ sub transfer_profile_to_env {
for ($envi=0;$envi<=$#profile;$envi++) {
chomp($profile[$envi]);
my ($envname,$envvalue)=split(/=/,$profile[$envi],2);
- $envname=&unescape($envname);
- $envvalue=&unescape($envvalue);
$env{$envname} = $envvalue;
if (my ($key,$time) = ($envname =~ /^(cgi\.(\d+)_\d+\.)/)) {
if ($time < time-300) {
@@ -291,14 +289,14 @@ sub transfer_profile_to_env {
sub appenv {
my %newenv=@_;
- foreach (keys %newenv) {
- if (($newenv{$_}=~/^user\.role/) || ($newenv{$_}=~/^user\.priv/)) {
+ foreach my $key (keys(%newenv)) {
+ if (($newenv{$key}=~/^user\.role/) || ($newenv{$key}=~/^user\.priv/)) {
&logthis("WARNING: ".
- "Attempt to modify environment ".$_." to ".$newenv{$_}
+ "Attempt to modify environment ".$key." to ".$newenv{$key}
.'');
- delete($newenv{$_});
+ delete($newenv{$key});
} else {
- $env{$_}=$newenv{$_};
+ $env{$key}=$newenv{$key};
}
}
@@ -326,8 +324,6 @@ sub appenv {
chomp($oldenv[$i]);
if ($oldenv[$i] ne '') {
my ($name,$value)=split(/=/,$oldenv[$i],2);
- $name=&unescape($name);
- $value=&unescape($value);
unless (defined($newenv{$name})) {
$newenv{$name}=$value;
}
@@ -340,7 +336,7 @@ sub appenv {
}
my $newname;
foreach $newname (keys %newenv) {
- print $fh &escape($newname).'='.&escape($newenv{$newname})."\n";
+ print $fh "$newname=$newenv{$newname}\n";
}
close($fh);
}
@@ -352,6 +348,7 @@ sub appenv {
sub delenv {
my $delthis=shift;
+ my %newenv=();
if (($delthis=~/user\.role/) || ($delthis=~/user\.priv/)) {
&logthis("WARNING: ".
"Attempt to delete from environment ".$delthis);
@@ -384,10 +381,8 @@ sub delenv {
return 'error: '.$!;
}
foreach my $cur_key (@oldenv) {
- my $unescaped_cur_key = &unescape($cur_key);
- if ($unescaped_cur_key=~/^$delthis/) {
- my ($key) = split('=',$cur_key,2);
- $key = &unescape($key);
+ if ($cur_key=~/^$delthis/) {
+ my ($key,undef) = split('=',$cur_key,2);
delete($env{$key});
} else {
print $fh $cur_key;
@@ -1150,7 +1145,9 @@ sub ssi {
my $ua=new LWP::UserAgent;
my $request;
-
+
+ $form{'no_update_last_known'}=1;
+
if (%form) {
$request=new HTTP::Request('POST',"http://".$ENV{'HTTP_HOST'}.$fn);
$request->content(join('&',map { &escape($_).'='.&escape($form{$_}) } keys %form));
@@ -1322,8 +1319,15 @@ sub clean_filename {
}
# --------------- 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
+# input: $formname - the contents of the file are in $env{"form.$formname"}
+# the desired filenam is in $env{"form.$formname"}
+# $coursedoc - if true up to the current course
+# if false
+# $subdir - directory in userfile to store the file into
+# $parser, $allfiles, $codebase - unknown
+#
+# output: url of file in userspace, or error:
+# or /adm/notfound.html if failure to upload occurse
sub userfileupload {
@@ -1368,6 +1372,10 @@ sub userfileupload {
} else {
my $docuname=$env{'user.name'};
my $docudom=$env{'user.domain'};
+ if (exists($env{'form.group'})) {
+ $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
+ $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
+ }
return &finishuserfileupload($docuname,$docudom,$formname,
$fname,$parser,$allfiles,$codebase);
}
@@ -1393,8 +1401,16 @@ sub finishuserfileupload {
}
# Save the file
{
- open(FH,'>'.$filepath.'/'.$file);
- print FH $env{'form.'.$formname};
+ if (!open(FH,'>'.$filepath.'/'.$file)) {
+ &logthis('Failed to create '.$filepath.'/'.$file);
+ print STDERR ('Failed to create '.$filepath.'/'.$file."\n");
+ return '/adm/notfound.html';
+ }
+ if (!print FH ($env{'form.'.$formname})) {
+ &logthis('Failed to write to '.$filepath.'/'.$file);
+ print STDERR ('Failed to write to '.$filepath.'/'.$file."\n");
+ return '/adm/notfound.html';
+ }
close(FH);
}
if ($parser eq 'parse') {
@@ -2820,7 +2836,7 @@ sub del {
# -------------------------------------------------------------- dump interface
sub dump {
- my ($namespace,$udomain,$uname,$regexp)=@_;
+ my ($namespace,$udomain,$uname,$regexp,$range)=@_;
if (!$udomain) { $udomain=$env{'user.domain'}; }
if (!$uname) { $uname=$env{'user.name'}; }
my $uhome=&homeserver($uname,$udomain);
@@ -2829,16 +2845,23 @@ sub dump {
} else {
$regexp='.';
}
- my $rep=reply("dump:$udomain:$uname:$namespace:$regexp",$uhome);
+ my $rep=reply("dump:$udomain:$uname:$namespace:$regexp:$range",$uhome);
my @pairs=split(/\&/,$rep);
my %returnhash=();
foreach (@pairs) {
- my ($key,$value)=split(/=/,$_);
+ my ($key,$value)=split(/=/,$_,2);
$returnhash{unescape($key)}=&thaw_unescape($value);
}
return %returnhash;
}
+# --------------------------------------------------------- dumpstore interface
+
+sub dumpstore {
+ my ($namespace,$udomain,$uname,$regexp,$range)=@_;
+ return &dump($namespace,$udomain,$uname,$regexp,$range);
+}
+
# -------------------------------------------------------------- keys interface
sub getkeys {
@@ -2980,25 +3003,53 @@ sub newput {
# --------------------------------------------------------- putstore interface
sub putstore {
- my ($namespace,$storehash,$udomain,$uname)=@_;
+ my ($namespace,$symb,$version,$storehash,$udomain,$uname)=@_;
if (!$udomain) { $udomain=$env{'user.domain'}; }
if (!$uname) { $uname=$env{'user.name'}; }
my $uhome=&homeserver($uname,$udomain);
my $items='';
- my %allitems = ();
- foreach (keys %$storehash) {
- if ($_ =~ m/^([^\:]+):([^\:]+):([^\:]+)$/) {
- my $key = $1.':keys:'.$2;
- $allitems{$key} .= $3.':';
- }
- $items.=$_.'='.&freeze_escape($$storehash{$_}).'&';
- }
- foreach (keys %allitems) {
- $allitems{$_} =~ s/\:$//;
- $items.= $_.'='.$allitems{$_}.'&';
+ foreach my $key (keys(%$storehash)) {
+ $items.= &escape($key).'='.&freeze_escape($storehash->{$key}).'&';
}
$items=~s/\&$//;
- return &reply("put:$udomain:$uname:$namespace:$items",$uhome);
+ my $esc_symb=&escape($symb);
+ my $esc_v=&escape($version);
+ my $reply =
+ &reply("putstore:$udomain:$uname:$namespace:$esc_symb:$esc_v:$items",
+ $uhome);
+ if ($reply eq 'unknown_cmd') {
+ # gfall back to way things use to be done
+ return &old_putstore($namespace,$symb,$version,$storehash,$udomain,
+ $uname);
+ }
+ return $reply;
+}
+
+sub old_putstore {
+ my ($namespace,$symb,$version,$storehash,$udomain,$uname)=@_;
+ if (!$udomain) { $udomain=$env{'user.domain'}; }
+ if (!$uname) { $uname=$env{'user.name'}; }
+ my $uhome=&homeserver($uname,$udomain);
+ my %newstorehash;
+ foreach (keys %$storehash) {
+ my $key = $version.':'.&escape($symb).':'.$_;
+ $newstorehash{$key} = $storehash->{$_};
+ }
+ my $items='';
+ my %allitems = ();
+ foreach (keys %newstorehash) {
+ if ($_ =~ m/^([^\:]+):([^\:]+):([^\:]+)$/) {
+ my $key = $1.':keys:'.$2;
+ $allitems{$key} .= $3.':';
+ }
+ $items.=$_.'='.&freeze_escape($newstorehash{$_}).'&';
+ }
+ foreach (keys %allitems) {
+ $allitems{$_} =~ s/\:$//;
+ $items.= $_.'='.$allitems{$_}.'&';
+ }
+ $items=~s/\&$//;
+ return &reply("put:$udomain:$uname:$namespace:$items",$uhome);
}
# ------------------------------------------------------ critical put interface
@@ -3010,7 +3061,7 @@ sub cput {
my $uhome=&homeserver($uname,$udomain);
my $items='';
foreach (keys %$storehash) {
- $items.=escape($_).'='.&freeze_escape($$storehash{$_}).'&';
+ $items.=&escape($_).'='.&freeze_escape($$storehash{$_}).'&';
}
$items=~s/\&$//;
return &critical("put:$udomain:$uname:$namespace:$items",$uhome);
@@ -3121,12 +3172,29 @@ sub allowed {
}
# Free bre access to user's own portfolio contents
- my ($space,$domain,$name,$dir)=split('/',$uri);
+ my ($space,$domain,$name,@dir)=split('/',$uri);
if (($space=~/^(uploaded|editupload)$/) && ($env{'user.name'} eq $name) &&
- ($env{'user.domain'} eq $domain) && ('portfolio' eq $dir)) {
+ ($env{'user.domain'} eq $domain) && ('portfolio' eq $dir[0])) {
return 'F';
}
+# bre access to group if user has rgf priv for this group and course.
+ if (($space=~/^(uploaded|editupload)$/) && ($dir[0] eq 'groups')
+ && ($dir[2] eq 'portfolio') && ($priv eq 'bre')) {
+ if (exists($env{'request.course.id'})) {
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ if (($domain eq $cdom) && ($name eq $cnum)) {
+ my $courseprivid=$env{'request.course.id'};
+ $courseprivid=~s/\_/\//;
+ if ($env{'user.priv.'.$env{'request.role'}.'./'.$courseprivid
+ .'/'.$dir[1]} =~/rgf\&([^\:]*)/) {
+ return $1;
+ }
+ }
+ }
+ }
+
# Free bre to public access
if ($priv eq 'bre') {
@@ -3850,6 +3918,10 @@ sub modify_group_roles {
my $role = 'gr/'.&escape($userprivs);
my ($uname,$udom) = split(/:/,$user);
my $result = &assignrole($udom,$uname,$url,$role,$end,$start);
+ if ($result eq 'ok') {
+ &devalidate_getgroups_cache($udom,$uname,$cdom,$cnum);
+ }
+
return $result;
}
@@ -4651,6 +4723,36 @@ sub GetFileTimestamp {
}
}
+sub stat_file {
+ my ($uri) = @_;
+ $uri = &clutter($uri);
+ my ($udom,$uname,$file,$dir);
+ if ($uri =~ m-^/(uploaded|editupload)/-) {
+ ($udom,$uname,$file) =
+ ($uri =~ m-/(?:uploaded|editupload)/?([^/]*)/?([^/]*)/?(.*)-);
+ $file = 'userfiles/'.$file;
+ $dir = &Apache::loncommon::propath($udom,$uname);
+ }
+ if ($uri =~ m-^/res/-) {
+ ($udom,$uname) =
+ ($uri =~ m-/(?:res)/?([^/]*)/?([^/]*)/-);
+ $file = $uri;
+ }
+
+ if (!$udom || !$uname || !$file) {
+ # unable to handle the uri
+ return ();
+ }
+
+ my ($result) = &dirlist($file,$udom,$uname,$dir);
+ my @stats = split('&', $result);
+ if($stats[0] ne 'empty' && $stats[0] ne 'no_such_dir') {
+ shift(@stats); #filename is first
+ return @stats;
+ }
+ return ();
+}
+
# -------------------------------------------------------- Value of a Condition
# gets the value of a specific preevaluated condition
@@ -4843,8 +4945,8 @@ sub EXT_cache_set {
# --------------------------------------------------------- Value of a Variable
sub EXT {
- my ($varname,$symbparm,$udom,$uname,$usection,$recurse)=@_;
+ my ($varname,$symbparm,$udom,$uname,$usection,$recurse)=@_;
unless ($varname) { return ''; }
#get real user name/domain, courseid and symb
my $courseid;
@@ -4958,10 +5060,21 @@ sub EXT {
return $env{'course.'.$courseid.'.'.$spacequalifierrest};
} elsif ($realm eq 'resource') {
- my $section;
if (defined($courseid) && $courseid eq $env{'request.course.id'}) {
if (!$symbparm) { $symbparm=&symbread(); }
}
+
+ if ($space eq 'title') {
+ if (!$symbparm) { $symbparm = $env{'request.filename'}; }
+ return &gettitle($symbparm);
+ }
+
+ if ($space eq 'map') {
+ my ($map) = &decode_symb($symbparm);
+ return &symbread($map);
+ }
+
+ my ($section, $group, @groups);
my ($courselevelm,$courselevel);
if ($symbparm && defined($courseid) &&
$courseid eq $env{'request.course.id'}) {
@@ -4970,7 +5083,7 @@ sub EXT {
# ----------------------------------------------------- Cascading lookup scheme
my $symbp=$symbparm;
- my $mapp=&deversion((&decode_symb($symbp))[0]);
+ my $mapp=(&decode_symb($symbp))[0];
my $symbparm=$symbp.'.'.$spacequalifierrest;
my $mapparm=$mapp.'___(all).'.$spacequalifierrest;
@@ -4978,12 +5091,20 @@ sub EXT {
if (($env{'user.name'} eq $uname) &&
($env{'user.domain'} eq $udom)) {
$section=$env{'request.course.sec'};
+ @groups=&sort_course_groups($env{'request.course.groups'},$courseid);
+ if (@groups > 0) {
+ @groups = sort(@groups);
+ }
} else {
if (! defined($usection)) {
$section=&getsection($udom,$uname,$courseid);
} else {
$section = $usection;
}
+ my $grouplist = &get_users_groups($udom,$uname,$courseid);
+ if ($grouplist) {
+ @groups=&sort_course_groups($grouplist,$courseid);
+ }
}
my $seclevel=$courseid.'.['.$section.'].'.$spacequalifierrest;
@@ -4999,12 +5120,17 @@ sub EXT {
my $userreply=&resdata($uname,$udom,'user',
($courselevelr,$courselevelm,
$courselevel));
-
if (defined($userreply)) { return $userreply; }
# ------------------------------------------------ second, check some of course
+ my $coursereply;
+ if (@groups > 0) {
+ $coursereply = &check_group_parms($courseid,\@groups,$symbparm,
+ $mapparm,$spacequalifierrest);
+ if (defined($coursereply)) { return $coursereply; }
+ }
- my $coursereply=&resdata($env{'course.'.$courseid.'.num'},
+ $coursereply=&resdata($env{'course.'.$courseid.'.num'},
$env{'course.'.$courseid.'.domain'},
'course',
($seclevelr,$seclevelm,$seclevel,
@@ -5084,6 +5210,32 @@ sub EXT {
return '';
}
+sub check_group_parms {
+ my ($courseid,$groups,$symbparm,$mapparm,$what) = @_;
+ my @groupitems = ();
+ my $resultitem;
+ my @levels = ($symbparm,$mapparm,$what);
+ foreach my $group (@{$groups}) {
+ foreach my $level (@levels) {
+ my $item = $courseid.'.['.$group.'].'.$level;
+ push(@groupitems,$item);
+ }
+ }
+ my $coursereply = &resdata($env{'course.'.$courseid.'.num'},
+ $env{'course.'.$courseid.'.domain'},
+ 'course',@groupitems);
+ return $coursereply;
+}
+
+sub sort_course_groups { # Sort groups based on defined rankings. Default is sort().
+ my ($grouplist,$courseid) = @_;
+ my @groups = split/:/,$grouplist;
+ if (@groups > 1) {
+ @groups = sort(@groups);
+ }
+ return @groups;
+}
+
sub packages_tab_default {
my ($uri,$varname)=@_;
my (undef,$part,$name)=split(/\./,$varname);
@@ -5432,9 +5584,12 @@ sub symblist {
if (($env{'request.course.fn'}) && (%newhash)) {
if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
&GDBM_WRCREAT(),0640)) {
- foreach (keys %newhash) {
- $hash{declutter($_)}=&encode_symb($mapname,$newhash{$_}->[1],
- $newhash{$_}->[0]);
+ foreach my $url (keys %newhash) {
+ next if ($url eq 'last_known'
+ && $env{'form.no_update_last_known'});
+ $hash{declutter($url)}=&encode_symb($mapname,
+ $newhash{$url}->[1],
+ $newhash{$url}->[0]);
}
if (untie(%hash)) {
return 'ok';
@@ -6281,7 +6436,7 @@ sub clutter {
&& $thisfn!~/\.(sequence|page)$/) {
$thisfn='/adm/coursedocs/showdoc'.$thisfn;
} else {
- #&logthis("Got a blank emb style");
+ &logthis("Got a blank emb style");
}
}
}
@@ -6428,7 +6583,7 @@ BEGIN {
}
close($config);
# FIXME: dev server don't want this, production servers _do_ want this
- &get_iphost();
+ #&get_iphost();
}
sub get_iphost {
@@ -7102,6 +7257,27 @@ all args are optional
=item *
+dumpstore($namespace,$udom,$uname,$regexp,$range) :
+dumps the complete (or key matching regexp) namespace into a hash
+($udom, $uname, $regexp, $range are optional) for a namespace that is
+normally &store()ed into
+
+$range should be either an integer '100' (give me the first 100
+ matching records)
+ or be two integers sperated by a - with no spaces
+ '30-50' (give me the 30th through the 50th matching
+ records)
+
+
+=item *
+
+putstore($namespace,$symb,$version,$storehash,$udomain,$uname) :
+replaces a &store() version of data with a replacement set of data
+for a particular resource in a namespace passed in the $storehash hash
+reference
+
+=item *
+
tmpstore($storehash,$symb,$namespace,$udom,$uname) : storage that
works very similar to store/cstore, but all data is stored in a
temporary location and can be reset using tmpreset, $storehash should
@@ -7131,10 +7307,15 @@ namesp ($udom and $uname are optional)
=item *
-dump($namespace,$udom,$uname,$regexp) :
+dump($namespace,$udom,$uname,$regexp,$range) :
dumps the complete (or key matching regexp) namespace into a hash
-($udom, $uname and $regexp are optional)
+($udom, $uname, $regexp, $range are optional)
+$range should be either an integer '100' (give me the first 100
+ matching records)
+ or be two integers sperated by a - with no spaces
+ '30-50' (give me the 30th through the 50th matching
+ records)
=item *
inc($namespace,$store,$udom,$uname) : increments $store in $namespace.
@@ -7150,17 +7331,6 @@ put($namespace,$storehash,$udom,$uname)
=item *
-putstore($namespace,$storehash,$udomain,$uname) : stores hash in namesp
-keys used in storehash include version information (e.g., 1:$symb:message etc.) as
-used in records written by &store and retrieved by &restore. This function
-was created for use in editing discussion posts, without incrementing the
-version number included in the key for a particular post. The colon
-separated list of attribute names (e.g., the value associated with the key
-1:keys:$symb) is also generated and passed in the ampersand separated
-items sent to lonnet::reply().
-
-=item *
-
cput($namespace,$storehash,$udom,$uname) : critical put
($udom and $uname are optional)
@@ -7290,6 +7460,16 @@ getfile($file,$caller) : two cases - req
- returns the entire contents of a file or -1;
it properly subscribes to and replicates the file if neccessary.
+
+=item *
+
+stat_file($url) : $url is expected to be a /res/ or /uploaded/ style file
+ reference
+
+returns either a stat() list of data about the file or an empty list
+if the file doesn't exist or couldn't find out about it (connection
+problems or user unknown)
+
=item *
filelocation($dir,$file) : returns file system location of a file