Diff for /loncom/lonnet/perl/lonnet.pm between versions 1.477 and 1.530

version 1.477, 2004/03/16 20:15:08 version 1.530, 2004/08/24 06:43:21
Line 32  package Apache::lonnet; Line 32  package Apache::lonnet;
 use strict;  use strict;
 use LWP::UserAgent();  use LWP::UserAgent();
 use HTTP::Headers;  use HTTP::Headers;
   use HTTP::Date;
   # use Date::Parse;
 use vars   use vars 
 qw(%perlvar %hostname %homecache %badServerCache %hostip %iphost %spareid %hostdom   qw(%perlvar %hostname %homecache %badServerCache %hostip %iphost %spareid %hostdom 
    %libserv %pr %prp %metacache %packagetab %titlecache %courseresversioncache %resversioncache     %libserv %pr %prp %metacache %packagetab %titlecache %courseresversioncache %resversioncache
    %courselogs %accesshash %userrolehash $processmarker $dumpcount      %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      %userresdatacache %usectioncache %domaindescription %domain_auth_def %domain_auth_arg_def 
    %domain_lang_def %domain_city %domain_longi %domain_lati $tmpdir);     %domain_lang_def %domain_city %domain_longi %domain_lati $tmpdir);
   
Line 432  sub overloaderror { Line 434  sub overloaderror {
     if ($overload>0) {      if ($overload>0) {
  $r->err_headers_out->{'Retry-After'}=$overload;   $r->err_headers_out->{'Retry-After'}=$overload;
         $r->log_error('Overload of '.$overload.' on '.$checkserver);          $r->log_error('Overload of '.$overload.' on '.$checkserver);
         return 413;          return 409;
     }          }    
     return '';      return '';
 }  }
Line 615  sub idput { Line 617  sub idput {
     my ($udom,%ids)=@_;      my ($udom,%ids)=@_;
     my %servers=();      my %servers=();
     foreach (keys %ids) {      foreach (keys %ids) {
    &cput('environment',{'id'=>$ids{$_}},$udom,$_);
         my $uhom=&homeserver($_,$udom);          my $uhom=&homeserver($_,$udom);
         if ($uhom ne 'no_host') {          if ($uhom ne 'no_host') {
             my $id=&escape($ids{$_});              my $id=&escape($ids{$_});
Line 625  sub idput { Line 628  sub idput {
             } else {              } else {
                 $servers{$uhom}=$id.'='.$unam;                  $servers{$uhom}=$id.'='.$unam;
             }              }
             &critical('put:'.$udom.':'.$unam.':environment:id='.$id,$uhom);  
         }          }
     }      }
     foreach (keys %servers) {      foreach (keys %servers) {
Line 640  sub assign_access_key { Line 642  sub assign_access_key {
 # a valid key looks like uname:udom#comments  # a valid key looks like uname:udom#comments
 # comments are being appended  # comments are being appended
 #  #
     my ($ckey,$cdom,$cnum,$udom,$uname,$logentry)=@_;      my ($ckey,$kdom,$knum,$cdom,$cnum,$udom,$uname,$logentry)=@_;
       $kdom=
      $ENV{'course.'.$ENV{'request.course.id'}.'.domain'} unless (defined($kdom));
       $knum=
      $ENV{'course.'.$ENV{'request.course.id'}.'.num'} unless (defined($knum));
     $cdom=      $cdom=
    $ENV{'course.'.$ENV{'request.course.id'}.'.domain'} unless (defined($cdom));     $ENV{'course.'.$ENV{'request.course.id'}.'.domain'} unless (defined($cdom));
     $cnum=      $cnum=
    $ENV{'course.'.$ENV{'request.course.id'}.'.num'} unless (defined($cnum));     $ENV{'course.'.$ENV{'request.course.id'}.'.num'} unless (defined($cnum));
     $udom=$ENV{'user.name'} unless (defined($udom));      $udom=$ENV{'user.name'} unless (defined($udom));
     $uname=$ENV{'user.domain'} unless (defined($uname));      $uname=$ENV{'user.domain'} unless (defined($uname));
     my %existing=&get('accesskeys',[$ckey],$cdom,$cnum);      my %existing=&get('accesskeys',[$ckey],$kdom,$knum);
     if (($existing{$ckey}=~/^\#(.*)$/) || # - new key      if (($existing{$ckey}=~/^\#(.*)$/) || # - new key
         ($existing{$ckey}=~/^$uname\:$udom\#(.*)$/)) {           ($existing{$ckey}=~/^\Q$uname\E\:\Q$udom\E\#(.*)$/)) { 
                                                   # assigned to this person                                                    # assigned to this person
                                                   # - this should not happen,                                                    # - this should not happen,
                                                   # unless something went wrong                                                    # unless something went wrong
                                                   # the first time around                                                    # the first time around
 # ready to assign  # ready to assign
         $logentry=$1.'; '.$logentry;          $logentry=$1.'; '.$logentry;
         if (&put('accesskey',{$ckey=>$uname.':'.$udom.'#'.$logentry},          if (&put('accesskeys',{$ckey=>$uname.':'.$udom.'#'.$logentry},
                                                  $cdom,$cnum) eq 'ok') {                                                   $kdom,$knum) eq 'ok') {
 # key now belongs to user  # key now belongs to user
     my $envkey='key.'.$cdom.'_'.$cnum;      my $envkey='key.'.$cdom.'_'.$cnum;
             if (&put('environment',{$envkey => $ckey}) eq 'ok') {              if (&put('environment',{$envkey => $ckey}) eq 'ok') {
Line 753  sub validate_access_key { Line 759  sub validate_access_key {
    $ENV{'course.'.$ENV{'request.course.id'}.'.domain'} unless (defined($cdom));     $ENV{'course.'.$ENV{'request.course.id'}.'.domain'} unless (defined($cdom));
     $cnum=      $cnum=
    $ENV{'course.'.$ENV{'request.course.id'}.'.num'} unless (defined($cnum));     $ENV{'course.'.$ENV{'request.course.id'}.'.num'} unless (defined($cnum));
     $udom=$ENV{'user.name'} unless (defined($udom));      $udom=$ENV{'user.domain'} unless (defined($udom));
     $uname=$ENV{'user.domain'} unless (defined($uname));      $uname=$ENV{'user.name'} unless (defined($uname));
     my %existing=&get('accesskeys',[$ckey],$cdom,$cnum);      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  # ------------------------------------- Find the section of student in a course
Line 784  sub getsection { Line 790  sub getsection {
                         &homeserver($unam,$udom)))) {                          &homeserver($unam,$udom)))) {
         my ($key,$value)=split(/\=/,$_);          my ($key,$value)=split(/\=/,$_);
         $key=&unescape($key);          $key=&unescape($key);
         next if ($key !~/^$courseid(?:\/)*(\w+)*\_st$/);          next if ($key !~/^\Q$courseid\E(?:\/)*(\w+)*\_st$/);
         my $section=$1;          my $section=$1;
         if ($key eq $courseid.'_st') { $section=''; }          if ($key eq $courseid.'_st') { $section=''; }
         my ($dummy,$end,$start)=split(/\_/,&unescape($value));          my ($dummy,$end,$start)=split(/\_/,&unescape($value));
Line 963  sub usection { Line 969  sub usection {
                         &homeserver($unam,$udom)))) {                          &homeserver($unam,$udom)))) {
         my ($key,$value)=split(/\=/,$_);          my ($key,$value)=split(/\=/,$_);
         $key=&unescape($key);          $key=&unescape($key);
         if ($key=~/^$courseid(?:\/)*(\w+)*\_st$/) {          if ($key=~/^\Q$courseid\E(?:\/)*(\w+)*\_st$/) {
             my $section=$1;              my $section=$1;
             if ($key eq $courseid.'_st') { $section=''; }              if ($key eq $courseid.'_st') { $section=''; }
     my ($dummy,$end,$start)=split(/\_/,&unescape($value));      my ($dummy,$end,$start)=split(/\_/,&unescape($value));
Line 1125  sub ssi_body { Line 1131  sub ssi_body {
     my ($filelink,%form)=@_;      my ($filelink,%form)=@_;
     my $output=($filelink=~/^http\:/?&externalssi($filelink):      my $output=($filelink=~/^http\:/?&externalssi($filelink):
                                      &ssi($filelink,%form));                                       &ssi($filelink,%form));
     $output=~s/^.*?\<body[^\>]*\>//si;  
     $output=~s/(.*)\<\/body\s*\>.*?$/$1/si;  
     $output=~      $output=~
             s/\/\/ BEGIN LON\-CAPA Internal.+\/\/ END LON\-CAPA Internal\s//gs;              s/\/\/ BEGIN LON\-CAPA Internal.+\/\/ END LON\-CAPA Internal\s//gs;
       $output=~s/^.*?\<body[^\>]*\>//si;
       $output=~s/(.*)\<\/body\s*\>.*?$/$1/si;
     return $output;      return $output;
 }  }
   
Line 1163  sub externalssi { Line 1169  sub externalssi {
     return $response->content;      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 tokenwrapper {  sub allowuploaded {
     my $uri=shift;      my ($srcurl,$url)=@_;
     $uri=~s/^http\:\/\/([^\/]+)//;      $url=&clutter(&declutter($url));
     $uri=~s/^\///;      my $dir=$url;
     $ENV{'user.environment'}=~/\/([^\/]+)\.id/;      $dir=~s/\/[^\/]+$//;
     my $token=$1;      my %httpref=();
 #    if ($uri=~/^uploaded\/([^\/]+)\/([^\/]+)\/([^\/]+)(\?\.*)*$/) {      my $httpurl=&hreflocation('',$url);
     if ($uri=~/^uploaded\/([^\/]+)\/([^\/]+)\/(.+)(\?\.*)*$/) {      $httpref{'httpref.'.$httpurl}=$srcurl;
  &appenv('userfile.'.$1.'/'.$2.'/'.$3 => $ENV{'request.course.id'});      &Apache::lonnet::appenv(%httpref);
         return 'http://'.$hostname{ &homeserver($2,$1)}.'/'.$uri.  }
                (($uri=~/\?/)?'&':'?').'token='.$token.  
                                '&tokenissued='.$perlvar{'lonHostID'};  # --------- File operations in /home/httpd/html/userfiles/$domain/1/2/3/$course
     } else {  # input: action, courseID, current domain, home server for course, intended
  return '/adm/notfound.html';  #        path to file, source of file.
     }  # 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.
   #
   # 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.
   #
   # action = uploaddoc - /home/httpd/html/userfiles/$domain/1/2/3/$course/$file
   #         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.
   
 # --------------- 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/1/2/3/$course/userfiles/$file in  
 # course's home server.  
   
 sub process_coursefile {  sub process_coursefile {
     my ($action,$docuname,$docudom,$docuhome,$file,$source)=@_;      my ($action,$docuname,$docudom,$docuhome,$file,$source)=@_;
Line 1203  sub process_coursefile { Line 1215  sub process_coursefile {
     if ($action eq 'propagate') {      if ($action eq 'propagate') {
         $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file          $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file
                             ,$docuhome);                              ,$docuhome);
     } elsif ($action eq 'copy') {      } else {
         my $fetchresult = '';          my $fetchresult = '';
         my $fpath = '';          my $fpath = '';
         my $fname = $file;          my $fname = $file;
         ($fpath,$fname) = ($file =~ m/^(.*)\/([^\/]+)$/);          ($fpath,$fname) = ($file =~ m|^(.*)/([^/]+)$|);
         $fpath=$docudom.'/'.$docuname.'/'.$fpath;          $fpath=$docudom.'/'.$docuname.'/'.$fpath;
         my $filepath=$perlvar{'lonDocRoot'}.'/userfiles';          my $filepath=$perlvar{'lonDocRoot'}.'/userfiles';
         unless ($fpath eq '') {          unless ($fpath eq '') {
             my @parts=split(/\//,$fpath);              my @parts=split('/',$fpath);
             foreach my $part (@parts) {              foreach my $part (@parts) {
                 $filepath.= '/'.$part;                  $filepath.= '/'.$part;
                 if ((-e $filepath)!=1) {                  if ((-e $filepath)!=1) {
Line 1219  sub process_coursefile { Line 1231  sub process_coursefile {
                 }                  }
             }              }
         }          }
         if ($source eq '') {          if ($action eq 'copy') {
             $fetchresult = 'no source file';              if ($source eq '') {
         } else {                  $fetchresult = 'no source file';
             my $destination = $filepath.'/'.$fname;                  return $fetchresult;
             print STDERR "Getting ready to rename $source to $destination\n";              } else {
             rename($source,$destination);                  my $destination = $filepath.'/'.$fname;
                   rename($source,$destination);
                   $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file,
                                    $docuhome);
               }
           } elsif ($action eq 'uploaddoc') {
               open(my $fh,'>'.$filepath.'/'.$fname);
               print $fh $ENV{'form.'.$source};
               close($fh);
             $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file,              $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file,
                                  $docuhome);                                   $docuhome);
               if ($fetchresult eq 'ok') {
                   return '/uploaded/'.$fpath.'/'.$fname;
               } else {
                   &logthis('Failed to transfer '.$docudom.'/'.$docuname.'/'.$file.
                           ' to host '.$docuhome.': '.$fetchresult);
                   return '/adm/notfound.html';
               }
         }          }
     }      }
     unless ( ($fetchresult eq 'ok') || ($fetchresult eq 'no source file') ) {      unless ( $fetchresult eq 'ok') {
         &logthis('Failed to transfer '.$docudom.'/'.$docuname.'/'.$file.          &logthis('Failed to transfer '.$docudom.'/'.$docuname.'/'.$file.
              ' to host '.$docuhome.': '.$fetchresult);               ' to host '.$docuhome.': '.$fetchresult);
     }      }
Line 1241  sub process_coursefile { Line 1268  sub process_coursefile {
 # output: url of file in userspace  # output: url of file in userspace
   
 sub userfileupload {  sub userfileupload {
     my ($formname,$coursedoc)=@_;      my ($formname,$coursedoc,$subdir)=@_;
       if (!defined($subdir)) { $subdir='unknown'; }
     my $fname=$ENV{'form.'.$formname.'.filename'};      my $fname=$ENV{'form.'.$formname.'.filename'};
 # Replace Windows backslashes by forward slashes  # Replace Windows backslashes by forward slashes
     $fname=~s/\\/\//g;      $fname=~s/\\/\//g;
Line 1254  sub userfileupload { Line 1282  sub userfileupload {
 # See if there is anything left  # See if there is anything left
     unless ($fname) { return 'error: no uploaded file'; }      unless ($fname) { return 'error: no uploaded file'; }
     chop($ENV{'form.'.$formname});      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  # Create the directory if not present
     my $docuname='';      my $docuname='';
     my $docudom='';      my $docudom='';
     my $docuhome='';      my $docuhome='';
       $fname="$subdir/$fname";
     if ($coursedoc) {      if ($coursedoc) {
  $docuname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'};   $docuname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'};
  $docudom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};   $docudom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
  $docuhome=$ENV{'course.'.$ENV{'request.course.id'}.'.home'};   $docuhome=$ENV{'course.'.$ENV{'request.course.id'}.'.home'};
           if ($ENV{'form.folder'} =~ m/^default/) {
               return &finishuserfileupload($docuname,$docudom,$docuhome,$formname,$fname);
           } else {
               $fname=$ENV{'form.folder'}.'/'.$fname;
               return &process_coursefile('uploaddoc',$docuname,$docudom,$docuhome,$fname,$formname);
           }
     } else {      } else {
         $docuname=$ENV{'user.name'};          $docuname=$ENV{'user.name'};
         $docudom=$ENV{'user.domain'};          $docudom=$ENV{'user.domain'};
         $docuhome=$ENV{'user.home'};          $docuhome=$ENV{'user.home'};
           return &finishuserfileupload($docuname,$docudom,$docuhome,$formname,$fname);
     }      }
     return   
         &finishuserfileupload($docuname,$docudom,$docuhome,$formname,$fname);  
 }  }
   
 sub finishuserfileupload {  sub finishuserfileupload {
     my ($docuname,$docudom,$docuhome,$formname,$fname)=@_;      my ($docuname,$docudom,$docuhome,$formname,$fname)=@_;
     my $path=$docudom.'/'.$docuname.'/';      my $path=$docudom.'/'.$docuname.'/';
     my $filepath=$perlvar{'lonDocRoot'};      my $filepath=$perlvar{'lonDocRoot'};
       my ($fnamepath,$file);
       $file=$fname;
       if ($fname=~m|/|) {
           ($fnamepath,$file) = ($fname =~ m|^(.*)/([^/]+)$|);
    $path.=$fnamepath.'/';
       }
     my @parts=split(/\//,$filepath.'/userfiles/'.$path);      my @parts=split(/\//,$filepath.'/userfiles/'.$path);
     my $count;      my $count;
     for ($count=4;$count<=$#parts;$count++) {      for ($count=4;$count<=$#parts;$count++) {
Line 1285  sub finishuserfileupload { Line 1341  sub finishuserfileupload {
     }      }
 # Save the file  # Save the file
     {      {
        open(my $fh,'>'.$filepath.'/'.$fname);   #&Apache::lonnet::logthis("Saving to $filepath $file");
          open(my $fh,'>'.$filepath.'/'.$file);
        print $fh $ENV{'form.'.$formname};         print $fh $ENV{'form.'.$formname};
        close($fh);         close($fh);
     }      }
 # Notify homeserver to grep it  # Notify homeserver to grep it
 #  #
     my $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$fname,      my $fetchresult= &reply('fetchuserfile:'.$path.$file,$docuhome);
     $docuhome);  
     if ($fetchresult eq 'ok') {      if ($fetchresult eq 'ok') {
 #  #
 # Return the URL to it  # Return the URL to it
         return '/uploaded/'.$path.$fname;          return '/uploaded/'.$path.$file;
     } else {      } else {
         &logthis('Failed to transfer '.$docudom.'/'.$docuname.'/'.$fname.          &logthis('Failed to transfer '.$path.$file.' to host '.$docuhome.
          ' to host '.$docuhome.': '.$fetchresult);   ': '.$fetchresult);
         return '/adm/notfound.html';          return '/adm/notfound.html';
     }          }    
 }  }
   
   sub removeuploadedurl {
       my ($url)=@_;
       my (undef,undef,$udom,$uname,$fname)=split('/',$url,5);
       return &Apache::lonnet::removeuserfile($uname,$udom,$fname);
   }
   
   sub removeuserfile {
       my ($docuname,$docudom,$fname)=@_;
       my $home=&homeserver($docuname,$docudom);
       return &reply("removeuserfile:$docudom/$docuname/$fname",$home);
   }
   
   sub mkdiruserfile {
       my ($docuname,$docudom,$dir)=@_;
       my $home=&homeserver($docuname,$docudom);
       return &reply("mkdiruserfile:".&escape("$docudom/$docuname/$dir"),$home);
   }
   
 # ------------------------------------------------------------------------- Log  # ------------------------------------------------------------------------- Log
   
 sub log {  sub log {
Line 1343  sub flushcourselogs { Line 1417  sub flushcourselogs {
         }          }
         if ($courseidbuffer{$coursehombuf{$crsid}}) {          if ($courseidbuffer{$coursehombuf{$crsid}}) {
            $courseidbuffer{$coursehombuf{$crsid}}.='&'.             $courseidbuffer{$coursehombuf{$crsid}}.='&'.
  &escape($crsid).'='.&escape($coursedescrbuf{$crsid});   &escape($crsid).'='.&escape($coursedescrbuf{$crsid}).
                            '='.&escape($courseinstcodebuf{$crsid});
         } else {          } else {
            $courseidbuffer{$coursehombuf{$crsid}}=             $courseidbuffer{$coursehombuf{$crsid}}=
  &escape($crsid).'='.&escape($coursedescrbuf{$crsid});   &escape($crsid).'='.&escape($coursedescrbuf{$crsid}).
                            '='.&escape($courseinstcodebuf{$crsid});
         }              }    
     }      }
 #  #
Line 1420  sub courselog { Line 1496  sub courselog {
        $ENV{'course.'.$ENV{'request.course.id'}.'.home'};         $ENV{'course.'.$ENV{'request.course.id'}.'.home'};
     $coursedescrbuf{$ENV{'request.course.id'}}=      $coursedescrbuf{$ENV{'request.course.id'}}=
        $ENV{'course.'.$ENV{'request.course.id'}.'.description'};         $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'}}) {      if (defined $courselogs{$ENV{'request.course.id'}}) {
  $courselogs{$ENV{'request.course.id'}}.='&'.$what;   $courselogs{$ENV{'request.course.id'}}.='&'.$what;
     } else {      } else {
Line 1544  sub getannounce { Line 1622  sub getannounce {
  if ($announcement=~/\w/) {    if ($announcement=~/\w/) { 
     return       return 
    '<table bgcolor="#FF5555" cellpadding="5" cellspacing="3">'.     '<table bgcolor="#FF5555" cellpadding="5" cellspacing="3">'.
    '<tr><td bgcolor="#FFFFFF"><pre>'.$announcement.'</pre></td></tr></table>';      '<tr><td bgcolor="#FFFFFF"><tt>'.$announcement.'</tt></td></tr></table>'; 
  } else {   } else {
     return '';      return '';
  }   }
Line 1563  sub courseidput { Line 1641  sub courseidput {
 }  }
   
 sub courseiddump {  sub courseiddump {
     my ($domfilter,$descfilter,$sincefilter)=@_;      my ($domfilter,$descfilter,$sincefilter,$hostidflag,$hostidref)=@_;
     my %returnhash=();      my %returnhash=();
     unless ($domfilter) { $domfilter=''; }      unless ($domfilter) { $domfilter=''; }
     foreach my $tryserver (keys %libserv) {      foreach my $tryserver (keys %libserv) {
  if ((!$domfilter) || ($hostdom{$tryserver} eq $domfilter)) {          if ( ($hostidflag == 1 && grep/^$tryserver$/,@{$hostidref}) || (!defined($hostidflag)) ) {
     foreach (      if ((!$domfilter) || ($hostdom{$tryserver} eq $domfilter)) {
              split(/\&/,&reply('courseiddump:'.$hostdom{$tryserver}.':'.          foreach (
                    split(/\&/,&reply('courseiddump:'.$hostdom{$tryserver}.':'.
        $sincefilter.':'.&escape($descfilter),         $sincefilter.':'.&escape($descfilter),
                                $tryserver))) {                                 $tryserver))) {
  my ($key,$value)=split(/\=/,$_);      my ($key,$value)=split(/\=/,$_);
                 if (($key) && ($value)) {                      if (($key) && ($value)) {
     $returnhash{&unescape($key)}=&unescape($value);          $returnhash{&unescape($key)}=$value;
                       }
                 }                  }
             }              }
   
         }          }
     }      }
     return %returnhash;      return %returnhash;
Line 1586  sub courseiddump { Line 1665  sub courseiddump {
 #  #
 # ----------------------------------------------------------- Check out an item  # ----------------------------------------------------------- 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 {  sub checkout {
     my ($symb,$tuname,$tudom,$tcrsid)=@_;      my ($symb,$tuname,$tudom,$tcrsid)=@_;
     my $now=time;      my $now=time;
Line 1764  sub hash2str { Line 1865  sub hash2str {
 sub hashref2str {  sub hashref2str {
   my ($hashref)=@_;    my ($hashref)=@_;
   my $result='__HASH_REF__';    my $result='__HASH_REF__';
   foreach (keys(%$hashref)) {    foreach (sort(keys(%$hashref))) {
     if (ref($_) eq 'ARRAY') {      if (ref($_) eq 'ARRAY') {
       $result.=&arrayref2str($_).'=';        $result.=&arrayref2str($_).'=';
     } elsif (ref($_) eq 'HASH') {      } elsif (ref($_) eq 'HASH') {
Line 2496  sub put { Line 2597  sub put {
    return &reply("put:$udomain:$uname:$namespace:$items",$uhome);     return &reply("put:$udomain:$uname:$namespace:$items",$uhome);
 }  }
   
   # ---------------------------------------------------------- putstore interface
                                                                                        
   sub putstore {
      my ($namespace,$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.=$_.'='.&escape($$storehash{$_}).'&';
      }
      foreach (keys %allitems) {
          $allitems{$_} =~ s/\:$//;
          $items.= $_.'='.$allitems{$_}.'&';
      }
      $items=~s/\&$//;
      return &reply("put:$udomain:$uname:$namespace:$items",$uhome);
   }
   
 # ------------------------------------------------------ critical put interface  # ------------------------------------------------------ critical put interface
   
 sub cput {  sub cput {
Line 2578  sub allowed { Line 2703  sub allowed {
   
     if (defined($ENV{'allowed.'.$priv})) { return $ENV{'allowed.'.$priv}; }      if (defined($ENV{'allowed.'.$priv})) { return $ENV{'allowed.'.$priv}; }
 # Free bre access to adm and meta resources  # Free bre access to adm and meta resources
       if (((($uri=~/^adm\//) && ($uri !~ m|/bulletinboard$|)) 
     if ((($uri=~/^adm\//) || ($uri=~/\.meta$/)) && ($priv eq 'bre')) {   || ($uri=~/\.meta$/)) && ($priv eq 'bre')) {
  return 'F';   return 'F';
     }      }
   
Line 2625  sub allowed { Line 2750  sub allowed {
   
 # Course  # Course
   
     if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'}=~/$priv\&([^\:]*)/) {      if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'}=~/\Q$priv\E\&([^\:]*)/) {
        $thisallowed.=$1;         $thisallowed.=$1;
     }      }
   
 # Domain  # Domain
   
     if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.(split(/\//,$uri))[0].'/'}      if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.(split(/\//,$uri))[0].'/'}
        =~/$priv\&([^\:]*)/) {         =~/\Q$priv\E\&([^\:]*)/) {
        $thisallowed.=$1;         $thisallowed.=$1;
     }      }
   
Line 2642  sub allowed { Line 2767  sub allowed {
     $courseuri=~s/^([^\/])/\/$1/;      $courseuri=~s/^([^\/])/\/$1/;
   
     if ($ENV{'user.priv.'.$ENV{'request.role'}.'.'.$courseuri}      if ($ENV{'user.priv.'.$ENV{'request.role'}.'.'.$courseuri}
        =~/$priv\&([^\:]*)/) {         =~/\Q$priv\E\&([^\:]*)/) {
        $thisallowed.=$1;         $thisallowed.=$1;
     }      }
   
 # URI is an uploaded document for this course  # URI is an uploaded document for this course
   
     if (($priv eq 'bre') &&       if (($priv eq 'bre') && ($uri=~m|^uploaded/|)) {
         ($uri=~/^uploaded\/$ENV{'course.'.$ENV{'request.course.id'}.'.domain'}\/$ENV{'course.'.$ENV{'request.course.id'}.'.num'}/)) {   my $refuri=$ENV{'httpref.'.$orguri};
         return 'F';   if ($refuri) {
       if ($refuri =~ m|^/adm/|) {
    $thisallowed='F';
       }
    }
     }      }
   
 # Full access at system, domain or course-wide level? Exit.  # Full access at system, domain or course-wide level? Exit.
   
     if ($thisallowed=~/F/) {      if ($thisallowed=~/F/) {
Line 2660  sub allowed { Line 2790  sub allowed {
   
 # If this is generating or modifying users, exit with special codes  # 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;   return $thisallowed;
     }      }
 #  #
Line 2681  sub allowed { Line 2811  sub allowed {
        if ($match) {         if ($match) {
            $statecond=$cond;             $statecond=$cond;
            if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.$courseprivid}             if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.$courseprivid}
                =~/$priv\&([^\:]*)/) {                 =~/\Q$priv\E\&([^\:]*)/) {
                $thisallowed.=$1;                 $thisallowed.=$1;
                $checkreferer=0;                 $checkreferer=0;
            }             }
Line 2709  sub allowed { Line 2839  sub allowed {
             if ($match) {              if ($match) {
               my $refstatecond=$cond;                my $refstatecond=$cond;
               if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.$courseprivid}                if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.$courseprivid}
                   =~/$priv\&([^\:]*)/) {                    =~/\Q$priv\E\&([^\:]*)/) {
                   $thisallowed.=$1;                    $thisallowed.=$1;
                   $uri=$refuri;                    $uri=$refuri;
                   $statecond=$refstatecond;                    $statecond=$refstatecond;
Line 2762  sub allowed { Line 2892  sub allowed {
                if ((time-$ENV{$prefix.'last_cache'})>$expiretime) {                 if ((time-$ENV{$prefix.'last_cache'})>$expiretime) {
    &coursedescription($courseid);     &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')) {                  || ($ENV{$prefix.'res.'.$uri.'.lock.sections'} eq 'all')) {
    if ($ENV{$prefix.'res.'.$uri.'.lock.expire'}>time) {     if ($ENV{$prefix.'res.'.$uri.'.lock.expire'}>time) {
                        &log($ENV{'user.domain'},$ENV{'user.name'},                         &log($ENV{'user.domain'},$ENV{'user.name'},
Line 2773  sub allowed { Line 2903  sub allowed {
        return '';         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')) {                  || ($ENV{$prefix.'priv.'.$priv.'.lock.sections'} eq 'all')) {
    if ($ENV{'priv.'.$priv.'.lock.expire'}>time) {     if ($ENV{'priv.'.$priv.'.lock.expire'}>time) {
                        &log($ENV{'user.domain'},$ENV{'user.name'},                         &log($ENV{'user.domain'},$ENV{'user.name'},
Line 2807  sub allowed { Line 2937  sub allowed {
        my $rolecode=(split(/\./,$ENV{'request.role'}))[0];         my $rolecode=(split(/\./,$ENV{'request.role'}))[0];
        my $unamedom=$ENV{'user.name'}.':'.$ENV{'user.domain'};         my $unamedom=$ENV{'user.name'}.':'.$ENV{'user.domain'};
        if ($ENV{'course.'.$ENV{'request.course.id'}.'.'.$priv.'.roles.denied'}         if ($ENV{'course.'.$ENV{'request.course.id'}.'.'.$priv.'.roles.denied'}
    =~/$rolecode/) {     =~/\Q$rolecode\E/) {
            &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.host'},             &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.host'},
                 'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode.' in '.                  'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode.' in '.
                 $ENV{'request.course.id'});                  $ENV{'request.course.id'});
Line 2815  sub allowed { Line 2945  sub allowed {
        }         }
   
        if ($ENV{'course.'.$ENV{'request.course.id'}.'.'.$priv.'.users.denied'}         if ($ENV{'course.'.$ENV{'request.course.id'}.'.'.$priv.'.users.denied'}
    =~/$unamedom/) {     =~/\Q$unamedom\E/) {
            &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.host'},             &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.host'},
                 'Denied by user: '.$priv.' for '.$uri.' as '.$unamedom.' in '.                  'Denied by user: '.$priv.' for '.$uri.' as '.$unamedom.' in '.
                 $ENV{'request.course.id'});                  $ENV{'request.course.id'});
Line 2827  sub allowed { Line 2957  sub allowed {
   
    if ($thisallowed=~/R/) {     if ($thisallowed=~/R/) {
        my $rolecode=(split(/\./,$ENV{'request.role'}))[0];         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'},    &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.host'},
                     'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode);                      'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode);
           return '';            return '';
Line 2839  sub allowed { Line 2969  sub allowed {
    if ($thisallowed=~/X/) {     if ($thisallowed=~/X/) {
       if ($ENV{'acc.randomout'}) {        if ($ENV{'acc.randomout'}) {
          my $symb=&symbread($uri,1);           my $symb=&symbread($uri,1);
          if (($symb) && ($ENV{'acc.randomout'}=~/\&$symb\&/)) {            if (($symb) && ($ENV{'acc.randomout'}=~/\&\Q$symb\E\&/)) { 
             return '';               return ''; 
          }           }
       }        }
Line 2903  sub definerole { Line 3033  sub definerole {
     my ($rolename,$sysrole,$domrole,$courole)=@_;      my ($rolename,$sysrole,$domrole,$courole)=@_;
     foreach (split(':',$sysrole)) {      foreach (split(':',$sysrole)) {
  my ($crole,$cqual)=split(/\&/,$_);   my ($crole,$cqual)=split(/\&/,$_);
         if ($pr{'cr:s'}!~/$crole/) { return "refused:s:$crole"; }          if ($pr{'cr:s'}!~/\Q$crole\E/) { return "refused:s:$crole"; }
         if ($pr{'cr:s'}=~/$crole\&/) {          if ($pr{'cr:s'}=~/\Q$crole\E\&/) {
     if ($pr{'cr:s'}!~/$crole\&\w*$cqual/) {       if ($pr{'cr:s'}!~/\Q$crole\E\&\w*\Q$cqual\E/) { 
                return "refused:s:$crole&$cqual";                  return "refused:s:$crole&$cqual"; 
             }              }
         }          }
     }      }
     foreach (split(':',$domrole)) {      foreach (split(':',$domrole)) {
  my ($crole,$cqual)=split(/\&/,$_);   my ($crole,$cqual)=split(/\&/,$_);
         if ($pr{'cr:d'}!~/$crole/) { return "refused:d:$crole"; }          if ($pr{'cr:d'}!~/\Q$crole\E/) { return "refused:d:$crole"; }
         if ($pr{'cr:d'}=~/$crole\&/) {          if ($pr{'cr:d'}=~/\Q$crole\E\&/) {
     if ($pr{'cr:d'}!~/$crole\&\w*$cqual/) {       if ($pr{'cr:d'}!~/\Q$crole\W\&\w*\Q$cqual\E/) { 
                return "refused:d:$crole&$cqual";                  return "refused:d:$crole&$cqual"; 
             }              }
         }          }
     }      }
     foreach (split(':',$courole)) {      foreach (split(':',$courole)) {
  my ($crole,$cqual)=split(/\&/,$_);   my ($crole,$cqual)=split(/\&/,$_);
         if ($pr{'cr:c'}!~/$crole/) { return "refused:c:$crole"; }          if ($pr{'cr:c'}!~/\Q$crole\E/) { return "refused:c:$crole"; }
         if ($pr{'cr:c'}=~/$crole\&/) {          if ($pr{'cr:c'}=~/\Q$crole\E\&/) {
     if ($pr{'cr:c'}!~/$crole\&\w*$cqual/) {       if ($pr{'cr:c'}!~/\Q$crole\E\&\w*\Q$cqual\E/) { 
                return "refused:c:$crole&$cqual";                  return "refused:c:$crole&$cqual"; 
             }              }
         }          }
Line 2970  sub log_query { Line 3100  sub log_query {
     my $command=&escape(join(':',map{$_.'='.$filters{$_}} keys %filters));      my $command=&escape(join(':',map{$_.'='.$filters{$_}} keys %filters));
     my $queryid=&reply("querysend:".$query.':'.$udom.':'.$uname.':'.$command,      my $queryid=&reply("querysend:".$query.':'.$udom.':'.$uname.':'.$command,
                        $uhome);                         $uhome);
     unless ($queryid=~/^$uhost\_/) { return 'error: '.$queryid; }      unless ($queryid=~/^\Q$uhost\E\_/) { return 'error: '.$queryid; }
     return get_query_reply($queryid);      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\_/) { 
           &logthis('fetch_enrollment_query: invalid queryid: '.$queryid.' for host: '.$host.' and homeserver: '.$homeserver.' context: '.$context.' '.$cnum); 
           return 'error: '.$queryid;
       }
       my $reply = &get_query_reply($queryid);
       if ( ($reply =~/^timeout/) || ($reply =~/^error/) ) {
           &logthis('fetch_enrollment_query error: '.$reply.' for '.$dom.' '.$ENV{'user.name'}.' for '.$queryid.' context: '.$context.' '.$cnum);
       } else {
           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);
                           if ($xml_classlist =~ /^error/) {
                               &logthis('fetch_enrollment_query - autoretrieve error: '.$xml_classlist.' for '.$filename.' from server: '.$homeserver.' '.$context.' '.$cnum);
                           } else {
                               if ( open(FILE,">$destname") ) {
                                   print FILE &unescape($xml_classlist);
                                   close(FILE);
                               } else {
                                   &logthis('fetch_enrollment_query - error opening classlist file '.$destname.' '.$context.' '.$cnum);
                               }
                           }
                       }
                   }
               }
           }
           return 'ok';
       }
       return 'error';
   }
   
 sub get_query_reply {  sub get_query_reply {
     my $queryid=shift;      my $queryid=shift;
     my $replyfile=$perlvar{'lonDaemons'}.'/tmp/'.$queryid;      my $replyfile=$perlvar{'lonDaemons'}.'/tmp/'.$queryid;
Line 3018  sub userlog_query { Line 3210  sub userlog_query {
     return &log_query($uname,$udom,'userlog',%filters);      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  # ------------------------------------------------------------------ Plain Text
   
 sub plaintext {  sub plaintext {
Line 3208  sub modifyuser { Line 3474  sub modifyuser {
   
 sub modifystudent {  sub modifystudent {
     my ($udom,$uname,$uid,$umode,$upass,$first,$middle,$last,$gene,$usec,      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) {      if (!$cid) {
  unless ($cid=$ENV{'request.course.id'}) {   unless ($cid=$ENV{'request.course.id'}) {
     return 'not_in_class';      return 'not_in_class';
Line 3223  sub modifystudent { Line 3489  sub modifystudent {
     # students environment      # students environment
     $uid = undef if (!$forceid);      $uid = undef if (!$forceid);
     $reply = &modify_student_enrollment($udom,$uname,$uid,$first,$middle,$last,      $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;      return $reply;
 }  }
   
 sub modify_student_enrollment {  sub modify_student_enrollment {
     my ($udom,$uname,$uid,$first,$middle,$last,$gene,$usec,$end,$start,$type,      my ($udom,$uname,$uid,$first,$middle,$last,$gene,$usec,$end,$start,$type,$locktype,$cid) = @_;
  $cid) = @_;  
     my ($cdom,$cnum,$chome);      my ($cdom,$cnum,$chome);
     if (!$cid) {      if (!$cid) {
  unless ($cid=$ENV{'request.course.id'}) {   unless ($cid=$ENV{'request.course.id'}) {
Line 3273  sub modify_student_enrollment { Line 3538  sub modify_student_enrollment {
     }      }
     my $fullname = &Apache::loncoursedata::ProcessFullName($last,$gene,      my $fullname = &Apache::loncoursedata::ProcessFullName($last,$gene,
                                                            $first,$middle);                                                             $first,$middle);
     my $value=&escape($uname.':'.$udom).'='.      my $reply=cput('classlist',
  &escape(join(':',$end,$start,$uid,$usec,$fullname,$type));     {"$uname:$udom" => 
     my $reply=critical('put:'.$cdom.':'.$cnum.':classlist:'.$value,$chome);   join(':',$end,$start,$uid,$usec,$fullname,$type,$locktype) },
      $cdom,$cnum);
     unless (($reply eq 'ok') || ($reply eq 'delayed')) {      unless (($reply eq 'ok') || ($reply eq 'delayed')) {
  return 'error: '.$reply;   return 'error: '.$reply;
     }      }
Line 3310  sub writecoursepref { Line 3576  sub writecoursepref {
 # ---------------------------------------------------------- Make/modify course  # ---------------------------------------------------------- Make/modify course
   
 sub createcourse {  sub createcourse {
     my ($udom,$description,$url,$course_server,$nonstandard)=@_;      my ($udom,$description,$url,$course_server,$nonstandard,$inst_code)=@_;
     $url=&declutter($url);      $url=&declutter($url);
     my $cid='';      my $cid='';
     unless (&allowed('ccc',$udom)) {      unless (&allowed('ccc',$udom)) {
Line 3343  sub createcourse { Line 3609  sub createcourse {
  return 'error: no such course';   return 'error: no such course';
     }      }
 # ----------------------------------------------------------------- Course made  # ----------------------------------------------------------------- Course made
 # log existance  # log existence
     &courseidput($udom,&escape($udom.'_'.$uname).'='.&escape($description),      &courseidput($udom,&escape($udom.'_'.$uname).'='.&escape($description).
                  $uhome);                   '='.&escape($inst_code),$uhome);
     &flushcourselogs();      &flushcourselogs();
 # set toplevel url  # set toplevel url
     my $topurl=$url;      my $topurl=$url;
Line 3398  sub revokecustomrole { Line 3664  sub revokecustomrole {
            $deleteflag);             $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  # ------------------------------------------------------------ Directory lister
   
 sub dirlist {  sub dirlist {
Line 3901  sub metadata { Line 4203  sub metadata {
     my ($uri,$what,$liburi,$prefix,$depthcount)=@_;      my ($uri,$what,$liburi,$prefix,$depthcount)=@_;
     $uri=&declutter($uri);      $uri=&declutter($uri);
     # if it is a non metadata possible uri return quickly      # if it is a non metadata possible uri return quickly
     if (($uri eq '') || (($uri =~ m|^/*adm/|) && ($uri !~ m|^adm/includes|)) ||      if (($uri eq '') || 
    (($uri =~ m|^/*adm/|) && 
        ($uri !~ m|^adm/includes|) && ($uri !~ m|/bulletinboard$|)) ||
         ($uri =~ m|/$|) || ($uri =~ m|/.meta$|) || ($uri =~ /^~/) ||          ($uri =~ m|/$|) || ($uri =~ m|/.meta$|) || ($uri =~ /^~/) ||
  ($uri =~ m|home/[^/]+/public_html/|) || ($uri =~ m|^uploaded/|)) {   ($uri =~ m|home/[^/]+/public_html/|)) {
  return undef;   return undef;
     }      }
     my $filename=$uri;      my $filename=$uri;
Line 3932  sub metadata { Line 4236  sub metadata {
  }   }
         my %metathesekeys=();          my %metathesekeys=();
         unless ($filename=~/\.meta$/) { $filename.='.meta'; }          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 $parser=HTML::LCParser->new(\$metastring);
         my $token;          my $token;
         undef %metathesekeys;          undef %metathesekeys;
Line 4043  sub metadata { Line 4350  sub metadata {
 # the next is the end of "start tag"  # 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  # are there custom rights to evaluate
  if ($metacache{$uri}->{':copyright'} eq 'custom') {   if ($metacache{$uri}->{':copyright'} eq 'custom') {
   
Line 4071  sub metadata { Line 4394  sub metadata {
     return $metacache{$uri}->{':'.$what};      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 {  sub metadata_generate_part0 {
     my ($metadata,$metacache,$uri) = @_;      my ($metadata,$metacache,$uri) = @_;
     my %allnames;      my %allnames;
Line 4094  sub metadata_generate_part0 { Line 4441  sub metadata_generate_part0 {
       my $olddis=$$metacache{':parameter_'.$allnames{$name}.'_'.$name.        my $olddis=$$metacache{':parameter_'.$allnames{$name}.'_'.$name.
      '.display'};       '.display'};
       my $expr='\\[Part: '.$allnames{$name}.'\\]';        my $expr='\\[Part: '.$allnames{$name}.'\\]';
       $olddis=~s/$expr/\[Part: 0\]/;        $olddis=~s/\Q$expr\E/\[Part: 0\]/;
       $$metacache{"$key.display"}=$olddis;        $$metacache{"$key.display"}=$olddis;
     }      }
 }  }
Line 4150  sub symblist { Line 4497  sub symblist {
 # --------------------------------------------------------------- Verify a symb  # --------------------------------------------------------------- Verify a symb
   
 sub symbverify {  sub symbverify {
     my ($symb,$thisfn)=@_;      my ($symb,$thisurl)=@_;
       my $thisfn=$thisurl;
   # wrapper not part of symbs
       $thisfn=~s/^\/adm\/wrapper//;
     $thisfn=&declutter($thisfn);      $thisfn=&declutter($thisfn);
 # direct jump to resource in page or to a sequence - will construct own symbs  # direct jump to resource in page or to a sequence - will construct own symbs
     if ($thisfn=~/\.(page|sequence)$/) { return 1; }      if ($thisfn=~/\.(page|sequence)$/) { return 1; }
Line 4160  sub symbverify { Line 4510  sub symbverify {
     unless ($url eq $thisfn) { return 0; }      unless ($url eq $thisfn) { return 0; }
   
     $symb=&symbclean($symb);      $symb=&symbclean($symb);
       $thisurl=&deversion($thisurl);
     $thisfn=&deversion($thisfn);      $thisfn=&deversion($thisfn);
   
     my %bighash;      my %bighash;
Line 4167  sub symbverify { Line 4518  sub symbverify {
   
     if (tie(%bighash,'GDBM_File',$ENV{'request.course.fn'}.'.db',      if (tie(%bighash,'GDBM_File',$ENV{'request.course.fn'}.'.db',
                             &GDBM_READER(),0640)) {                              &GDBM_READER(),0640)) {
         my $ids=$bighash{'ids_'.&clutter($thisfn)};          my $ids=$bighash{'ids_'.&clutter($thisurl)};
         unless ($ids) {           unless ($ids) { 
            $ids=$bighash{'ids_/'.$thisfn};             $ids=$bighash{'ids_/'.$thisurl};
         }          }
         if ($ids) {          if ($ids) {
 # ------------------------------------------------------------------- Has ID(s)  # ------------------------------------------------------------------- Has ID(s)
Line 4198  sub symbclean { Line 4549  sub symbclean {
 # remove version from URL  # remove version from URL
     $symb=~s/\.(\d+)\.(\w+)$/\.$2/;      $symb=~s/\.(\d+)\.(\w+)$/\.$2/;
   
   # remove wrapper
   
       $symb=~s/(\_\_\_\d+\_\_\_)adm\/wrapper\/(res\/)*/$1/;
     return $symb;      return $symb;
 }  }
   
Line 4263  sub symbread { Line 4617  sub symbread {
     my %bighash;      my %bighash;
     my $syval='';      my $syval='';
     if (($ENV{'request.course.fn'}) && ($thisfn)) {      if (($ENV{'request.course.fn'}) && ($thisfn)) {
           my $targetfn = $thisfn;
           if ( ($thisfn =~ m/^uploaded\//) && ($thisfn !~ m/\.(page|sequence)$/) ) {
               $targetfn = 'adm/wrapper/'.$thisfn;
           }
         if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.'_symb.db',          if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.'_symb.db',
                       &GDBM_READER(),0640)) {                        &GDBM_READER(),0640)) {
     $syval=$hash{$thisfn};      $syval=$hash{$targetfn};
             untie(%hash);              untie(%hash);
         }          }
 # ---------------------------------------------------------- There was an entry  # ---------------------------------------------------------- There was an entry
Line 4317  sub symbread { Line 4675  sub symbread {
                  }                   }
       }        }
               untie(%bighash)                untie(%bighash)
            }              }
         }          }
         if ($syval) {          if ($syval) {
            return &symbclean($syval.'___'.$thisfn);              return &symbclean($syval.'___'.$thisfn); 
Line 4341  sub numval { Line 4699  sub numval {
     return int($txt);      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 {  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 {
       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 {  sub rndseed {
Line 4355  sub rndseed { Line 4746  sub rndseed {
     if (!$courseid) { $courseid=$wcourseid; }      if (!$courseid) { $courseid=$wcourseid; }
     if (!$domain) { $domain=$wdomain; }      if (!$domain) { $domain=$wdomain; }
     if (!$username) { $username=$wusername }      if (!$username) { $username=$wusername }
     my $which=$ENV{"course.$courseid.rndseed"};      my $which=&get_rand_alg();
     my $CODE=$ENV{'scantron.CODE'};      if (defined(&getCODE())) {
     if (defined($CODE)) {   return &rndseed_CODE_64bit($symb,$courseid,$domain,$username);
  &rndseed_CODE_64bit($symb,$courseid,$domain,$username);      } elsif ($which eq '64bit3') {
    return &rndseed_64bit3($symb,$courseid,$domain,$username);
     } elsif ($which eq '64bit2') {      } elsif ($which eq '64bit2') {
  return &rndseed_64bit2($symb,$courseid,$domain,$username);   return &rndseed_64bit2($symb,$courseid,$domain,$username);
     } elsif ($which eq '64bit') {      } elsif ($which eq '64bit') {
Line 4426  sub rndseed_64bit2 { Line 4818  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 {  sub rndseed_CODE_64bit {
     my ($symb,$courseid,$domain,$username)=@_;      my ($symb,$courseid,$domain,$username)=@_;
     {      {
  use integer;   use integer;
  my $symbchck=unpack("%32S*",$symb.' ') << 16;   my $symbchck=unpack("%32S*",$symb.' ') << 16;
  my $symbseed=numval($symb);   my $symbseed=numval2($symb);
  my $CODEseed=numval($ENV{'scantron.CODE'}) << 16;   my $CODEchck=unpack("%32S*",&getCODE().' ') << 16;
    my $CODEseed=numval(&getCODE());
  my $courseseed=unpack("%32S*",$courseid.' ');   my $courseseed=unpack("%32S*",$courseid.' ');
  my $num1=$symbseed+$CODEseed;   my $num1=$symbseed+$CODEchck;
  my $num2=$courseseed+$symbchck;   my $num2=$CODEseed+$courseseed+$symbchck;
  #&Apache::lonxml::debug("$symbseed:$CODEseed|$courseseed:$symbchck");   #&Apache::lonxml::debug("$symbseed:$CODEchck|$CODEseed:$courseseed:$symbchck");
  #&Apache::lonxml::debug("rndseed :$num1:$num2:$symb");   #&Apache::lonxml::debug("rndseed :$num1:$num2:$symb");
  return "$num1,$num2";   return "$num1:$num2";
     }      }
 }  }
   
 sub setup_random_from_rndseed {  sub setup_random_from_rndseed {
     my ($rndseed)=@_;      my ($rndseed)=@_;
     if ($rndseed =~/,/) {      if ($rndseed =~/([,:])/) {
  my ($num1,$num2)=split(/,/,$rndseed);   my ($num1,$num2)=split(/[,:]/,$rndseed);
  &Math::Random::random_set_seed(abs($num1),abs($num2));   &Math::Random::random_set_seed(abs($num1),abs($num2));
     } else {      } else {
  &Math::Random::random_set_seed_from_phrase($rndseed);   &Math::Random::random_set_seed_from_phrase($rndseed);
Line 4456  sub latest_receipt_algorithm_id { Line 4871  sub latest_receipt_algorithm_id {
     return 'receipt2';      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 {  sub ireceipt {
     my ($funame,$fudom,$fucourseid,$fusymb,$part)=@_;      my ($funame,$fudom,$fucourseid,$fusymb,$part)=@_;
     my $cuname=unpack("%32C*",$funame);      my $cuname=unpack("%32C*",$funame);
     my $cudom=unpack("%32C*",$fudom);      my $cudom=unpack("%32C*",$fudom);
     my $cucourseid=unpack("%32C*",$fucourseid);      my $cucourseid=unpack("%32C*",$fucourseid);
     my $cusymb=unpack("%32C*",$fusymb);      my $cusymb=unpack("%32C*",$fusymb);
     my $cunique=unpack("%32C*",$perlvar{'lonReceipt'});      my $cunique=&recunique($fucourseid);
     my $cpart=unpack("%32S*",$part);      my $cpart=unpack("%32S*",$part);
     my $return =unpack("%32C*",$perlvar{'lonHostID'}).'-';      my $return =&recprefix($fucourseid).'-';
     if ($ENV{"course.$fucourseid.receiptalg"} eq 'receipt2' ||      if ($ENV{"course.$fucourseid.receiptalg"} eq 'receipt2' ||
  $ENV{'request.state'} eq 'construct') {   $ENV{'request.state'} eq 'construct') {
  &Apache::lonxml::debug("doing receipt2  using parts $cpart, uname $cuname and udom $cudom gets  ".($cpart%$cuname).   &Apache::lonxml::debug("doing receipt2  using parts $cpart, uname $cuname and udom $cudom gets  ".($cpart%$cuname).
Line 4498  sub receipt { Line 4935  sub receipt {
 # ------------------------------------------------------------ Serves up a file  # ------------------------------------------------------------ Serves up a file
 # returns either the contents of the file or   # returns either the contents of the file or 
 # -1 if the file doesn't exist  # -1 if the file doesn't exist
 # -2 if an error occured when trying to aqcuire the file  #
   # if the target is a file that was uploaded via DOCS, 
   # a check will be made to see if a current copy exists on the local server,
   # if it does this will be served, otherwise a copy will be retrieved from
   # the home server for the course and stored in /home/httpd/html/userfiles on
   # the local server.   
   
 sub getfile {  sub getfile {
     my $file=shift;      my ($file,$caller) = @_;
     if ($file=~/^\/*uploaded\//) { # user file  
  my $ua=new LWP::UserAgent;      if ($file !~ m|^/*uploaded/(\w+)/(\w+)/(.+)$|) {
  my $request=new HTTP::Request('GET',&tokenwrapper($file));   # normal file from res space
  my $response=$ua->request($request);   &repcopy($file);
  if ($response->is_success()) {          return &readfile($file);
     return $response->content;      }
  } else {   
     #&logthis("Return Code is ".$response->code." for $file ".      my $info;
     #         &tokenwrapper($file));      my $cdom = $1;
     # 500 for ISE when tokenwrapper can't figure out what server to      my $cnum = $2;
             #  contact      my $filename = $3;
             # 503 when lonuploadacc can't contact the requested server      my $path = $Apache::lonnet::perlvar{'lonDocRoot'}.'/userfiles';
     if ($response->code eq 503 || $response->code eq 500) {      my ($lwpresp,$rtncode);
  return -2;      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);
       }
       #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]) {
       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') {
       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 {      } else {
  return -1;   return -1;
     }      }
  }   }
     } else { # normal file from res space   my @parts = ($cdom,$cnum); 
  &repcopy($file);   if ($filename =~ m|^(.+)/[^/]+$|) {
  if (! -e $file ) { return -1; };      push @parts, split(/\//,$1);
  my $fh;   }
  open($fh,"<$file");   foreach my $part (@parts) {
  my $a='';      $path .= '/'.$part;
  while (<$fh>) { $a .=$_; }      if (!-e $path) {
  return $a;   mkdir($path,0770);
       }
    }
       }
       open (FILE,">$localfile");
       print FILE $info;
       close(FILE);
       if ($caller eq 'uploadrep') {
    return 'ok';
       }
       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/^\///;
       $uri = 'http://'.$hostname{ &homeserver($cnum,$cdom)}.'/raw/'.$uri;
       my $ua=new LWP::UserAgent;
       my $request=new HTTP::Request($reqtype,$uri);
       my $response=$ua->request($request);
       $$rtncode = $response->code;
       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 {
       my $file = shift;
       if ( (! -e $file ) || ($file eq '') ) { return -1; };
       my $fh;
       open($fh,"<$file");
       my $a='';
       while (<$fh>) { $a .=$_; }
       return $a;
   }
   
 sub filelocation {  sub filelocation {
   my ($dir,$file) = @_;    my ($dir,$file) = @_;
   my $location;    my $location;
Line 4539  sub filelocation { Line 5068  sub filelocation {
     $location = $file;      $location = $file;
     $location =~ s:/~(.*?)/(.*):/home/$1/public_html/$2:;      $location =~ s:/~(.*?)/(.*):/home/$1/public_html/$2:;
   } elsif ($file=~/^\/*uploaded/) { # is an uploaded file    } elsif ($file=~/^\/*uploaded/) { # is an uploaded file
     $location=$file;        if ($file=~/^\/uploaded\/([^\/]+)\/([^\/]+)\/(\/)?simplepage\/([^\/]+)$/) {
     $location=&Apache::loncommon::propath($1,$2).'/userfiles/simplepage/'.$4;
     if (not -e $location) {
         $file=~/^\/uploaded\/(.*)$/;
         $location=$Apache::lonnet::perlvar{'lonDocRoot'}.'/userfiles/'.$1;
     }
         } elsif ($file=~/^\/uploaded\/([^\/]+)\/([^\/]+)\/aboutme\/([^\/]+)$/) {
     $location=&Apache::loncommon::propath($1,$2).'/userfiles/aboutme/'.$3;
            if (not -e $location) {
        $file=~/^\/uploaded\/(.*)$/;
        $location=$Apache::lonnet::perlvar{'lonDocRoot'}.'/userfiles/'.$1;
            }
         } else {
     $location=$file;
         }
   } else {    } else {
     $file=~s/^$perlvar{'lonDocRoot'}//;      $file=~s/^\Q$perlvar{'lonDocRoot'}\E//;
     $file=~s:^/res/:/:;      $file=~s:^/res/:/:;
     if ( !( $file =~ m:^/:) ) {      if ( !( $file =~ m:^/:) ) {
       $location = $dir. '/'.$file;        $location = $dir. '/'.$file;
Line 4598  sub current_machine_ids { Line 5141  sub current_machine_ids {
   
 sub declutter {  sub declutter {
     my $thisfn=shift;      my $thisfn=shift;
     $thisfn=~s/^$perlvar{'lonDocRoot'}//;      $thisfn=~s/^\Q$perlvar{'lonDocRoot'}\E//;
     $thisfn=~s/^\///;      $thisfn=~s/^\///;
     $thisfn=~s/^res\///;      $thisfn=~s/^res\///;
     $thisfn=~s/\?.+$//;      $thisfn=~s/\?.+$//;
Line 4609  sub declutter { Line 5152  sub declutter {
   
 sub clutter {  sub clutter {
     my $thisfn='/'.&declutter(shift);      my $thisfn='/'.&declutter(shift);
     unless ($thisfn=~/^\/(uploaded|adm|userfiles|ext|raw|priv)\//) {       unless ($thisfn=~/^\/(uploaded|adm|userfiles|ext|raw|priv|public)\//) { 
        $thisfn='/res'.$thisfn;          $thisfn='/res'.$thisfn; 
     }      }
     return $thisfn;      return $thisfn;
Line 4671  BEGIN { Line 5214  BEGIN {
     open(my $config,"</etc/httpd/conf/loncapa.conf");      open(my $config,"</etc/httpd/conf/loncapa.conf");
   
     while (my $configline=<$config>) {      while (my $configline=<$config>) {
         if ($configline =~ /^[^\#]*PerlSetVar/) {          if ($configline=~/\S/ && $configline =~ /^[^\#]*PerlSetVar/) {
    my ($dummy,$varname,$varvalue)=split(/\s+/,$configline);     my ($dummy,$varname,$varvalue)=split(/\s+/,$configline);
            chomp($varvalue);             chomp($varvalue);
            $perlvar{$varname}=$varvalue;             $perlvar{$varname}=$varvalue;
Line 4789  BEGIN { Line 5332  BEGIN {
     open(my $config,"<$perlvar{'lonTabDir'}/packages.tab");      open(my $config,"<$perlvar{'lonTabDir'}/packages.tab");
   
     while (my $configline=<$config>) {      while (my $configline=<$config>) {
    if ($configline !~ /\S/ || $configline=~/^#/) { next; }
  chomp($configline);   chomp($configline);
  my ($short,$plain)=split(/:/,$configline);   my ($short,$plain)=split(/:/,$configline);
  my ($pack,$name)=split(/\&/,$short);   my ($pack,$name)=split(/\&/,$short);
Line 5429  put($namespace,$storehash,$udom,$uname) Line 5973  put($namespace,$storehash,$udom,$uname)
   
 =item *  =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  cput($namespace,$storehash,$udom,$uname) : critical put
 ($udom and $uname are optional)  ($udom and $uname are optional)
   
Line 5534  messages of critical importance should g Line 6089  messages of critical importance should g
   
 =item *  =item *
   
 getfile($file) : returns the entire contents of a file or -1; it  getfile($file,$caller) : two cases - requests for files in /res or in /uploaded.
 properly subscribes to and replicates the file if neccessary.  (a) files in /uploaded
     (i) If a local copy of the file exists - 
         compares modification date of local copy with last-modified date for 
         definitive version stored on home server for course. If local copy is 
         stale, requests a new version from the home server and stores it. 
         If the original has been removed from the home server, then local copy 
         is unlinked.
     (ii) If local copy does not exist -
         requests the file from the home server and stores it. 
     
     If $caller is 'uploadrep':  
       This indicates a call from lonuploadrep.pm (PerlHeaderParserHandler phase)
       for request for files originally uploaded via DOCS. 
        - returns 'ok' if fresh local copy now available, -1 otherwise.
     
     Otherwise:
        This indicates a call from the content generation phase of the request.
        -  returns the entire contents of the file or -1.
        
   (b) files in /res
      - returns the entire contents of a file or -1; 
      it properly subscribes to and replicates the file if neccessary.
   
 =item *  =item *
   

Removed from v.1.477  
changed lines
  Added in v.1.530


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>