--- loncom/lonnet/perl/lonnet.pm	2001/08/18 14:17:50	1.152
+++ loncom/lonnet/perl/lonnet.pm	2001/10/02 18:32:56	1.160
@@ -72,7 +72,12 @@
 # EXT(name)          : value of a variable
 # symblist(map,hash) : Updates symbolic storage links
 # symbread([filename]) : returns the data handle (filename optional)
-# rndseed()          : returns a random seed 
+# rndseed([symb,courseid,domain,uname])
+#                    : returns a random seed, all arguments are optional,
+#                      if they aren't sent it use the environment to derive
+#                      them
+#                      Note: if symb isn't sent and it can't get one from
+#                      &symbread it will use the current time as it's return
 # receipt()          : returns a receipt to be given out to users 
 # getfile(filename)  : returns the contents of filename, or a -1 if it can't
 #                      be found, replicates and subscribes to the file
@@ -122,7 +127,8 @@
 # 5/30 H. K. Ng
 # 6/1 Gerd Kortemeyer
 # July Guy Albertelli
-# 8/4,8/7,8/8,8/9,8/11,8/16,8/17,8/18 Gerd Kortemeyer
+# 8/4,8/7,8/8,8/9,8/11,8/16,8/17,8/18,8/20,8/23,9/20,9/21,9/26,
+# 10/2 Gerd Kortemeyer
 
 package Apache::lonnet;
 
@@ -131,7 +137,7 @@ use Apache::File;
 use LWP::UserAgent();
 use HTTP::Headers;
 use vars 
-qw(%perlvar %hostname %homecache %hostip %spareid %hostdom %libserv %pr %prp %fe %fd $readit %metacache %packagetab);
+qw(%perlvar %hostname %homecache %hostip %spareid %hostdom %libserv %pr %prp %fe %fd $readit %metacache %packagetab %courselogs);
 use IO::Socket;
 use GDBM_File;
 use Apache::Constants qw(:common :http);
@@ -660,6 +666,56 @@ sub log {
     return critical("log:$dom:$nam:$what",$hom);
 }
 
+# ------------------------------------------------------------------ Course Log
+
+sub flushcourselogs {
+    &logthis('Flushing course log buffers');
+    map {
+        my $crsid=$_;
+        if (&reply('log:'.$ENV{'course.'.$crsid.'.domain'}.':'.
+		          $ENV{'course.'.$crsid.'.num'}.':'.
+		           &escape($courselogs{$crsid}),
+		          $ENV{'course.'.$crsid.'.home'}) eq 'ok') {
+	    delete $courselogs{$crsid};
+        } else {
+            &logthis('Failed to flush log buffer for '.$crsid);
+            if (length($courselogs{$crsid})>40000) {
+               &logthis("<font color=blue>WARNING: Buffer for ".$crsid.
+                        " exceeded maximum size, deleting.</font>");
+               delete $courselogs{$crsid};
+            }
+        }        
+    } keys %courselogs;
+}
+
+sub courselog {
+    my $what=shift;
+    $what=time.':'.$what;
+    unless ($ENV{'request.course.id'}) { return ''; }
+    if (defined $courselogs{$ENV{'request.course.id'}}) {
+	$courselogs{$ENV{'request.course.id'}}.='&'.$what;
+    } else {
+	$courselogs{$ENV{'request.course.id'}}.=$what;
+    }
+    if (length($courselogs{$ENV{'request.course.id'}})>4048) {
+	&flushcourselogs();
+    }
+}
+
+sub courseacclog {
+    my $fnsymb=shift;
+    unless ($ENV{'request.course.id'}) { return ''; }
+    my $what=$fnsymb.':'.$ENV{'user.name'}.':'.$ENV{'user.domain'};
+    if ($what=~/(problem|exam|quiz|assess|survey|form)$/) {
+	map {
+            if ($_=~/^form\.(.*)/) {
+		$what.=':'.$1.'='.$ENV{$_};
+            }
+        } keys %ENV;
+    }
+    &courselog($what);
+}
+
 # ----------------------------------------------------------- Check out an item
 
 sub checkout {
@@ -683,9 +739,9 @@ sub checkout {
     $token=~s/^(\d+)\_.*\_(\d+)$/$1\*$2\*$lonhost/;
     $token=~tr/a-z/A-Z/;
 
-    my %infohash=('outtoken' => $token,
-                  'checkouttime' => $now,
-                  'outremote' => $ENV{'REMOTE_ADDR'});
+    my %infohash=('resource.0.outtoken' => $token,
+                  'resource.0.checkouttime' => $now,
+                  'resource.0.outremote' => $ENV{'REMOTE_ADDR'});
 
     unless (&cstore(\%infohash,$symb,$tcrsid,$tudom,$tuname) eq 'ok') {
        return '';
@@ -719,9 +775,20 @@ sub checkin {
     my ($tuname,$tudom,$tcrsid,$symb,$chtim,$rmaddr)=
                  split(/\&/,&unescape(&reply('tmpget:'.$dtoken,$lonhost)));
 
-    my %infohash=('intoken' => $token,
-                  'checkintime' => $now,
-                  'inremote' => $ENV{'REMOTE_ADDR'});
+    unless (($tuname) && ($tudom)) {
+        &logthis('Check in '.$token.' ('.$dtoken.') failed');
+        return '';
+    }
+    
+    unless (&allowed('mgr',$tcrsid)) {
+        &logthis('Check in '.$token.' ('.$dtoken.') unauthorized: '.
+                 $ENV{'user.name'}.' - '.$ENV{'user.domain'});
+        return '';
+    }
+
+    my %infohash=('resource.0.intoken' => $token,
+                  'resource.0.checkintime' => $now,
+                  'resource.0.inremote' => $ENV{'REMOTE_ADDR'});
 
     unless (&cstore(\%infohash,$symb,$tcrsid,$tudom,$tuname) eq 'ok') {
        return '';
@@ -1121,6 +1188,12 @@ sub allowed {
 	return 'F';
     }
 
+# Free bre to public access
+
+    if ($priv eq 'bre') {
+	if (&metadata($uri,'copyright') eq 'public') { return 'F'; }
+    }
+
     my $thisallowed='';
     my $statecond=0;
     my $courseprivid='';
@@ -1193,6 +1266,7 @@ sub allowed {
                 map {
 		    if ($_=~/^httpref\..*\*/) {
 			my $pattern=$_;
+                        $pattern=~s/^httpref\.\/res\///;
                         $pattern=~s/\*/\[\^\/\]\+/g;
                         $pattern=~s/\//\\\//g;
                         if ($orguri=~/$pattern/) {
@@ -1559,7 +1633,7 @@ sub modifystudent {
 	return 'error: no such user';
     }
 # -------------------------------------------------- Add student to course list
-    my $reply=critical('put:'.$ENV{'course.'.$cid.'.domain'}.':'.
+    $reply=critical('put:'.$ENV{'course.'.$cid.'.domain'}.':'.
 	              $ENV{'course.'.$cid.'.num'}.':classlist:'.
                       &escape($uname.':'.$udom).'='.
                       &escape($end.':'.$start),
@@ -1624,7 +1698,7 @@ sub createcourse {
     my $reply=&reply('encrypt:makeuser:'.$udom.':'.$uname.':none::',
                       $ENV{'user.home'});
     unless ($reply eq 'ok') { return 'error: '.$reply; }
-    my $uhome=&homeserver($uname,$udom);
+    $uhome=&homeserver($uname,$udom);
     if (($uhome eq '') || ($uhome eq 'no_host')) { 
 	return 'error: no such course';
     }
@@ -2133,16 +2207,21 @@ sub numval {
 }    
 
 sub rndseed {
-    my $symb;
-    unless ($symb=&symbread()) { return time; }
-    { 
+    my ($symb,$courseid,$domain,$username)=@_;
+    if (!$symb) {
+      unless ($symb=&symbread()) { return time; }
+    }
+    if (!$courseid) { $courseid=$ENV{'request.course.id'};}
+    if (!$domain) {$domain=$ENV{'user.domain'};}
+    if (!$username) {$username=$ENV{'user.name'};}
+    {
       use integer;
       my $symbchck=unpack("%32C*",$symb) << 27;
       my $symbseed=numval($symb) << 22;
-      my $namechck=unpack("%32C*",$ENV{'user.name'}) << 17;
-      my $nameseed=numval($ENV{'user.name'}) << 12;
-      my $domainseed=unpack("%32C*",$ENV{'user.domain'}) << 7;
-      my $courseseed=unpack("%32C*",$ENV{'request.course.id'});
+      my $namechck=unpack("%32C*",$username) << 17;
+      my $nameseed=numval($username) << 12;
+      my $domainseed=unpack("%32C*",$domain) << 7;
+      my $courseseed=unpack("%32C*",$courseid);
       my $num=$symbseed+$nameseed+$domainseed+$courseseed+$namechck+$symbchck;
       #uncommenting these lines can break things!
       #&Apache::lonxml::debug("$symbseed:$nameseed;$domainseed|$courseseed;$namechck:$symbchck");
@@ -2245,7 +2324,7 @@ sub unescape {
 # ================================================================ Main Program
 
 sub BEGIN {
-if ($readit ne 'done') {
+unless ($readit) {
 # ------------------------------------------------------------ Read access.conf
 {
     my $config=Apache::File->new("/etc/httpd/conf/access.conf");
@@ -2264,6 +2343,7 @@ if ($readit ne 'done') {
     my $config=Apache::File->new("$perlvar{'lonTabDir'}/hosts.tab");
 
     while (my $configline=<$config>) {
+       chomp($configline);
        my ($id,$domain,$role,$name,$ip)=split(/:/,$configline);
        $hostname{$id}=$name;
        $hostdom{$id}=$domain;
@@ -2289,8 +2369,10 @@ if ($readit ne 'done') {
 
     while (my $configline=<$config>) {
        chomp($configline);
+      if ($configline) {
        my ($role,$perm)=split(/ /,$configline);
        if ($perm ne '') { $pr{$role}=$perm; }
+      }
     }
 }
 
@@ -2300,8 +2382,10 @@ if ($readit ne 'done') {
 
     while (my $configline=<$config>) {
        chomp($configline);
+      if ($configline) {
        my ($short,$plain)=split(/:/,$configline);
        if ($plain ne '') { $prp{$short}=$plain; }
+      }
     }
 }