Diff for /loncom/lonnet/perl/lonnet.pm between versions 1.587 and 1.648

version 1.587, 2005/01/11 22:12:22 version 1.648, 2005/07/26 13:30:34
Line 35  use HTTP::Headers; Line 35  use HTTP::Headers;
 use HTTP::Date;  use HTTP::Date;
 # use Date::Parse;  # use Date::Parse;
 use vars   use vars 
 qw(%perlvar %hostname %homecache %badServerCache %hostip %iphost %spareid %hostdom   qw(%perlvar %hostname %badServerCache %iphost %spareid %hostdom 
    %libserv %pr %prp %metacache %packagetab %titlecache %courseresversioncache %resversioncache     %libserv %pr %prp $memcache %packagetab 
    %courselogs %accesshash %userrolehash $processmarker $dumpcount      %courselogs %accesshash %userrolehash $processmarker $dumpcount 
    %coursedombuf %coursenumbuf %coursehombuf %coursedescrbuf %courseinstcodebuf %courseownerbuf %courseresdatacache      %coursedombuf %coursenumbuf %coursehombuf %coursedescrbuf %courseinstcodebuf %courseownerbuf
    %userresdatacache %getsectioncache %domaindescription %domain_auth_def %domain_auth_arg_def      %domaindescription %domain_auth_def %domain_auth_arg_def 
    %domain_lang_def %domain_city %domain_longi %domain_lati $tmpdir $_64bit);     %domain_lang_def %domain_city %domain_longi %domain_lati $tmpdir $_64bit
      %env);
   
 use IO::Socket;  use IO::Socket;
 use GDBM_File;  use GDBM_File;
 use Apache::Constants qw(:common :http);  use Apache::Constants qw(:common :http);
 use HTML::LCParser;  use HTML::LCParser;
   use HTML::Parser;
 use Fcntl qw(:flock);  use Fcntl qw(:flock);
 use Apache::lonlocal;  use Apache::lonlocal;
 use Storable qw(lock_store lock_nstore lock_retrieve freeze thaw nfreeze);  use Storable qw(lock_store lock_nstore lock_retrieve freeze thaw nfreeze);
 use Time::HiRes qw( gettimeofday tv_interval );  use Time::HiRes qw( gettimeofday tv_interval );
   use Cache::Memcached;
 my $readit;  my $readit;
 my $max_connection_retries = 10;     # Or some such value.  my $max_connection_retries = 10;     # Or some such value.
   
   require Exporter;
   
   our @ISA = qw (Exporter);
   our @EXPORT = qw(%env);
   
 =pod  =pod
   
 =head1 Package Variables  =head1 Package Variables
Line 157  sub reply { Line 165  sub reply {
     my ($cmd,$server)=@_;      my ($cmd,$server)=@_;
     unless (defined($hostname{$server})) { return 'no_such_host'; }      unless (defined($hostname{$server})) { return 'no_such_host'; }
     my $answer=subreply($cmd,$server);      my $answer=subreply($cmd,$server);
     if ($answer eq 'con_lost') {  
         #sleep 5;   
         #$answer=subreply($cmd,$server);  
         #if ($answer eq 'con_lost') {  
  #   &logthis("Second attempt con_lost on $server");  
         #   my $peerfile="$perlvar{'lonSockDir'}/$server";  
         #   my $client=IO::Socket::UNIX->new(Peer    =>"$peerfile",  
         #                                    Type    => SOCK_STREAM,  
         #                                    Timeout => 10)  
         #              or return "con_lost";  
         #   &logthis("Killing socket");  
         #   print $client "close_connection_exit\n";  
            #sleep 5;  
         #   $answer=subreply($cmd,$server);         
        #}     
     }  
     if (($answer=~/^refused/) || ($answer=~/^rejected/)) {      if (($answer=~/^refused/) || ($answer=~/^rejected/)) {
        &logthis("<font color=blue>WARNING:".         &logthis("<font color=blue>WARNING:".
                 " $cmd to $server returned $answer</font>");                  " $cmd to $server returned $answer</font>");
Line 220  sub critical { Line 212  sub critical {
     }      }
     my $answer=reply($cmd,$server);      my $answer=reply($cmd,$server);
     if ($answer eq 'con_lost') {      if ($answer eq 'con_lost') {
         my $pingreply=reply('ping',$server);  
  &reconlonc("$perlvar{'lonSockDir'}/$server");   &reconlonc("$perlvar{'lonSockDir'}/$server");
         my $pongreply=reply('pong',$server);   my $answer=reply($cmd,$server);
         &logthis("Ping/Pong for $server: $pingreply/$pongreply");  
         $answer=reply($cmd,$server);  
         if ($answer eq 'con_lost') {          if ($answer eq 'con_lost') {
             my $now=time;              my $now=time;
             my $middlename=$cmd;              my $middlename=$cmd;
Line 266  sub critical { Line 255  sub critical {
     return $answer;      return $answer;
 }  }
   
 #  
 # -------------- Remove all key from the env that start witha lowercase letter  
 #                (Which is always a lon-capa value)  
   
 sub cleanenv {  
 #    unless (defined(&Apache::exists_config_define("MODPERL2"))) { return; }  
 #    unless (&Apache::exists_config_define("MODPERL2")) { return; }  
     foreach my $key (keys(%ENV)) {  
  if ($key =~ /^[a-z]/) {  
     delete($ENV{$key});  
  }  
     }  
 }  
    
 # ------------------------------------------- Transfer profile into environment  # ------------------------------------------- Transfer profile into environment
   
 sub transfer_profile_to_env {  sub transfer_profile_to_env {
Line 296  sub transfer_profile_to_env { Line 271  sub transfer_profile_to_env {
     for ($envi=0;$envi<=$#profile;$envi++) {      for ($envi=0;$envi<=$#profile;$envi++) {
  chomp($profile[$envi]);   chomp($profile[$envi]);
  my ($envname,$envvalue)=split(/=/,$profile[$envi]);   my ($envname,$envvalue)=split(/=/,$profile[$envi]);
  $ENV{$envname} = $envvalue;   $env{$envname} = $envvalue;
         if (my ($key,$time) = ($envname =~ /^(cgi\.(\d+)_\d+\.)/)) {          if (my ($key,$time) = ($envname =~ /^(cgi\.(\d+)_\d+\.)/)) {
             if ($time < time-300) {              if ($time < time-300) {
                 $Remove{$key}++;                  $Remove{$key}++;
             }              }
         }          }
     }      }
     $ENV{'user.environment'} = "$lonidsdir/$handle.id";      $env{'user.environment'} = "$lonidsdir/$handle.id";
     foreach my $expired_key (keys(%Remove)) {      foreach my $expired_key (keys(%Remove)) {
         &delenv($expired_key);          &delenv($expired_key);
     }      }
Line 320  sub appenv { Line 295  sub appenv {
                 .'</font>');                  .'</font>');
     delete($newenv{$_});      delete($newenv{$_});
         } else {          } else {
             $ENV{$_}=$newenv{$_};              $env{$_}=$newenv{$_};
         }          }
     }      }
   
     my $lockfh;      my $lockfh;
     unless (open($lockfh,"$ENV{'user.environment'}")) {      unless (open($lockfh,"$env{'user.environment'}")) {
  return 'error: '.$!;   return 'error: '.$!;
     }      }
     unless (flock($lockfh,LOCK_EX)) {      unless (flock($lockfh,LOCK_EX)) {
Line 338  sub appenv { Line 313  sub appenv {
     my @oldenv;      my @oldenv;
     {      {
  my $fh;   my $fh;
  unless (open($fh,"$ENV{'user.environment'}")) {   unless (open($fh,"$env{'user.environment'}")) {
     return 'error: '.$!;      return 'error: '.$!;
  }   }
  @oldenv=<$fh>;   @oldenv=<$fh>;
Line 355  sub appenv { Line 330  sub appenv {
     }      }
     {      {
  my $fh;   my $fh;
  unless (open($fh,">$ENV{'user.environment'}")) {   unless (open($fh,">$env{'user.environment'}")) {
     return 'error';      return 'error';
  }   }
  my $newname;   my $newname;
Line 381  sub delenv { Line 356  sub delenv {
     my @oldenv;      my @oldenv;
     {      {
  my $fh;   my $fh;
  unless (open($fh,"$ENV{'user.environment'}")) {   unless (open($fh,"$env{'user.environment'}")) {
     return 'error';      return 'error';
  }   }
  unless (flock($fh,LOCK_SH)) {   unless (flock($fh,LOCK_SH)) {
Line 395  sub delenv { Line 370  sub delenv {
     }      }
     {      {
  my $fh;   my $fh;
  unless (open($fh,">$ENV{'user.environment'}")) {   unless (open($fh,">$env{'user.environment'}")) {
     return 'error';      return 'error';
  }   }
  unless (flock($fh,LOCK_EX)) {   unless (flock($fh,LOCK_EX)) {
Line 407  sub delenv { Line 382  sub delenv {
  foreach (@oldenv) {   foreach (@oldenv) {
     if ($_=~/^$delthis/) {       if ($_=~/^$delthis/) { 
                 my ($key,undef) = split('=',$_);                  my ($key,undef) = split('=',$_);
                 delete($ENV{$key});                  delete($env{$key});
             } else {              } else {
                 print $fh $_;                   print $fh $_; 
             }              }
Line 577  sub authenticate { Line 552  sub authenticate {
   
 # ---------------------- Find the homebase for a user from domain's lib servers  # ---------------------- Find the homebase for a user from domain's lib servers
   
   my %homecache;
 sub homeserver {  sub homeserver {
     my ($uname,$udom,$ignoreBadCache)=@_;      my ($uname,$udom,$ignoreBadCache)=@_;
     my $index="$uname:$udom";      my $index="$uname:$udom";
   
     my ($result,$cached)=&is_cached(\%homecache,$index,'home',86400);      if (exists($homecache{$index})) { return $homecache{$index}; }
     if (defined($cached)) { return $result; }  
     my $tryserver;      my $tryserver;
     foreach $tryserver (keys %libserv) {      foreach $tryserver (keys %libserv) {
         next if ($ignoreBadCache ne 'true' &&           next if ($ignoreBadCache ne 'true' && 
Line 590  sub homeserver { Line 565  sub homeserver {
  if ($hostdom{$tryserver} eq $udom) {   if ($hostdom{$tryserver} eq $udom) {
            my $answer=reply("home:$udom:$uname",$tryserver);             my $answer=reply("home:$udom:$uname",$tryserver);
            if ($answer eq 'found') {              if ($answer eq 'found') { 
        return &do_cache(\%homecache,$index,$tryserver,'home');         return $homecache{$index}=$tryserver;
            } elsif ($answer eq 'no_host') {             } elsif ($answer eq 'no_host') {
        $badServerCache{$tryserver}=1;         $badServerCache{$tryserver}=1;
            }             }
Line 670  sub assign_access_key { Line 645  sub assign_access_key {
 #  #
     my ($ckey,$kdom,$knum,$cdom,$cnum,$udom,$uname,$logentry)=@_;      my ($ckey,$kdom,$knum,$cdom,$cnum,$udom,$uname,$logentry)=@_;
     $kdom=      $kdom=
    $ENV{'course.'.$ENV{'request.course.id'}.'.domain'} unless (defined($kdom));     $env{'course.'.$env{'request.course.id'}.'.domain'} unless (defined($kdom));
     $knum=      $knum=
    $ENV{'course.'.$ENV{'request.course.id'}.'.num'} unless (defined($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],$kdom,$knum);      my %existing=&get('accesskeys',[$ckey],$kdom,$knum);
     if (($existing{$ckey}=~/^\#(.*)$/) || # - new key      if (($existing{$ckey}=~/^\#(.*)$/) || # - new key
         ($existing{$ckey}=~/^\Q$uname\E\:\Q$udom\E\#(.*)$/)) {           ($existing{$ckey}=~/^\Q$uname\E\:\Q$udom\E\#(.*)$/)) { 
Line 720  sub comment_access_key { Line 695  sub comment_access_key {
 #  #
     my ($ckey,$cdom,$cnum,$logentry)=@_;      my ($ckey,$cdom,$cnum,$logentry)=@_;
     $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));
     my %existing=&get('accesskeys',[$ckey],$cdom,$cnum);      my %existing=&get('accesskeys',[$ckey],$cdom,$cnum);
     if ($existing{$ckey}) {      if ($existing{$ckey}) {
         $existing{$ckey}.='; '.$logentry;          $existing{$ckey}.='; '.$logentry;
Line 744  sub comment_access_key { Line 719  sub comment_access_key {
 sub generate_access_keys {  sub generate_access_keys {
     my ($number,$cdom,$cnum,$logentry)=@_;      my ($number,$cdom,$cnum,$logentry)=@_;
     $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));
     unless (&allowed('mky',$cdom)) { return 0; }      unless (&allowed('mky',$cdom)) { return 0; }
     unless (($cdom) && ($cnum)) { return 0; }      unless (($cdom) && ($cnum)) { return 0; }
     if ($number>10000) { return 0; }      if ($number>10000) { return 0; }
Line 765  sub generate_access_keys { Line 740  sub generate_access_keys {
        } else {         } else {
   if (&put('accesskeys',    if (&put('accesskeys',
               { $newkey => '# generated '.localtime().                { $newkey => '# generated '.localtime().
                            ' by '.$ENV{'user.name'}.'@'.$ENV{'user.domain'}.                             ' by '.$env{'user.name'}.'@'.$env{'user.domain'}.
                            '; '.$logentry },                             '; '.$logentry },
    $cdom,$cnum) eq 'ok') {     $cdom,$cnum) eq 'ok') {
               $total++;                $total++;
   }    }
        }         }
     }      }
     &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.home'},      &log($env{'user.domain'},$env{'user.name'},$env{'user.home'},
          'Generated '.$total.' keys for '.$cnum.' at '.$cdom);           'Generated '.$total.' keys for '.$cnum.' at '.$cdom);
     return $total;      return $total;
 }  }
Line 782  sub generate_access_keys { Line 757  sub generate_access_keys {
 sub validate_access_key {  sub validate_access_key {
     my ($ckey,$cdom,$cnum,$udom,$uname)=@_;      my ($ckey,$cdom,$cnum,$udom,$uname)=@_;
     $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.domain'} unless (defined($udom));      $udom=$env{'user.domain'} unless (defined($udom));
     $uname=$ENV{'user.name'} 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}=~/^\Q$uname\E\:\Q$udom\E\#/);      return ($existing{$ckey}=~/^\Q$uname\E\:\Q$udom\E\#/);
 }  }
Line 795  sub validate_access_key { Line 770  sub validate_access_key {
   
 sub getsection {  sub getsection {
     my ($udom,$unam,$courseid)=@_;      my ($udom,$unam,$courseid)=@_;
       my $cachetime=1800;
     $courseid=~s/\_/\//g;      $courseid=~s/\_/\//g;
     $courseid=~s/^(\w)/\/$1/;      $courseid=~s/^(\w)/\/$1/;
   
     my $hashid="$udom:$unam:$courseid";      my $hashid="$udom:$unam:$courseid";
     my ($result,$cached)=&is_cached(\%getsectioncache,$hashid,'getsection');      my ($result,$cached)=&is_cached_new('getsection',$hashid);
     if (defined($cached)) { return $result; }      if (defined($cached)) { return $result; }
   
     my %Pending;       my %Pending; 
Line 834  sub getsection { Line 810  sub getsection {
             $Pending{$start}=$section;              $Pending{$start}=$section;
             next;              next;
         }          }
         return &do_cache(\%getsectioncache,$hashid,$section,'getsection');          return &do_cache_new('getsection',$hashid,$section,$cachetime);
     }      }
     #      #
     # Presumedly there will be few matching roles from the above      # Presumedly there will be few matching roles from the above
     # loop and the sorting time will be negligible.      # loop and the sorting time will be negligible.
     if (scalar(keys(%Pending))) {      if (scalar(keys(%Pending))) {
         my ($time) = sort {$a <=> $b} keys(%Pending);          my ($time) = sort {$a <=> $b} keys(%Pending);
         return &do_cache(\%getsectioncache,$hashid,$Pending{$time},'getsection');          return &do_cache_new('getsection',$hashid,$Pending{$time},$cachetime);
     }       } 
     if (scalar(keys(%Expired))) {      if (scalar(keys(%Expired))) {
         my @sorted = sort {$a <=> $b} keys(%Expired);          my @sorted = sort {$a <=> $b} keys(%Expired);
         my $time = pop(@sorted);          my $time = pop(@sorted);
         return &do_cache(\%getsectioncache,$hashid,$Expired{$time},'getsection');          return &do_cache_new('getsection',$hashid,$Expired{$time},$cachetime);
     }      }
     return &do_cache(\%getsectioncache,$hashid,'-1','getsection');      return &do_cache_new('getsection',$hashid,'-1',$cachetime);
 }  }
   
   sub save_cache {
       my ($r)=@_;
       if (! $r->is_initial_req()) { return DECLINED; }
       &purge_remembered();
       undef(%env);
       return OK;
   }
   
 my $disk_caching_disabled=1;  my $to_remember=-1;
   my %remembered;
 sub devalidate_cache {  my %accessed;
     my ($cache,$id,$name) = @_;  my $kicks=0;
     delete $$cache{$id.'.time'};  my $hits=0;
     delete $$cache{$id.'.file'};  sub devalidate_cache_new {
     delete $$cache{$id};      my ($name,$id,$debug) = @_;
     if (1 || $disk_caching_disabled) { return; }      if ($debug) { &Apache::lonnet::logthis("deleting $name:$id"); }
     my $filename=$perlvar{'lonDaemons'}.'/tmp/lonnet_internal_cache_'.$name.".db";      $id=&escape($name.':'.$id);
     if (!-e $filename) { return; }      $memcache->delete($id);
     open(DB,">$filename.lock");      delete($remembered{$id});
     flock(DB,LOCK_EX);      delete($accessed{$id});
     my %hash;  }
     if (tie(%hash,'GDBM_File',$filename,&GDBM_WRCREAT(),0640)) {  
  eval <<'EVALBLOCK';  sub is_cached_new {
     delete($hash{$id});      my ($name,$id,$debug) = @_;
     delete($hash{$id.'.time'});      $id=&escape($name.':'.$id);
 EVALBLOCK      if (exists($remembered{$id})) {
         if ($@) {   if ($debug) { &Apache::lonnet::logthis("Earyl return $id of $remembered{$id} "); }
     &logthis("<font color='red'>devalidate_cache blew up :$@:$name</font>");   $accessed{$id}=[&gettimeofday()];
     unlink($filename);   $hits++;
  }   return ($remembered{$id},1);
     } else {      }
  if (-e $filename) {      my $value = $memcache->get($id);
     &logthis("Unable to tie hash (devalidate cache): $name");      if (!(defined($value))) {
     unlink($filename);   if ($debug) { &Apache::lonnet::logthis("getting $id is not defined"); }
  }  
     }  
     untie(%hash);  
     flock(DB,LOCK_UN);  
     close(DB);  
 }  
   
 sub is_cached {  
     my ($cache,$id,$name,$time) = @_;  
     if (!$time) { $time=300; }  
     if (!exists($$cache{$id.'.time'})) {  
  &load_cache_item($cache,$name,$id,$time);  
     }  
     if (!exists($$cache{$id.'.time'})) {  
 # &logthis("Didn't find $id");  
  return (undef,undef);   return (undef,undef);
     } else {  
  if (time-($$cache{$id.'.time'})>$time) {  
     if (exists($$cache{$id.'.file'})) {  
  foreach my $filename (@{ $$cache{$id.'.file'} }) {  
     my $mtime=(stat($filename))[9];  
     #+1 is to take care of edge effects  
     if ($mtime && (($mtime+1) < ($$cache{$id.'.time'}))) {  
 # &logthis("Upping $mtime - ".$$cache{$id.'.time'}.  
 # "$id because of $filename");  
     } else {  
  &logthis("Devalidating $filename $id - ".(time-($$cache{$id.'.time'})));  
  &devalidate_cache($cache,$id,$name);  
  return (undef,undef);  
     }  
  }  
  $$cache{$id.'.time'}=time;  
     } else {  
 # &logthis("Devalidating $id - ".time-($$cache{$id.'.time'}));  
  &devalidate_cache($cache,$id,$name);  
  return (undef,undef);  
     }  
  }  
     }      }
     return ($$cache{$id},1);      if ($value eq '__undef__') {
 }   if ($debug) { &Apache::lonnet::logthis("getting $id is __undef__"); }
    $value=undef;
 sub do_cache {      }
     my ($cache,$id,$value,$name) = @_;      &make_room($id,$value,$debug);
     $$cache{$id.'.time'}=time;      if ($debug) { &Apache::lonnet::logthis("getting $id is $value"); }
     $$cache{$id}=$value;      return ($value,1);
 #    &logthis("Caching $id as :$value:");  }
     &save_cache_item($cache,$name,$id);  
     # do_cache implictly return the set value  sub do_cache_new {
     $$cache{$id};      my ($name,$id,$value,$time,$debug) = @_;
 }      $id=&escape($name.':'.$id);
       my $setvalue=$value;
 my %do_save_item;      if (!defined($setvalue)) {
 my %do_save;   $setvalue='__undef__';
 sub save_cache_item {      }
     my ($cache,$name,$id)=@_;      if (!defined($time) ) {
     if ($disk_caching_disabled) { return; }   $time=600;
     $do_save{$name}=$cache;      }
     if (!exists($do_save_item{$name})) { $do_save_item{$name}={} }      if ($debug) { &Apache::lonnet::logthis("Setting $id to $value"); }
     $do_save_item{$name}->{$id}=1;      $memcache->set($id,$setvalue,$time);
       # need to make a copy of $value
       #&make_room($id,$value,$debug);
       return $value;
   }
   
   sub make_room {
       my ($id,$value,$debug)=@_;
       $remembered{$id}=$value;
       if ($to_remember<0) { return; }
       $accessed{$id}=[&gettimeofday()];
       if (scalar(keys(%remembered)) <= $to_remember) { return; }
       my $to_kick;
       my $max_time=0;
       foreach my $other (keys(%accessed)) {
    if (&tv_interval($accessed{$other}) > $max_time) {
       $to_kick=$other;
       $max_time=&tv_interval($accessed{$other});
    }
       }
       delete($remembered{$to_kick});
       delete($accessed{$to_kick});
       $kicks++;
       if ($debug) { &logthis("kicking $to_kick $max_time $kicks\n"); }
     return;      return;
 }  }
   
 sub save_cache {  sub purge_remembered {
     if ($disk_caching_disabled) { return; }      #&logthis("Tossing ".scalar(keys(%remembered)));
     my ($cache,$name,$id);      #&logthis(sprintf("%-20s is %s",'%remembered',length(&freeze(\%remembered))));
     foreach $name (keys(%do_save)) {      undef(%remembered);
  $cache=$do_save{$name};      undef(%accessed);
   
  my $starttime=&Time::HiRes::time();  
  &logthis("Saving :$name:");  
  my %hash;  
  my $filename=$perlvar{'lonDaemons'}.'/tmp/lonnet_internal_cache_'.$name.".db";  
  open(DB,">$filename.lock");  
  flock(DB,LOCK_EX);  
  if (tie(%hash,'GDBM_File',$filename,&GDBM_WRCREAT(),0640)) {  
     foreach $id (keys(%{ $do_save_item{$name} })) {  
  eval <<'EVALBLOCK';  
  $hash{$id.'.time'}=$$cache{$id.'.time'};  
  $hash{$id}=freeze({'item'=>$$cache{$id}});  
  if (exists($$cache{$id.'.file'})) {  
     $hash{$id.'.file'}=freeze({'item'=>$$cache{$id.'.file'}});  
  }  
 EVALBLOCK  
                 if ($@) {  
     &logthis("<font color='red'>save_cache blew up :$@:$name</font>");  
     unlink($filename);  
     last;  
  }  
     }  
  } else {  
     if (-e $filename) {  
  &logthis("Unable to tie hash (save cache): $name ($!)");  
  unlink($filename);  
     }  
  }  
  untie(%hash);  
  flock(DB,LOCK_UN);  
  close(DB);  
  &logthis("save_cache $name took ".(&Time::HiRes::time()-$starttime));  
     }  
     undef(%do_save);  
     undef(%do_save_item);  
   
 }  
   
 sub load_cache_item {  
     my ($cache,$name,$id,$time)=@_;  
     if ($disk_caching_disabled) { return; }  
     my $starttime=&Time::HiRes::time();  
 #    &logthis("Before Loading $name  for $id size is ".scalar(%$cache));  
     my %hash;  
     my $filename=$perlvar{'lonDaemons'}.'/tmp/lonnet_internal_cache_'.$name.".db";  
     if (!-e $filename) { return; }  
     open(DB,">$filename.lock");  
     flock(DB,LOCK_SH);  
     if (tie(%hash,'GDBM_File',$filename,&GDBM_READER(),0640)) {  
  eval <<'EVALBLOCK';  
     if (!%$cache) {  
  my $count;  
  while (my ($key,$value)=each(%hash)) {   
     $count++;  
     if ($key =~ /\.time$/) {  
  $$cache{$key}=$value;  
     } else {  
  my $hashref=thaw($value);  
  $$cache{$key}=$hashref->{'item'};  
     }  
  }  
 #    &logthis("Initial load: $count");  
     } else {  
  if (($$cache{$id.'.time'}+$time) < time) {  
     $$cache{$id.'.time'}=$hash{$id.'.time'};  
     {  
  my $hashref=thaw($hash{$id});  
  $$cache{$id}=$hashref->{'item'};  
     }  
     if (exists($hash{$id.'.file'})) {  
  my $hashref=thaw($hash{$id.'.file'});  
  $$cache{$id.'.file'}=$hashref->{'item'};  
     }  
  }  
     }  
 EVALBLOCK  
         if ($@) {  
     &logthis("<font color='red'>load_cache blew up :$@:$name</font>");  
     unlink($filename);  
  }          
     } else {  
  if (-e $filename) {  
     &logthis("Unable to tie hash (load cache item): $name ($!)");  
     unlink($filename);  
  }  
     }  
     untie(%hash);  
     flock(DB,LOCK_UN);  
     close(DB);  
 #    &logthis("After Loading $name size is ".scalar(%$cache));  
 #    &logthis("load_cache_item $name took ".(&Time::HiRes::time()-$starttime));  
 }  }
   
 # ------------------------------------- Read an entry from a user's environment  # ------------------------------------- Read an entry from a user's environment
   
 sub userenvironment {  sub userenvironment {
Line 1054  sub userenvironment { Line 931  sub userenvironment {
     return %returnhash;      return %returnhash;
 }  }
   
   # ---------------------------------------------------------- Get a studentphoto
   sub studentphoto {
       my ($udom,$unam,$ext) = @_;
       my $home=&Apache::lonnet::homeserver($unam,$udom);
       my $ret=&Apache::lonnet::reply("studentphoto:$udom:$unam:$ext",$home);
       my $url="/uploaded/$udom/$unam/internal/studentphoto.".$ext;
       if ($ret ne 'ok') {
    return '/adm/lonKaputt/lonlogo_broken.gif';
       }
       my $tokenurl=&Apache::lonnet::tokenwrapper($url);
       return $tokenurl;
   }
   
 # -------------------------------------------------------------------- New chat  # -------------------------------------------------------------------- New chat
   
 sub chatsend {  sub chatsend {
     my ($newentry,$anon)=@_;      my ($newentry,$anon)=@_;
     my $cnum=$ENV{'course.'.$ENV{'request.course.id'}.'.num'};      my $cnum=$env{'course.'.$env{'request.course.id'}.'.num'};
     my $cdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};      my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};
     my $chome=$ENV{'course.'.$ENV{'request.course.id'}.'.home'};      my $chome=$env{'course.'.$env{'request.course.id'}.'.home'};
     &reply('chatsend:'.$cdom.':'.$cnum.':'.      &reply('chatsend:'.$cdom.':'.$cnum.':'.
    &escape($ENV{'user.domain'}.':'.$ENV{'user.name'}.':'.$anon.':'.     &escape($env{'user.domain'}.':'.$env{'user.name'}.':'.$anon.':'.
    &escape($newentry)),$chome);     &escape($newentry)),$chome);
 }  }
   
Line 1076  sub getversion { Line 966  sub getversion {
   
 sub currentversion {  sub currentversion {
     my $fname=shift;      my $fname=shift;
     my ($result,$cached)=&is_cached(\%resversioncache,$fname,'resversion',600);      my ($result,$cached)=&is_cached_new('resversion',$fname);
     if (defined($cached)) { return $result; }      if (defined($cached)) { return $result; }
     my $author=$fname;      my $author=$fname;
     $author=~s/\/home\/httpd\/html\/res\/([^\/]*)\/([^\/]*).*/$1\/$2/;      $author=~s/\/home\/httpd\/html\/res\/([^\/]*)\/([^\/]*).*/$1\/$2/;
Line 1089  sub currentversion { Line 979  sub currentversion {
     if (($answer eq 'con_lost') || ($answer eq 'rejected')) {      if (($answer eq 'con_lost') || ($answer eq 'rejected')) {
  return -1;   return -1;
     }      }
     return &do_cache(\%resversioncache,$fname,$answer,'resversion');      return &do_cache_new('resversion',$fname,$answer,600);
 }  }
   
 # ----------------------------- Subscribe to a resource, return URL if possible  # ----------------------------- Subscribe to a resource, return URL if possible
Line 1117  sub subscribe { Line 1007  sub subscribe {
 sub repcopy {  sub repcopy {
     my $filename=shift;      my $filename=shift;
     $filename=~s/\/+/\//g;      $filename=~s/\/+/\//g;
     if ($filename=~m|^/home/httpd/html/adm/|) { return OK; }      if ($filename=~m|^/home/httpd/html/adm/|) { return 'ok'; }
     if ($filename=~m|^/home/httpd/html/lonUsers/|) { return OK; }      if ($filename=~m|^/home/httpd/html/lonUsers/|) { return 'ok'; }
     if ($filename=~m|^/home/httpd/html/userfiles/| or      if ($filename=~m|^/home/httpd/html/userfiles/| or
  $filename=~m|^/*uploaded/|) {    $filename=~m -^/*(uploaded|editupload)/-) { 
  return &repcopy_userfile($filename);   return &repcopy_userfile($filename);
     }      }
     $filename=~s/[\n\r]//g;      $filename=~s/[\n\r]//g;
     my $transname="$filename.in.transfer";      my $transname="$filename.in.transfer";
     if ((-e $filename) || (-e $transname)) { return OK; }      if ((-e $filename) || (-e $transname)) { return 'ok'; }
     my $remoteurl=subscribe($filename);      my $remoteurl=subscribe($filename);
     if ($remoteurl =~ /^con_lost by/) {      if ($remoteurl =~ /^con_lost by/) {
    &logthis("Subscribe returned $remoteurl: $filename");     &logthis("Subscribe returned $remoteurl: $filename");
            return HTTP_SERVICE_UNAVAILABLE;             return 'unavailable';
     } elsif ($remoteurl eq 'not_found') {      } elsif ($remoteurl eq 'not_found') {
    #&logthis("Subscribe returned not_found: $filename");     #&logthis("Subscribe returned not_found: $filename");
    return HTTP_NOT_FOUND;     return 'not_found';
     } elsif ($remoteurl =~ /^rejected by/) {      } elsif ($remoteurl =~ /^rejected by/) {
    &logthis("Subscribe returned $remoteurl: $filename");     &logthis("Subscribe returned $remoteurl: $filename");
            return FORBIDDEN;             return 'forbidden';
     } elsif ($remoteurl eq 'directory') {      } elsif ($remoteurl eq 'directory') {
            return OK;             return 'ok';
     } else {      } else {
         my $author=$filename;          my $author=$filename;
         $author=~s/\/home\/httpd\/html\/res\/([^\/]*)\/([^\/]*).*/$1\/$2/;          $author=~s/\/home\/httpd\/html\/res\/([^\/]*)\/([^\/]*).*/$1\/$2/;
Line 1148  sub repcopy { Line 1038  sub repcopy {
            my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]";             my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]";
            if ($path ne "$perlvar{'lonDocRoot'}/res") {             if ($path ne "$perlvar{'lonDocRoot'}/res") {
                &logthis("Malconfiguration for replication: $filename");                 &logthis("Malconfiguration for replication: $filename");
        return HTTP_BAD_REQUEST;         return 'bad_request';
            }             }
            my $count;             my $count;
            for ($count=5;$count<$#parts;$count++) {             for ($count=5;$count<$#parts;$count++) {
Line 1165  sub repcopy { Line 1055  sub repcopy {
                my $message=$response->status_line;                 my $message=$response->status_line;
                &logthis("<font color=blue>WARNING:"                 &logthis("<font color=blue>WARNING:"
                        ." LWP get: $message: $filename</font>");                         ." LWP get: $message: $filename</font>");
                return HTTP_SERVICE_UNAVAILABLE;                 return 'unavailable';
            } else {             } else {
        if ($remoteurl!~/\.meta$/) {         if ($remoteurl!~/\.meta$/) {
                   my $mrequest=new HTTP::Request('GET',$remoteurl.'.meta');                    my $mrequest=new HTTP::Request('GET',$remoteurl.'.meta');
Line 1177  sub repcopy { Line 1067  sub repcopy {
                   }                    }
        }         }
                rename($transname,$filename);                 rename($transname,$filename);
                return OK;                 return 'ok';
            }             }
        }         }
     }      }
Line 1186  sub repcopy { Line 1076  sub repcopy {
 # ------------------------------------------------ Get server side include body  # ------------------------------------------------ Get server side include body
 sub ssi_body {  sub ssi_body {
     my ($filelink,%form)=@_;      my ($filelink,%form)=@_;
       if (! exists($form{'LONCAPA_INTERNAL_no_discussion'})) {
           $form{'LONCAPA_INTERNAL_no_discussion'}='true';
       }
     my $output=($filelink=~/^http\:/?&externalssi($filelink):      my $output=($filelink=~/^http\:/?&externalssi($filelink):
                                      &ssi($filelink,%form));                                       &ssi($filelink,%form));
     $output=~s|//(\s*<!--)? BEGIN LON-CAPA Internal.+// END LON-CAPA Internal\s*(-->)?\s||gs;      $output=~s|//(\s*<!--)? BEGIN LON-CAPA Internal.+// END LON-CAPA Internal\s*(-->)?\s||gs;
Line 1239  sub allowuploaded { Line 1132  sub allowuploaded {
 }  }
   
 # --------- File operations in /home/httpd/html/userfiles/$domain/1/2/3/$course  # --------- File operations in /home/httpd/html/userfiles/$domain/1/2/3/$course
 # input: action, courseID, current domain, home server for course, intended  # input: action, courseID, current domain, intended
 #        path to file, source of file.  #        path to file, source of file, instruction to parse file for objects,
   #        ref to hash for embedded objects,
   #        ref to hash for codebase of java objects.
   #
 # output: url to file (if action was uploaddoc),   # output: url to file (if action was uploaddoc), 
 #         ok if successful, or diagnostic message otherwise (if action was propagate or copy)  #         ok if successful, or diagnostic message otherwise (if action was propagate or copy)
 #  #
Line 1259  sub allowuploaded { Line 1155  sub allowuploaded {
 #         course's home server.  #         course's home server.
 #  #
 # action = uploaddoc - /home/httpd/html/userfiles/$domain/1/2/3/$course/$file  # action = uploaddoc - /home/httpd/html/userfiles/$domain/1/2/3/$course/$file
 #         will be retrived from $ENV{form.uploaddoc} (from DOCS interface) to  #         will be retrived from $env{form.uploaddoc} (from DOCS interface) to
 #         /home/httpd/html/userfiles/$domain/1/2/3/$course/$file  #         /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  #         and will then be copied to /home/httpd/lonUsers/1/2/3/$course/userfiles/$file
 #         in course's home server.  #         in course's home server.
   #
   
 sub process_coursefile {  sub process_coursefile {
     my ($action,$docuname,$docudom,$docuhome,$file,$source)=@_;      my ($action,$docuname,$docudom,$file,$source,$parser,$allfiles,$codebase)=@_;
     my $fetchresult;      my $fetchresult;
       my $home=&homeserver($docuname,$docudom);
     if ($action eq 'propagate') {      if ($action eq 'propagate') {
         $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file          $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file,
                             ,$docuhome);       $home);
     } else {      } 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 = &build_filepath($fpath);
         unless ($fpath eq '') {  
             my @parts=split('/',$fpath);  
             foreach my $part (@parts) {  
                 $filepath.= '/'.$part;  
                 if ((-e $filepath)!=1) {  
                     mkdir($filepath,0777);  
                 }  
             }  
         }  
         if ($action eq 'copy') {          if ($action eq 'copy') {
             if ($source eq '') {              if ($source eq '') {
                 $fetchresult = 'no source file';                  $fetchresult = 'no source file';
Line 1295  sub process_coursefile { Line 1183  sub process_coursefile {
                 my $destination = $filepath.'/'.$fname;                  my $destination = $filepath.'/'.$fname;
                 rename($source,$destination);                  rename($source,$destination);
                 $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file,                  $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file,
                                  $docuhome);                                   $home);
             }              }
         } elsif ($action eq 'uploaddoc') {          } elsif ($action eq 'uploaddoc') {
             open(my $fh,'>'.$filepath.'/'.$fname);              open(my $fh,'>'.$filepath.'/'.$fname);
             print $fh $ENV{'form.'.$source};              print $fh $env{'form.'.$source};
             close($fh);              close($fh);
               if ($parser eq 'parse') {
                   my $parse_result = &extract_embedded_items($filepath,$fname,$allfiles,$codebase);
                   unless ($parse_result eq 'ok') {
                       &logthis('Failed to parse '.$filepath.'/'.$fname.' for embedded media: '.$parse_result);
                   }
               }
             $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file,              $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file,
                                  $docuhome);                                   $home);
             if ($fetchresult eq 'ok') {              if ($fetchresult eq 'ok') {
                 return '/uploaded/'.$fpath.'/'.$fname;                  return '/uploaded/'.$fpath.'/'.$fname;
             } else {              } else {
                 &logthis('Failed to transfer '.$docudom.'/'.$docuname.'/'.$file.                  &logthis('Failed to transfer '.$docudom.'/'.$docuname.'/'.$file.
                         ' to host '.$docuhome.': '.$fetchresult);                          ' to host '.$home.': '.$fetchresult);
                 return '/adm/notfound.html';                  return '/adm/notfound.html';
             }              }
         }          }
     }      }
     unless ( $fetchresult eq 'ok') {      unless ( $fetchresult eq 'ok') {
         &logthis('Failed to transfer '.$docudom.'/'.$docuname.'/'.$file.          &logthis('Failed to transfer '.$docudom.'/'.$docuname.'/'.$file.
              ' to host '.$docuhome.': '.$fetchresult);               ' to host '.$home.': '.$fetchresult);
     }      }
     return $fetchresult;      return $fetchresult;
 }  }
   
 # --------------- Take an uploaded file and put it into the userfiles directory  sub build_filepath {
 # input: name of form element, coursedoc=1 means this is for the course      my ($fpath) = @_;
 # output: url of file in userspace      my $filepath=$perlvar{'lonDocRoot'}.'/userfiles';
       unless ($fpath eq '') {
           my @parts=split('/',$fpath);
           foreach my $part (@parts) {
               $filepath.= '/'.$part;
               if ((-e $filepath)!=1) {
                   mkdir($filepath,0777);
               }
           }
       }
       return $filepath;
   }
   
   sub store_edited_file {
       my ($primary_url,$content,$docudom,$docuname,$fetchresult) = @_;
       my $file = $primary_url;
       $file =~ s#^/uploaded/$docudom/$docuname/##;
       my $fpath = '';
       my $fname = $file;
       ($fpath,$fname) = ($file =~ m|^(.*)/([^/]+)$|);
       $fpath=$docudom.'/'.$docuname.'/'.$fpath;
       my $filepath = &build_filepath($fpath);
       open(my $fh,'>'.$filepath.'/'.$fname);
       print $fh $content;
       close($fh);
       my $home=&homeserver($docuname,$docudom);
       $$fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file,
     $home);
       if ($$fetchresult eq 'ok') {
           return '/uploaded/'.$fpath.'/'.$fname;
       } else {
           &logthis('Failed to transfer '.$docudom.'/'.$docuname.'/'.$file.
    ' to host '.$home.': '.$$fetchresult);
           return '/adm/notfound.html';
       }
   }
   
 sub clean_filename {  sub clean_filename {
     my ($fname)=@_;      my ($fname)=@_;
Line 1339  sub clean_filename { Line 1268  sub clean_filename {
     return $fname;      return $fname;
 }  }
   
   # --------------- 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
   
   
 sub userfileupload {  sub userfileupload {
     my ($formname,$coursedoc,$subdir)=@_;      my ($formname,$coursedoc,$subdir,$parser,$allfiles,$codebase)=@_;
     if (!defined($subdir)) { $subdir='unknown'; }      if (!defined($subdir)) { $subdir='unknown'; }
     my $fname=$ENV{'form.'.$formname.'.filename'};      my $fname=$env{'form.'.$formname.'.filename'};
     $fname=&clean_filename($fname);      $fname=&clean_filename($fname);
 # 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      if (($formname eq 'screenshot') && ($subdir eq 'helprequests')) { #files uploaded to help request form are handled differently
         my $now = time;          my $now = time;
         my $filepath = 'tmp/helprequests/'.$now;          my $filepath = 'tmp/helprequests/'.$now;
Line 1359  sub userfileupload { Line 1293  sub userfileupload {
             }              }
         }          }
         open(my $fh,'>'.$fullpath.'/'.$fname);          open(my $fh,'>'.$fullpath.'/'.$fname);
         print $fh $ENV{'form.'.$formname};          print $fh $env{'form.'.$formname};
         close($fh);          close($fh);
         return $fullpath.'/'.$fname;           return $fullpath.'/'.$fname; 
     }      }
 # Create the directory if not present  # Create the directory if not present
     my $docuname='';  
     my $docudom='';  
     my $docuhome='';  
     $fname="$subdir/$fname";      $fname="$subdir/$fname";
     if ($coursedoc) {      if ($coursedoc) {
  $docuname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'};   my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
  $docudom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};   my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
  $docuhome=$ENV{'course.'.$ENV{'request.course.id'}.'.home'};          if ($env{'form.folder'} =~ m/^(default|supplemental)/) {
         if ($ENV{'form.folder'} =~ m/^default/) {              return &finishuserfileupload($docuname,$docudom,
             return &finishuserfileupload($docuname,$docudom,$docuhome,$formname,$fname);   $formname,$fname,$parser,$allfiles,
    $codebase);
         } else {          } else {
             $fname=$ENV{'form.folder'}.'/'.$fname;              $fname=$env{'form.folder'}.'/'.$fname;
             return &process_coursefile('uploaddoc',$docuname,$docudom,$docuhome,$fname,$formname);              return &process_coursefile('uploaddoc',$docuname,$docudom,
          $fname,$formname,$parser,
          $allfiles,$codebase);
         }          }
     } else {      } else {
         $docuname=$ENV{'user.name'};          my $docuname=$env{'user.name'};
         $docudom=$ENV{'user.domain'};          my $docudom=$env{'user.domain'};
         $docuhome=$ENV{'user.home'};   return &finishuserfileupload($docuname,$docudom,$formname,
         return &finishuserfileupload($docuname,$docudom,$docuhome,$formname,$fname);       $fname,$parser,$allfiles,$codebase);
     }      }
 }  }
   
 sub finishuserfileupload {  sub finishuserfileupload {
     my ($docuname,$docudom,$docuhome,$formname,$fname)=@_;      my ($docuname,$docudom,$formname,$fname,$parser,$allfiles,$codebase) = @_;
     my $path=$docudom.'/'.$docuname.'/';      my $path=$docudom.'/'.$docuname.'/';
     my $filepath=$perlvar{'lonDocRoot'};      my $filepath=$perlvar{'lonDocRoot'};
     my ($fnamepath,$file);      my ($fnamepath,$file);
Line 1407  sub finishuserfileupload { Line 1341  sub finishuserfileupload {
 # Save the file  # Save the file
     {      {
  open(FH,'>'.$filepath.'/'.$file);   open(FH,'>'.$filepath.'/'.$file);
  print FH $ENV{'form.'.$formname};   print FH $env{'form.'.$formname};
  close(FH);   close(FH);
     }      }
       if ($parser eq 'parse') {
           my $parse_result = &extract_embedded_items($filepath,$file,$allfiles,
      $codebase);
           unless ($parse_result eq 'ok') {
               &logthis('Failed to parse '.$filepath.$file.
        ' for embedded media: '.$parse_result); 
           }
       }
 # Notify homeserver to grep it  # Notify homeserver to grep it
 #  #
     &Apache::lonnet::logthis("fetching ".$path.$file);      my $docuhome=&homeserver($docuname,$docudom);
     my $fetchresult= &reply('fetchuserfile:'.$path.$file,$docuhome);      my $fetchresult= &reply('fetchuserfile:'.$path.$file,$docuhome);
     if ($fetchresult eq 'ok') {      if ($fetchresult eq 'ok') {
 #  #
Line 1425  sub finishuserfileupload { Line 1367  sub finishuserfileupload {
     }          }    
 }  }
   
   sub extract_embedded_items {
       my ($filepath,$file,$allfiles,$codebase,$content) = @_;
       my @state = ();
       my %javafiles = (
                         codebase => '',
                         code => '',
                         archive => ''
                       );
       my %mediafiles = (
                         src => '',
                         movie => '',
                        );
       my $p;
       if ($content) {
           $p = HTML::LCParser->new($content);
       } else {
           $p = HTML::LCParser->new($filepath.'/'.$file);
       }
       while (my $t=$p->get_token()) {
    if ($t->[0] eq 'S') {
       my ($tagname, $attr) = ($t->[1],$t->[2]);
       push (@state, $tagname);
               if (lc($tagname) eq 'allow') {
                   &add_filetype($allfiles,$attr->{'src'},'src');
               }
       if (lc($tagname) eq 'img') {
    &add_filetype($allfiles,$attr->{'src'},'src');
       }
               if (lc($tagname) eq 'script') {
                   if ($attr->{'archive'} =~ /\.jar$/i) {
                       &add_filetype($allfiles,$attr->{'archive'},'archive');
                   } else {
                       &add_filetype($allfiles,$attr->{'src'},'src');
                   }
               }
               if (lc($tagname) eq 'link') {
                   if (lc($attr->{'rel'}) eq 'stylesheet') { 
                       &add_filetype($allfiles,$attr->{'href'},'href');
                   }
               }
       if (lc($tagname) eq 'object' ||
    (lc($tagname) eq 'embed' && lc($state[-2]) ne 'object')) {
    foreach my $item (keys(%javafiles)) {
       $javafiles{$item} = '';
    }
       }
       if (lc($state[-2]) eq 'object' && lc($tagname) eq 'param') {
    my $name = lc($attr->{'name'});
    foreach my $item (keys(%javafiles)) {
       if ($name eq $item) {
    $javafiles{$item} = $attr->{'value'};
    last;
       }
    }
    foreach my $item (keys(%mediafiles)) {
       if ($name eq $item) {
    &add_filetype($allfiles, $attr->{'value'}, 'value');
    last;
       }
    }
       }
       if (lc($tagname) eq 'embed' || lc($tagname) eq 'applet') {
    foreach my $item (keys(%javafiles)) {
       if ($attr->{$item}) {
    $javafiles{$item} = $attr->{$item};
    last;
       }
    }
    foreach my $item (keys(%mediafiles)) {
       if ($attr->{$item}) {
    &add_filetype($allfiles,$attr->{$item},$item);
    last;
       }
    }
       }
    } elsif ($t->[0] eq 'E') {
       my ($tagname) = ($t->[1]);
       if ($javafiles{'codebase'} ne '') {
    $javafiles{'codebase'} .= '/';
       }  
       if (lc($tagname) eq 'applet' ||
    lc($tagname) eq 'object' ||
    (lc($tagname) eq 'embed' && lc($state[-2]) ne 'object')
    ) {
    foreach my $item (keys(%javafiles)) {
       if ($item ne 'codebase' && $javafiles{$item} ne '') {
    my $file=$javafiles{'codebase'}.$javafiles{$item};
    &add_filetype($allfiles,$file,$item);
       }
    }
       } 
       pop @state;
    }
       }
       return 'ok';
   }
   
   sub add_filetype {
       my ($allfiles,$file,$type)=@_;
       if (exists($allfiles->{$file})) {
    unless (grep/^\Q$type\E$/, @{$allfiles->{$file}}) {
       push(@{$allfiles->{$file}}, &escape($type));
    }
       } else {
    @{$allfiles->{$file}} = (&escape($type));
       }
   }
   
 sub removeuploadedurl {  sub removeuploadedurl {
     my ($url)=@_;      my ($url)=@_;
     my (undef,undef,$udom,$uname,$fname)=split('/',$url,5);      my (undef,undef,$udom,$uname,$fname)=split('/',$url,5);
     return &Apache::lonnet::removeuserfile($uname,$udom,$fname);      return &removeuserfile($uname,$udom,$fname);
 }  }
   
 sub removeuserfile {  sub removeuserfile {
Line 1514  sub flushcourselogs { Line 1564  sub flushcourselogs {
             ($dom,$name,undef)=($entry=~m:___(\w+)/(\w+)/(.*)___count$:);              ($dom,$name,undef)=($entry=~m:___(\w+)/(\w+)/(.*)___count$:);
             if (! defined($dom) || $dom eq '' ||               if (! defined($dom) || $dom eq '' || 
                 ! defined($name) || $name eq '') {                  ! defined($name) || $name eq '') {
                 my $cid = $ENV{'request.course.id'};                  my $cid = $env{'request.course.id'};
                 $dom  = $ENV{'request.'.$cid.'.domain'};                  $dom  = $env{'request.'.$cid.'.domain'};
                 $name = $ENV{'request.'.$cid.'.num'};                  $name = $env{'request.'.$cid.'.num'};
             }              }
             my $value = $accesshash{$entry};              my $value = $accesshash{$entry};
             my (undef,$url,undef) = ($entry =~ /^(.*)___(.*)___count$/);              my (undef,$url,undef) = ($entry =~ /^(.*)___(.*)___count$/);
Line 1559  sub flushcourselogs { Line 1609  sub flushcourselogs {
 sub courselog {  sub courselog {
     my $what=shift;      my $what=shift;
     $what=time.':'.$what;      $what=time.':'.$what;
     unless ($ENV{'request.course.id'}) { return ''; }      unless ($env{'request.course.id'}) { return ''; }
     $coursedombuf{$ENV{'request.course.id'}}=      $coursedombuf{$env{'request.course.id'}}=
        $ENV{'course.'.$ENV{'request.course.id'}.'.domain'};         $env{'course.'.$env{'request.course.id'}.'.domain'};
     $coursenumbuf{$ENV{'request.course.id'}}=      $coursenumbuf{$env{'request.course.id'}}=
        $ENV{'course.'.$ENV{'request.course.id'}.'.num'};         $env{'course.'.$env{'request.course.id'}.'.num'};
     $coursehombuf{$ENV{'request.course.id'}}=      $coursehombuf{$env{'request.course.id'}}=
        $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'}}=      $courseinstcodebuf{$env{'request.course.id'}}=
        $ENV{'course.'.$ENV{'request.course.id'}.'.internal.coursecode'};         $env{'course.'.$env{'request.course.id'}.'.internal.coursecode'};
     $courseownerbuf{$ENV{'request.course.id'}}=      $courseownerbuf{$env{'request.course.id'}}=
        $ENV{'course.'.$ENV{'request.course.id'}.'.internal.courseowner'};         $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'};
     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 {
  $courselogs{$ENV{'request.course.id'}}.=$what;   $courselogs{$env{'request.course.id'}}.=$what;
     }      }
     if (length($courselogs{$ENV{'request.course.id'}})>4048) {      if (length($courselogs{$env{'request.course.id'}})>4048) {
  &flushcourselogs();   &flushcourselogs();
     }      }
 }  }
   
 sub courseacclog {  sub courseacclog {
     my $fnsymb=shift;      my $fnsymb=shift;
     unless ($ENV{'request.course.id'}) { return ''; }      unless ($env{'request.course.id'}) { return ''; }
     my $what=$fnsymb.':'.$ENV{'user.name'}.':'.$ENV{'user.domain'};      my $what=$fnsymb.':'.$env{'user.name'}.':'.$env{'user.domain'};
     if ($fnsymb=~/(problem|exam|quiz|assess|survey|form|page)$/) {      if ($fnsymb=~/(problem|exam|quiz|assess|survey|form|page)$/) {
         $what.=':POST';          $what.=':POST';
         # FIXME: Probably ought to escape things....          # FIXME: Probably ought to escape things....
  foreach (keys %ENV) {   foreach (keys %env) {
             if ($_=~/^form\.(.*)/) {              if ($_=~/^form\.(.*)/) {
  $what.=':'.$1.'='.$ENV{$_};   $what.=':'.$1.'='.$env{$_};
             }              }
         }          }
     } elsif ($fnsymb =~ m:^/adm/searchcat:) {      } elsif ($fnsymb =~ m:^/adm/searchcat:) {
         # FIXME: We should not be depending on a form parameter that someone          # FIXME: We should not be depending on a form parameter that someone
         # editing lonsearchcat.pm might change in the future.          # editing lonsearchcat.pm might change in the future.
         if ($ENV{'form.phase'} eq 'course_search') {          if ($env{'form.phase'} eq 'course_search') {
             $what.= ':POST';              $what.= ':POST';
             # FIXME: Probably ought to escape things....              # FIXME: Probably ought to escape things....
             foreach my $element ('courseexp','crsfulltext','crsrelated',              foreach my $element ('courseexp','crsfulltext','crsrelated',
                                  'crsdiscuss') {                                   'crsdiscuss') {
                 $what.=':'.$element.'='.$ENV{'form.'.$element};                  $what.=':'.$element.'='.$env{'form.'.$element};
             }              }
         }          }
     }      }
Line 1612  sub courseacclog { Line 1662  sub courseacclog {
 sub countacc {  sub countacc {
     my $url=&declutter(shift);      my $url=&declutter(shift);
     return if (! defined($url) || $url eq '');      return if (! defined($url) || $url eq '');
     unless ($ENV{'request.course.id'}) { return ''; }      unless ($env{'request.course.id'}) { return ''; }
     $accesshash{$ENV{'request.course.id'}.'___'.$url.'___course'}=1;      $accesshash{$env{'request.course.id'}.'___'.$url.'___course'}=1;
     my $key=$$.$processmarker.'_'.$dumpcount.'___'.$url.'___count';      my $key=$$.$processmarker.'_'.$dumpcount.'___'.$url.'___count';
     $accesshash{$key}++;      $accesshash{$key}++;
 }  }
Line 1640  sub userrolelog { Line 1690  sub userrolelog {
   
 sub get_course_adv_roles {  sub get_course_adv_roles {
     my $cid=shift;      my $cid=shift;
     $cid=$ENV{'request.course.id'} unless (defined($cid));      $cid=$env{'request.course.id'} unless (defined($cid));
     my %coursehash=&coursedescription($cid);      my %coursehash=&coursedescription($cid);
     my %nothide=();      my %nothide=();
     foreach (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) {      foreach (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) {
Line 1672  sub get_course_adv_roles { Line 1722  sub get_course_adv_roles {
   
 sub get_my_roles {  sub get_my_roles {
     my ($uname,$udom)=@_;      my ($uname,$udom)=@_;
     unless (defined($uname)) { $uname=$ENV{'user.name'}; }      unless (defined($uname)) { $uname=$env{'user.name'}; }
     unless (defined($udom)) { $udom=$ENV{'user.domain'}; }      unless (defined($udom)) { $udom=$env{'user.domain'}; }
     my %dumphash=      my %dumphash=
             &dump('nohist_userroles',$udom,$uname);              &dump('nohist_userroles',$udom,$uname);
     my %returnhash=();      my %returnhash=();
Line 1728  sub courseidput { Line 1778  sub courseidput {
 }  }
   
 sub courseiddump {  sub courseiddump {
     my ($domfilter,$descfilter,$sincefilter,$instcodefilter,$ownerfilter,$hostidflag,$hostidref)=@_;      my ($domfilter,$descfilter,$sincefilter,$instcodefilter,$ownerfilter,$coursefilter,$hostidflag,$hostidref)=@_;
     my %returnhash=();      my %returnhash=();
     unless ($domfilter) { $domfilter=''; }      unless ($domfilter) { $domfilter=''; }
     foreach my $tryserver (keys %libserv) {      foreach my $tryserver (keys %libserv) {
Line 1737  sub courseiddump { Line 1787  sub courseiddump {
         foreach (          foreach (
                  split(/\&/,&reply('courseiddump:'.$hostdom{$tryserver}.':'.                   split(/\&/,&reply('courseiddump:'.$hostdom{$tryserver}.':'.
        $sincefilter.':'.&escape($descfilter).':'.         $sincefilter.':'.&escape($descfilter).':'.
                                &escape($instcodefilter).':'.&escape($ownerfilter),                                 &escape($instcodefilter).':'.&escape($ownerfilter).':'.&escape($coursefilter),
                                $tryserver))) {                                 $tryserver))) {
     my ($key,$value)=split(/\=/,$_);      my ($key,$value)=split(/\=/,$_);
                     if (($key) && ($value)) {                      if (($key) && ($value)) {
Line 1758  sub get_first_access { Line 1808  sub get_first_access {
     my ($symb,$courseid,$udom,$uname)=&Apache::lonxml::whichuser();      my ($symb,$courseid,$udom,$uname)=&Apache::lonxml::whichuser();
     if ($argsymb) { $symb=$argsymb; }      if ($argsymb) { $symb=$argsymb; }
     my ($map,$id,$res)=&decode_symb($symb);      my ($map,$id,$res)=&decode_symb($symb);
     if ($type eq 'map') { $res=$map; }      if ($type eq 'map') {
     my %times=&get('firstaccesstimes',[$res],$udom,$uname);   $res=&symbread($map);
     return $times{$res};      } else {
    $res=$symb;
       }
       my %times=&get('firstaccesstimes',["$courseid\0$res"],$udom,$uname);
       return $times{"$courseid\0$res"};
 }  }
   
 sub set_first_access {  sub set_first_access {
     my ($type)=@_;      my ($type)=@_;
     my ($symb,$courseid,$udom,$uname)=&Apache::lonxml::whichuser();      my ($symb,$courseid,$udom,$uname)=&Apache::lonxml::whichuser();
     my ($map,$id,$res)=&decode_symb($symb);      my ($map,$id,$res)=&decode_symb($symb);
     if ($type eq 'map') { $res=$map; }      if ($type eq 'map') {
     my $firstaccess=&get_first_access($type);   $res=&symbread($map);
       } else {
    $res=$symb;
       }
       my $firstaccess=&get_first_access($type,$symb);
     if (!$firstaccess) {      if (!$firstaccess) {
  return &put('firstaccesstimes',{$res=>time},$udom,$uname);   return &put('firstaccesstimes',{"$courseid\0$res"=>time},$udom,$uname);
     }      }
     return 'already_set';      return 'already_set';
 }  }
Line 1828  sub checkin { Line 1886  sub checkin {
     my $now=time;      my $now=time;
     my ($ta,$tb,$lonhost)=split(/\*/,$token);      my ($ta,$tb,$lonhost)=split(/\*/,$token);
     $lonhost=~tr/A-Z/a-z/;      $lonhost=~tr/A-Z/a-z/;
     my $dtoken=$ta.'_'.$hostip{$lonhost}.'_'.$tb;      my $dtoken=$ta.'_'.$hostname{$lonhost}.'_'.$tb;
     $dtoken=~s/\W/\_/g;      $dtoken=~s/\W/\_/g;
     my ($dummy,$tuname,$tudom,$tcrsid,$symb,$chtim,$rmaddr)=      my ($dummy,$tuname,$tudom,$tcrsid,$symb,$chtim,$rmaddr)=
                  split(/\&/,&unescape(&reply('tmpget:'.$dtoken,$lonhost)));                   split(/\&/,&unescape(&reply('tmpget:'.$dtoken,$lonhost)));
Line 1840  sub checkin { Line 1898  sub checkin {
           
     unless (&allowed('mgr',$tcrsid)) {      unless (&allowed('mgr',$tcrsid)) {
         &logthis('Check in '.$token.' ('.$dtoken.') unauthorized: '.          &logthis('Check in '.$token.' ('.$dtoken.') unauthorized: '.
                  $ENV{'user.name'}.' - '.$ENV{'user.domain'});                   $env{'user.name'}.' - '.$env{'user.domain'});
         return '';          return '';
     }      }
   
Line 1864  sub checkin { Line 1922  sub checkin {
   
 sub expirespread {  sub expirespread {
     my ($uname,$udom,$stype,$usymb)=@_;      my ($uname,$udom,$stype,$usymb)=@_;
     my $cid=$ENV{'request.course.id'};       my $cid=$env{'request.course.id'}; 
     if ($cid) {      if ($cid) {
        my $now=time;         my $now=time;
        my $key=$uname.':'.$udom.':'.$stype.':'.$usymb;         my $key=$uname.':'.$udom.':'.$stype.':'.$usymb;
        return &reply('put:'.$ENV{'course.'.$cid.'.domain'}.':'.         return &reply('put:'.$env{'course.'.$cid.'.domain'}.':'.
                             $ENV{'course.'.$cid.'.num'}.                              $env{'course.'.$cid.'.num'}.
             ':nohist_expirationdates:'.              ':nohist_expirationdates:'.
                             &escape($key).'='.$now,                              &escape($key).'='.$now,
                             $ENV{'course.'.$cid.'.home'})                              $env{'course.'.$cid.'.home'})
     }      }
     return 'ok';      return 'ok';
 }  }
Line 1881  sub expirespread { Line 1939  sub expirespread {
   
 sub devalidate {  sub devalidate {
     my ($symb,$uname,$udom)=@_;      my ($symb,$uname,$udom)=@_;
     my $cid=$ENV{'request.course.id'};       my $cid=$env{'request.course.id'}; 
     if ($cid) {      if ($cid) {
         # delete the stored spreadsheets for          # delete the stored spreadsheets for
         # - the student level sheet of this user in course's homespace          # - the student level sheet of this user in course's homespace
Line 1892  sub devalidate { Line 1950  sub devalidate {
         my $status=          my $status=
     &del('nohist_calculatedsheets',      &del('nohist_calculatedsheets',
  [$key.'studentcalc:'],   [$key.'studentcalc:'],
  $ENV{'course.'.$cid.'.domain'},   $env{'course.'.$cid.'.domain'},
  $ENV{'course.'.$cid.'.num'})   $env{'course.'.$cid.'.num'})
  .' '.   .' '.
     &del('nohist_calculatedsheets_'.$cid,      &del('nohist_calculatedsheets_'.$cid,
  [$key.'assesscalc:'.$symb],$udom,$uname);   [$key.'assesscalc:'.$symb],$udom,$uname);
Line 2103  sub tmpreset { Line 2161  sub tmpreset {
   my ($symb,$namespace,$domain,$stuname) = @_;    my ($symb,$namespace,$domain,$stuname) = @_;
   if (!$symb) {    if (!$symb) {
     $symb=&symbread();      $symb=&symbread();
     if (!$symb) { $symb= $ENV{'request.url'}; }      if (!$symb) { $symb= $env{'request.url'}; }
   }    }
   $symb=escape($symb);    $symb=escape($symb);
   
   if (!$namespace) { $namespace=$ENV{'request.state'}; }    if (!$namespace) { $namespace=$env{'request.state'}; }
   $namespace=~s/\//\_/g;    $namespace=~s/\//\_/g;
   $namespace=~s/\W//g;    $namespace=~s/\W//g;
   
   #FIXME needs to do something for /pub resources    if (!$domain) { $domain=$env{'user.domain'}; }
   if (!$domain) { $domain=$ENV{'user.domain'}; }    if (!$stuname) { $stuname=$env{'user.name'}; }
   if (!$stuname) { $stuname=$ENV{'user.name'}; }    if ($domain eq 'public' && $stuname eq 'public') {
         $stuname=$ENV{'REMOTE_ADDR'};
     }
   my $path=$perlvar{'lonDaemons'}.'/tmp';    my $path=$perlvar{'lonDaemons'}.'/tmp';
   my %hash;    my %hash;
   if (tie(%hash,'GDBM_File',    if (tie(%hash,'GDBM_File',
Line 2132  sub tmpstore { Line 2192  sub tmpstore {
   
   if (!$symb) {    if (!$symb) {
     $symb=&symbread();      $symb=&symbread();
     if (!$symb) { $symb= $ENV{'request.url'}; }      if (!$symb) { $symb= $env{'request.url'}; }
   }    }
   $symb=escape($symb);    $symb=escape($symb);
   
   if (!$namespace) {    if (!$namespace) {
     # I don't think we would ever want to store this for a course.      # I don't think we would ever want to store this for a course.
     # it seems this will only be used if we don't have a course.      # it seems this will only be used if we don't have a course.
     #$namespace=$ENV{'request.course.id'};      #$namespace=$env{'request.course.id'};
     #if (!$namespace) {      #if (!$namespace) {
       $namespace=$ENV{'request.state'};        $namespace=$env{'request.state'};
     #}      #}
   }    }
   $namespace=~s/\//\_/g;    $namespace=~s/\//\_/g;
   $namespace=~s/\W//g;    $namespace=~s/\W//g;
 #FIXME needs to do something for /pub resources    if (!$domain) { $domain=$env{'user.domain'}; }
   if (!$domain) { $domain=$ENV{'user.domain'}; }    if (!$stuname) { $stuname=$env{'user.name'}; }
   if (!$stuname) { $stuname=$ENV{'user.name'}; }    if ($domain eq 'public' && $stuname eq 'public') {
         $stuname=$ENV{'REMOTE_ADDR'};
     }
   my $now=time;    my $now=time;
   my %hash;    my %hash;
   my $path=$perlvar{'lonDaemons'}.'/tmp';    my $path=$perlvar{'lonDaemons'}.'/tmp';
Line 2160  sub tmpstore { Line 2222  sub tmpstore {
     my $allkeys='';       my $allkeys=''; 
     foreach my $key (keys(%$storehash)) {      foreach my $key (keys(%$storehash)) {
       $allkeys.=$key.':';        $allkeys.=$key.':';
       $hash{"$version:$symb:$key"}=$$storehash{$key};        $hash{"$version:$symb:$key"}=&freeze_escape($$storehash{$key});
     }      }
     $hash{"$version:$symb:timestamp"}=$now;      $hash{"$version:$symb:timestamp"}=$now;
     $allkeys.='timestamp';      $allkeys.='timestamp';
Line 2182  sub tmprestore { Line 2244  sub tmprestore {
   
   if (!$symb) {    if (!$symb) {
     $symb=&symbread();      $symb=&symbread();
     if (!$symb) { $symb= $ENV{'request.url'}; }      if (!$symb) { $symb= $env{'request.url'}; }
   }    }
   $symb=escape($symb);    $symb=escape($symb);
   
   if (!$namespace) { $namespace=$ENV{'request.state'}; }    if (!$namespace) { $namespace=$env{'request.state'}; }
   #FIXME needs to do something for /pub resources  
   if (!$domain) { $domain=$ENV{'user.domain'}; }  
   if (!$stuname) { $stuname=$ENV{'user.name'}; }  
   
     if (!$domain) { $domain=$env{'user.domain'}; }
     if (!$stuname) { $stuname=$env{'user.name'}; }
     if ($domain eq 'public' && $stuname eq 'public') {
         $stuname=$ENV{'REMOTE_ADDR'};
     }
   my %returnhash;    my %returnhash;
   $namespace=~s/\//\_/g;    $namespace=~s/\//\_/g;
   $namespace=~s/\W//g;    $namespace=~s/\W//g;
Line 2208  sub tmprestore { Line 2272  sub tmprestore {
       my $key;        my $key;
       $returnhash{"$scope:keys"}=$vkeys;        $returnhash{"$scope:keys"}=$vkeys;
       foreach $key (@keys) {        foreach $key (@keys) {
  $returnhash{"$scope:$key"}=$hash{"$scope:$symb:$key"};   $returnhash{"$scope:$key"}=&thaw_unescape($hash{"$scope:$symb:$key"});
  $returnhash{"$key"}=$hash{"$scope:$symb:$key"};   $returnhash{"$key"}=&thaw_unescape($hash{"$scope:$symb:$key"});
       }        }
     }      }
     if (!(untie(%hash))) {      if (!(untie(%hash))) {
Line 2232  sub store { Line 2296  sub store {
     $symb=&symbclean($symb);      $symb=&symbclean($symb);
     if (!$symb) { unless ($symb=&symbread()) { return ''; } }      if (!$symb) { unless ($symb=&symbread()) { return ''; } }
   
     if (!$domain) { $domain=$ENV{'user.domain'}; }      if (!$domain) { $domain=$env{'user.domain'}; }
     if (!$stuname) { $stuname=$ENV{'user.name'}; }      if (!$stuname) { $stuname=$env{'user.name'}; }
   
     &devalidate($symb,$stuname,$domain);      &devalidate($symb,$stuname,$domain);
   
     $symb=escape($symb);      $symb=escape($symb);
     if (!$namespace) {       if (!$namespace) { 
        unless ($namespace=$ENV{'request.course.id'}) {          unless ($namespace=$env{'request.course.id'}) { 
           return '';             return ''; 
        }          } 
     }      }
     if (!$home) { $home=$ENV{'user.home'}; }      if (!$home) { $home=$env{'user.home'}; }
   
     $$storehash{'ip'}=$ENV{'REMOTE_ADDR'};      $$storehash{'ip'}=$ENV{'REMOTE_ADDR'};
     $$storehash{'host'}=$perlvar{'lonHostID'};      $$storehash{'host'}=$perlvar{'lonHostID'};
   
     my $namevalue='';      my $namevalue='';
     foreach (keys %$storehash) {      foreach (keys %$storehash) {
         $namevalue.=escape($_).'='.escape($$storehash{$_}).'&';          $namevalue.=&escape($_).'='.&freeze_escape($$storehash{$_}).'&';
     }      }
     $namevalue=~s/\&$//;      $namevalue=~s/\&$//;
     &courselog($symb.':'.$stuname.':'.$domain.':STORE:'.$namevalue);      &courselog($symb.':'.$stuname.':'.$domain.':STORE:'.$namevalue);
Line 2268  sub cstore { Line 2332  sub cstore {
     $symb=&symbclean($symb);      $symb=&symbclean($symb);
     if (!$symb) { unless ($symb=&symbread()) { return ''; } }      if (!$symb) { unless ($symb=&symbread()) { return ''; } }
   
     if (!$domain) { $domain=$ENV{'user.domain'}; }      if (!$domain) { $domain=$env{'user.domain'}; }
     if (!$stuname) { $stuname=$ENV{'user.name'}; }      if (!$stuname) { $stuname=$env{'user.name'}; }
   
     &devalidate($symb,$stuname,$domain);      &devalidate($symb,$stuname,$domain);
   
     $symb=escape($symb);      $symb=escape($symb);
     if (!$namespace) {       if (!$namespace) { 
        unless ($namespace=$ENV{'request.course.id'}) {          unless ($namespace=$env{'request.course.id'}) { 
           return '';             return ''; 
        }          } 
     }      }
     if (!$home) { $home=$ENV{'user.home'}; }      if (!$home) { $home=$env{'user.home'}; }
   
     $$storehash{'ip'}=$ENV{'REMOTE_ADDR'};      $$storehash{'ip'}=$ENV{'REMOTE_ADDR'};
     $$storehash{'host'}=$perlvar{'lonHostID'};      $$storehash{'host'}=$perlvar{'lonHostID'};
   
     my $namevalue='';      my $namevalue='';
     foreach (keys %$storehash) {      foreach (keys %$storehash) {
         $namevalue.=escape($_).'='.escape($$storehash{$_}).'&';          $namevalue.=&escape($_).'='.&freeze_escape($$storehash{$_}).'&';
     }      }
     $namevalue=~s/\&$//;      $namevalue=~s/\&$//;
     &courselog($symb.':'.$stuname.':'.$domain.':CSTORE:'.$namevalue);      &courselog($symb.':'.$stuname.':'.$domain.':CSTORE:'.$namevalue);
Line 2308  sub restore { Line 2372  sub restore {
       $symb=&escape(&symbclean($symb));        $symb=&escape(&symbclean($symb));
     }      }
     if (!$namespace) {       if (!$namespace) { 
        unless ($namespace=$ENV{'request.course.id'}) {          unless ($namespace=$env{'request.course.id'}) { 
           return '';             return ''; 
        }          } 
     }      }
     if (!$domain) { $domain=$ENV{'user.domain'}; }      if (!$domain) { $domain=$env{'user.domain'}; }
     if (!$stuname) { $stuname=$ENV{'user.name'}; }      if (!$stuname) { $stuname=$env{'user.name'}; }
     if (!$home) { $home=$ENV{'user.home'}; }      if (!$home) { $home=$env{'user.home'}; }
     my $answer=&reply("restore:$domain:$stuname:$namespace:$symb","$home");      my $answer=&reply("restore:$domain:$stuname:$namespace:$symb","$home");
   
     my %returnhash=();      my %returnhash=();
     foreach (split(/\&/,$answer)) {      foreach (split(/\&/,$answer)) {
  my ($name,$value)=split(/\=/,$_);   my ($name,$value)=split(/\=/,$_);
         $returnhash{&unescape($name)}=&unescape($value);          $returnhash{&unescape($name)}=&thaw_unescape($value);
     }      }
     my $version;      my $version;
     for ($version=1;$version<=$returnhash{'version'};$version++) {      for ($version=1;$version<=$returnhash{'version'};$version++) {
Line 2356  sub coursedescription { Line 2420  sub coursedescription {
            }             }
            $returnhash{'url'}=&clutter($returnhash{'url'});             $returnhash{'url'}=&clutter($returnhash{'url'});
            $returnhash{'fn'}=$perlvar{'lonDaemons'}.'/tmp/'.             $returnhash{'fn'}=$perlvar{'lonDaemons'}.'/tmp/'.
        $ENV{'user.name'}.'_'.$cdomain.'_'.$cnum;         $env{'user.name'}.'_'.$cdomain.'_'.$cnum;
            $envhash{'course.'.$normalid.'.home'}=$chome;             $envhash{'course.'.$normalid.'.home'}=$chome;
            $envhash{'course.'.$normalid.'.domain'}=$cdomain;             $envhash{'course.'.$normalid.'.domain'}=$cdomain;
            $envhash{'course.'.$normalid.'.num'}=$cnum;             $envhash{'course.'.$normalid.'.num'}=$cnum;
Line 2436  sub rolesinit { Line 2500  sub rolesinit {
         my ($author,$adv) = &set_userprivs(\$userroles,\%allroles);          my ($author,$adv) = &set_userprivs(\$userroles,\%allroles);
         $userroles.='user.adv='.$adv."\n".          $userroles.='user.adv='.$adv."\n".
             'user.author='.$author."\n";              'user.author='.$author."\n";
         $ENV{'user.adv'}=$adv;          $env{'user.adv'}=$adv;
     }      }
     return $userroles;        return $userroles;  
 }  }
Line 2528  sub get { Line 2592  sub get {
        $items.=escape($_).'&';         $items.=escape($_).'&';
    }     }
    $items=~s/\&$//;     $items=~s/\&$//;
    if (!$udomain) { $udomain=$ENV{'user.domain'}; }     if (!$udomain) { $udomain=$env{'user.domain'}; }
    if (!$uname) { $uname=$ENV{'user.name'}; }     if (!$uname) { $uname=$env{'user.name'}; }
    my $uhome=&homeserver($uname,$udomain);     my $uhome=&homeserver($uname,$udomain);
   
    my $rep=&reply("get:$udomain:$uname:$namespace:$items",$uhome);     my $rep=&reply("get:$udomain:$uname:$namespace:$items",$uhome);
Line 2555  sub del { Line 2619  sub del {
        $items.=escape($_).'&';         $items.=escape($_).'&';
    }     }
    $items=~s/\&$//;     $items=~s/\&$//;
    if (!$udomain) { $udomain=$ENV{'user.domain'}; }     if (!$udomain) { $udomain=$env{'user.domain'}; }
    if (!$uname) { $uname=$ENV{'user.name'}; }     if (!$uname) { $uname=$env{'user.name'}; }
    my $uhome=&homeserver($uname,$udomain);     my $uhome=&homeserver($uname,$udomain);
   
    return &reply("del:$udomain:$uname:$namespace:$items",$uhome);     return &reply("del:$udomain:$uname:$namespace:$items",$uhome);
Line 2566  sub del { Line 2630  sub del {
   
 sub dump {  sub dump {
    my ($namespace,$udomain,$uname,$regexp)=@_;     my ($namespace,$udomain,$uname,$regexp)=@_;
    if (!$udomain) { $udomain=$ENV{'user.domain'}; }     if (!$udomain) { $udomain=$env{'user.domain'}; }
    if (!$uname) { $uname=$ENV{'user.name'}; }     if (!$uname) { $uname=$env{'user.name'}; }
    my $uhome=&homeserver($uname,$udomain);     my $uhome=&homeserver($uname,$udomain);
    if ($regexp) {     if ($regexp) {
        $regexp=&escape($regexp);         $regexp=&escape($regexp);
Line 2588  sub dump { Line 2652  sub dump {
   
 sub getkeys {  sub getkeys {
    my ($namespace,$udomain,$uname)=@_;     my ($namespace,$udomain,$uname)=@_;
    if (!$udomain) { $udomain=$ENV{'user.domain'}; }     if (!$udomain) { $udomain=$env{'user.domain'}; }
    if (!$uname) { $uname=$ENV{'user.name'}; }     if (!$uname) { $uname=$env{'user.name'}; }
    my $uhome=&homeserver($uname,$udomain);     my $uhome=&homeserver($uname,$udomain);
    my $rep=reply("keys:$udomain:$uname:$namespace",$uhome);     my $rep=reply("keys:$udomain:$uname:$namespace",$uhome);
    my @keyarray=();     my @keyarray=();
Line 2602  sub getkeys { Line 2666  sub getkeys {
 # --------------------------------------------------------------- currentdump  # --------------------------------------------------------------- currentdump
 sub currentdump {  sub currentdump {
    my ($courseid,$sdom,$sname)=@_;     my ($courseid,$sdom,$sname)=@_;
    $courseid = $ENV{'request.course.id'} if (! defined($courseid));     $courseid = $env{'request.course.id'} if (! defined($courseid));
    $sdom     = $ENV{'user.domain'}       if (! defined($sdom));     $sdom     = $env{'user.domain'}       if (! defined($sdom));
    $sname    = $ENV{'user.name'}         if (! defined($sname));     $sname    = $env{'user.name'}         if (! defined($sname));
    my $uhome = &homeserver($sname,$sdom);     my $uhome = &homeserver($sname,$sdom);
    my $rep=reply('currentdump:'.$sdom.':'.$sname.':'.$courseid,$uhome);     my $rep=reply('currentdump:'.$sdom.':'.$sname.':'.$courseid,$uhome);
    return if ($rep =~ /^(error:|no_such_host)/);     return if ($rep =~ /^(error:|no_such_host)/);
Line 2658  sub convert_dump_to_currentdump{ Line 2722  sub convert_dump_to_currentdump{
     return \%returnhash;      return \%returnhash;
 }  }
   
   # ------------------------------------------------------ critical inc interface
   
   sub cinc {
       return &inc(@_,'critical');
   }
   
 # --------------------------------------------------------------- inc interface  # --------------------------------------------------------------- inc interface
   
 sub inc {  sub inc {
     my ($namespace,$store,$udomain,$uname) = @_;      my ($namespace,$store,$udomain,$uname,$critical) = @_;
     if (!$udomain) { $udomain=$ENV{'user.domain'}; }      if (!$udomain) { $udomain=$env{'user.domain'}; }
     if (!$uname) { $uname=$ENV{'user.name'}; }      if (!$uname) { $uname=$env{'user.name'}; }
     my $uhome=&homeserver($uname,$udomain);      my $uhome=&homeserver($uname,$udomain);
     my $items='';      my $items='';
     if (! ref($store)) {      if (! ref($store)) {
Line 2679  sub inc { Line 2749  sub inc {
         }          }
     }      }
     $items=~s/\&$//;      $items=~s/\&$//;
     return &reply("inc:$udomain:$uname:$namespace:$items",$uhome);      if ($critical) {
    return &critical("inc:$udomain:$uname:$namespace:$items",$uhome);
       } else {
    return &reply("inc:$udomain:$uname:$namespace:$items",$uhome);
       }
 }  }
   
 # --------------------------------------------------------------- put interface  # --------------------------------------------------------------- put interface
   
 sub put {  sub put {
    my ($namespace,$storehash,$udomain,$uname)=@_;     my ($namespace,$storehash,$udomain,$uname)=@_;
    if (!$udomain) { $udomain=$ENV{'user.domain'}; }     if (!$udomain) { $udomain=$env{'user.domain'}; }
    if (!$uname) { $uname=$ENV{'user.name'}; }     if (!$uname) { $uname=$env{'user.name'}; }
    my $uhome=&homeserver($uname,$udomain);     my $uhome=&homeserver($uname,$udomain);
    my $items='';     my $items='';
    foreach (keys %$storehash) {     foreach (keys %$storehash) {
Line 2697  sub put { Line 2771  sub put {
    return &reply("put:$udomain:$uname:$namespace:$items",$uhome);     return &reply("put:$udomain:$uname:$namespace:$items",$uhome);
 }  }
   
 # ---------------------------------------------------------- putstore interface  # ------------------------------------------------------------ newput interface
                                                                                        
   sub newput {
      my ($namespace,$storehash,$udomain,$uname)=@_;
      if (!$udomain) { $udomain=$env{'user.domain'}; }
      if (!$uname) { $uname=$env{'user.name'}; }
      my $uhome=&homeserver($uname,$udomain);
      my $items='';
      foreach my $key (keys(%$storehash)) {
          $items.=&escape($key).'='.&freeze_escape($$storehash{$key}).'&';
      }
      $items=~s/\&$//;
      return &reply("newput:$udomain:$uname:$namespace:$items",$uhome);
   }
   
   # ---------------------------------------------------------  putstore interface
   
 sub putstore {  sub putstore {
    my ($namespace,$storehash,$udomain,$uname)=@_;     my ($namespace,$storehash,$udomain,$uname)=@_;
    if (!$udomain) { $udomain=$ENV{'user.domain'}; }     if (!$udomain) { $udomain=$env{'user.domain'}; }
    if (!$uname) { $uname=$ENV{'user.name'}; }     if (!$uname) { $uname=$env{'user.name'}; }
    my $uhome=&homeserver($uname,$udomain);     my $uhome=&homeserver($uname,$udomain);
    my $items='';     my $items='';
    my %allitems = ();     my %allitems = ();
Line 2711  sub putstore { Line 2800  sub putstore {
            my $key = $1.':keys:'.$2;             my $key = $1.':keys:'.$2;
            $allitems{$key} .= $3.':';             $allitems{$key} .= $3.':';
        }         }
        $items.=$_.'='.&escape($$storehash{$_}).'&';         $items.=$_.'='.&freeze_escape($$storehash{$_}).'&';
    }     }
    foreach (keys %allitems) {     foreach (keys %allitems) {
        $allitems{$_} =~ s/\:$//;         $allitems{$_} =~ s/\:$//;
Line 2725  sub putstore { Line 2814  sub putstore {
   
 sub cput {  sub cput {
    my ($namespace,$storehash,$udomain,$uname)=@_;     my ($namespace,$storehash,$udomain,$uname)=@_;
    if (!$udomain) { $udomain=$ENV{'user.domain'}; }     if (!$udomain) { $udomain=$env{'user.domain'}; }
    if (!$uname) { $uname=$ENV{'user.name'}; }     if (!$uname) { $uname=$env{'user.name'}; }
    my $uhome=&homeserver($uname,$udomain);     my $uhome=&homeserver($uname,$udomain);
    my $items='';     my $items='';
    foreach (keys %$storehash) {     foreach (keys %$storehash) {
Line 2745  sub eget { Line 2834  sub eget {
        $items.=escape($_).'&';         $items.=escape($_).'&';
    }     }
    $items=~s/\&$//;     $items=~s/\&$//;
    if (!$udomain) { $udomain=$ENV{'user.domain'}; }     if (!$udomain) { $udomain=$env{'user.domain'}; }
    if (!$uname) { $uname=$ENV{'user.name'}; }     if (!$uname) { $uname=$env{'user.name'}; }
    my $uhome=&homeserver($uname,$udomain);     my $uhome=&homeserver($uname,$udomain);
    my $rep=&reply("eget:$udomain:$uname:$namespace:$items",$uhome);     my $rep=&reply("eget:$udomain:$uname:$namespace:$items",$uhome);
    my @pairs=split(/\&/,$rep);     my @pairs=split(/\&/,$rep);
Line 2763  sub eget { Line 2852  sub eget {
   
 sub customaccess {  sub customaccess {
     my ($priv,$uri)=@_;      my ($priv,$uri)=@_;
     my ($urole,$urealm)=split(/\./,$ENV{'request.role'});      my ($urole,$urealm)=split(/\./,$env{'request.role'});
     $urealm=~s/^\W//;      $urealm=~s/^\W//;
     my ($udom,$ucrs,$usec)=split(/\//,$urealm);      my ($udom,$ucrs,$usec)=split(/\//,$urealm);
     my $access=0;      my $access=0;
Line 2803  sub allowed { Line 2892  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 !~ m|/bulletinboard$|)) 
  || ($uri=~/\.meta$/)) && ($priv eq 'bre')) {   || ($uri=~/\.meta$/)) && ($priv eq 'bre')) {
Line 2812  sub allowed { Line 2901  sub allowed {
   
 # Free bre access to user's own portfolio contents  # Free bre access to user's own portfolio contents
     my ($space,$domain,$name,$dir)=split('/',$uri);      my ($space,$domain,$name,$dir)=split('/',$uri);
     if (('uploaded' eq $space) && ($ENV{'user.name'} eq $name) &&       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)) {
         return 'F';          return 'F';
     }      }
   
Line 2821  sub allowed { Line 2910  sub allowed {
   
     if ($priv eq 'bre') {      if ($priv eq 'bre') {
         my $copyright=&metadata($uri,'copyright');          my $copyright=&metadata($uri,'copyright');
  if (($copyright eq 'public') && (!$ENV{'request.course.id'})) {    if (($copyright eq 'public') && (!$env{'request.course.id'})) { 
            return 'F';              return 'F'; 
         }          }
         if ($copyright eq 'priv') {          if ($copyright eq 'priv') {
             $uri=~/([^\/]+)\/([^\/]+)\//;              $uri=~/([^\/]+)\/([^\/]+)\//;
     unless (($ENV{'user.name'} eq $2) && ($ENV{'user.domain'} eq $1)) {      unless (($env{'user.name'} eq $2) && ($env{'user.domain'} eq $1)) {
  return '';   return '';
             }              }
         }          }
         if ($copyright eq 'domain') {          if ($copyright eq 'domain') {
             $uri=~/([^\/]+)\/([^\/]+)\//;              $uri=~/([^\/]+)\/([^\/]+)\//;
     unless (($ENV{'user.domain'} eq $1) ||      unless (($env{'user.domain'} eq $1) ||
                  ($ENV{'course.'.$ENV{'request.course.id'}.'.domain'} eq $1)) {                   ($env{'course.'.$env{'request.course.id'}.'.domain'} eq $1)) {
  return '';   return '';
             }              }
         }          }
         if ($ENV{'request.role'}=~ /li\.\//) {          if ($env{'request.role'}=~ /li\.\//) {
             # Library role, so allow browsing of resources in this domain.              # Library role, so allow browsing of resources in this domain.
             return 'F';              return 'F';
         }          }
Line 2846  sub allowed { Line 2935  sub allowed {
         }          }
     }      }
     # Domain coordinator is trying to create a course      # Domain coordinator is trying to create a course
     if (($priv eq 'ccc') && ($ENV{'request.role'} =~ /^dc\./)) {      if (($priv eq 'ccc') && ($env{'request.role'} =~ /^dc\./)) {
         # uri is the requested domain in this case.          # uri is the requested domain in this case.
         # comparison to 'request.role.domain' shows if the user has selected          # comparison to 'request.role.domain' shows if the user has selected
         # a role of dc for the domain in question.           # a role of dc for the domain in question. 
         return 'F' if ($uri eq $ENV{'request.role.domain'});          return 'F' if ($uri eq $env{'request.role.domain'});
     }      }
   
     my $thisallowed='';      my $thisallowed='';
Line 2859  sub allowed { Line 2948  sub allowed {
   
 # Course  # Course
   
     if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'}=~/\Q$priv\E\&([^\:]*)/) {      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].'/'}
        =~/\Q$priv\E\&([^\:]*)/) {         =~/\Q$priv\E\&([^\:]*)/) {
        $thisallowed.=$1;         $thisallowed.=$1;
     }      }
Line 2875  sub allowed { Line 2964  sub allowed {
     $courseuri=~s/\_(\d)/\/$1/;      $courseuri=~s/\_(\d)/\/$1/;
     $courseuri=~s/^([^\/])/\/$1/;      $courseuri=~s/^([^\/])/\/$1/;
   
     if ($ENV{'user.priv.'.$ENV{'request.role'}.'.'.$courseuri}      if ($env{'user.priv.'.$env{'request.role'}.'.'.$courseuri}
        =~/\Q$priv\E\&([^\:]*)/) {         =~/\Q$priv\E\&([^\:]*)/) {
        $thisallowed.=$1;         $thisallowed.=$1;
     }      }
   
 # URI is an uploaded document for this course  # URI is an uploaded document for this course
   # not allowing 'edit' access (editupload) to uploaded course docs
     if (($priv eq 'bre') && ($uri=~m|^uploaded/|)) {      if (($priv eq 'bre') && ($uri=~m|^uploaded/|)) {
  my $refuri=$ENV{'httpref.'.$orguri};   my $refuri=$env{'httpref.'.$orguri};
  if ($refuri) {   if ($refuri) {
     if ($refuri =~ m|^/adm/|) {      if ($refuri =~ m|^/adm/|) {
  $thisallowed='F';   $thisallowed='F';
Line 2899  sub allowed { Line 2988  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:'=~/\:\Q$priv\E\:/) {      if (':csu:cdc:ccc:cin:cta:cep:ccr:cst:cad:cli:cau:cdg:cca:caa:'=~/\:\Q$priv\E\:/) {
    if (($priv eq 'cca') || ($priv eq 'caa')) {
       my ($audom,$auname)=split('/',$uri);
   # no author name given, so this just checks on the general right to make a co-author in this domain
       unless ($auname) { return $thisallowed; }
   # an author name is given, so we are about to actually make a co-author for a certain account
       if (($auname ne $env{'user.name'} && $env{'request.role'} !~ /^dc\./) ||
    (($audom ne $env{'user.domain'} && $env{'request.role'} !~ /^dc\./) &&
    ($audom ne $env{'request.role.domain'}))) { return ''; }
    }
  return $thisallowed;   return $thisallowed;
     }      }
 #  #
Line 2908  sub allowed { Line 3006  sub allowed {
 # Course: See if uri or referer is an individual resource that is part of   # Course: See if uri or referer is an individual resource that is part of 
 # the course  # the course
   
     if ($ENV{'request.course.id'}) {      if ($env{'request.course.id'}) {
   
        $courseprivid=$ENV{'request.course.id'};         $courseprivid=$env{'request.course.id'};
        if ($ENV{'request.course.sec'}) {         if ($env{'request.course.sec'}) {
           $courseprivid.='/'.$ENV{'request.course.sec'};            $courseprivid.='/'.$env{'request.course.sec'};
        }         }
        $courseprivid=~s/\_/\//;         $courseprivid=~s/\_/\//;
        my $checkreferer=1;         my $checkreferer=1;
        my ($match,$cond)=&is_on_map($uri);         my ($match,$cond)=&is_on_map($uri);
        if ($match) {         if ($match) {
            $statecond=$cond;             $statecond=$cond;
            if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.$courseprivid}             if ($env{'user.priv.'.$env{'request.role'}.'./'.$courseprivid}
                =~/\Q$priv\E\&([^\:]*)/) {                 =~/\Q$priv\E\&([^\:]*)/) {
                $thisallowed.=$1;                 $thisallowed.=$1;
                $checkreferer=0;                 $checkreferer=0;
Line 2927  sub allowed { Line 3025  sub allowed {
        }         }
                 
        if ($checkreferer) {         if ($checkreferer) {
   my $refuri=$ENV{'httpref.'.$orguri};    my $refuri=$env{'httpref.'.$orguri};
             unless ($refuri) {              unless ($refuri) {
                 foreach (keys %ENV) {                  foreach (keys %env) {
     if ($_=~/^httpref\..*\*/) {      if ($_=~/^httpref\..*\*/) {
  my $pattern=$_;   my $pattern=$_;
                         $pattern=~s/^httpref\.\/res\///;                          $pattern=~s/^httpref\.\/res\///;
                         $pattern=~s/\*/\[\^\/\]\+/g;                          $pattern=~s/\*/\[\^\/\]\+/g;
                         $pattern=~s/\//\\\//g;                          $pattern=~s/\//\\\//g;
                         if ($orguri=~/$pattern/) {                          if ($orguri=~/$pattern/) {
     $refuri=$ENV{$_};      $refuri=$env{$_};
                         }                          }
                     }                      }
                 }                  }
Line 2947  sub allowed { Line 3045  sub allowed {
           my ($match,$cond)=&is_on_map($refuri);            my ($match,$cond)=&is_on_map($refuri);
             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}
                   =~/\Q$priv\E\&([^\:]*)/) {                    =~/\Q$priv\E\&([^\:]*)/) {
                   $thisallowed.=$1;                    $thisallowed.=$1;
                   $uri=$refuri;                    $uri=$refuri;
Line 2987  sub allowed { Line 3085  sub allowed {
   
     my $envkey;      my $envkey;
     if ($thisallowed=~/L/) {      if ($thisallowed=~/L/) {
         foreach $envkey (keys %ENV) {          foreach $envkey (keys %env) {
            if ($envkey=~/^user\.role\.(st|ta)\.([^\.]*)/) {             if ($envkey=~/^user\.role\.(st|ta)\.([^\.]*)/) {
                my $courseid=$2;                 my $courseid=$2;
                my $roleid=$1.'.'.$2;                 my $roleid=$1.'.'.$2;
                $courseid=~s/^\///;                 $courseid=~s/^\///;
                my $expiretime=600;                 my $expiretime=600;
                if ($ENV{'request.role'} eq $roleid) {                 if ($env{'request.role'} eq $roleid) {
   $expiretime=120;    $expiretime=120;
                }                 }
        my ($cdom,$cnum,$csec)=split(/\//,$courseid);         my ($cdom,$cnum,$csec)=split(/\//,$courseid);
                my $prefix='course.'.$cdom.'_'.$cnum.'.';                 my $prefix='course.'.$cdom.'_'.$cnum.'.';
                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'}=~/\,\Q$csec\E\,/)                 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'},
                             $ENV{'user.home'},                              $env{'user.home'},
                             'Locked by res: '.$priv.' for '.$uri.' due to '.                              'Locked by res: '.$priv.' for '.$uri.' due to '.
                             $cdom.'/'.$cnum.'/'.$csec.' expire '.                              $cdom.'/'.$cnum.'/'.$csec.' expire '.
                             $ENV{$prefix.'priv.'.$priv.'.lock.expire'});                              $env{$prefix.'priv.'.$priv.'.lock.expire'});
        return '';         return '';
                    }                     }
                }                 }
                if (($ENV{$prefix.'priv.'.$priv.'.lock.sections'}=~/\,\Q$csec\E\,/)                 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'},
                             $ENV{'user.home'},                              $env{'user.home'},
                             'Locked by priv: '.$priv.' for '.$uri.' due to '.                              'Locked by priv: '.$priv.' for '.$uri.' due to '.
                             $cdom.'/'.$cnum.'/'.$csec.' expire '.                              $cdom.'/'.$cnum.'/'.$csec.' expire '.
                             $ENV{$prefix.'priv.'.$priv.'.lock.expire'});                              $env{$prefix.'priv.'.$priv.'.lock.expire'});
        return '';         return '';
                    }                     }
                }                 }
Line 3031  sub allowed { Line 3129  sub allowed {
 # Rest of the restrictions depend on selected course  # Rest of the restrictions depend on selected course
 #  #
   
     unless ($ENV{'request.course.id'}) {      unless ($env{'request.course.id'}) {
        return '1';         return '1';
     }      }
   
Line 3043  sub allowed { Line 3141  sub allowed {
 # Course preferences  # Course preferences
   
    if ($thisallowed=~/C/) {     if ($thisallowed=~/C/) {
        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'}
    =~/\Q$rolecode\E/) {     =~/\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'});
            return '';             return '';
        }         }
   
        if ($ENV{'course.'.$ENV{'request.course.id'}.'.'.$priv.'.users.denied'}         if ($env{'course.'.$env{'request.course.id'}.'.'.$priv.'.users.denied'}
    =~/\Q$unamedom\E/) {     =~/\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'});
            return '';             return '';
        }         }
    }     }
Line 3065  sub allowed { Line 3163  sub allowed {
 # Resource preferences  # Resource preferences
   
    if ($thisallowed=~/R/) {     if ($thisallowed=~/R/) {
        my $rolecode=(split(/\./,$ENV{'request.role'}))[0];         my $rolecode=(split(/\./,$env{'request.role'}))[0];
        if (&metadata($uri,'roledeny')=~/\Q$rolecode\E/) {         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 3076  sub allowed { Line 3174  sub allowed {
 # Restricted by state or randomout?  # Restricted by state or randomout?
   
    if ($thisallowed=~/X/) {     if ($thisallowed=~/X/) {
       if ($ENV{'acc.randomout'}) {        if ($env{'acc.randomout'}) {
  if (!$symb) { $symb=&symbread($uri,1); }   if (!$symb) { $symb=&symbread($uri,1); }
          if (($symb) && ($ENV{'acc.randomout'}=~/\&\Q$symb\E\&/)) {            if (($symb) && ($env{'acc.randomout'}=~/\&\Q$symb\E\&/)) { 
             return '';               return ''; 
          }           }
       }        }
Line 3103  sub is_on_map { Line 3201  sub is_on_map {
     $pathname=~s|/\Q$filename\E$||;      $pathname=~s|/\Q$filename\E$||;
     $pathname=~s/^adm\/wrapper\///;          $pathname=~s/^adm\/wrapper\///;    
     #Trying to find the conditional for the file      #Trying to find the conditional for the file
     my $match=($ENV{'acc.res.'.$ENV{'request.course.id'}.'.'.$pathname}=~      my $match=($env{'acc.res.'.$env{'request.course.id'}.'.'.$pathname}=~
        /\&\Q$filename\E\:([\d\|]+)\&/);         /\&\Q$filename\E\:([\d\|]+)\&/);
     if ($match) {      if ($match) {
  return (1,$1);   return (1,$1);
Line 3122  sub get_symb_from_alias { Line 3220  sub get_symb_from_alias {
 # Must be an alias  # Must be an alias
     my $aliassymb='';      my $aliassymb='';
     my %bighash;      my %bighash;
     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 $rid=$bighash{'mapalias_'.$symb};          my $rid=$bighash{'mapalias_'.$symb};
  if ($rid) {   if ($rid) {
Line 3167  sub definerole { Line 3265  sub definerole {
             }              }
         }          }
     }      }
     my $command="encrypt:rolesput:$ENV{'user.domain'}:$ENV{'user.name'}:".      my $command="encrypt:rolesput:$env{'user.domain'}:$env{'user.name'}:".
                 "$ENV{'user.domain'}:$ENV{'user.name'}:".                  "$env{'user.domain'}:$env{'user.name'}:".
         "rolesdef_$rolename=".          "rolesdef_$rolename=".
                 escape($sysrole.'_'.$domrole.'_'.$courole);                  escape($sysrole.'_'.$domrole.'_'.$courole);
     return reply($command,$ENV{'user.home'});      return reply($command,$env{'user.home'});
   } else {    } else {
     return 'refused';      return 'refused';
   }    }
Line 3233  sub fetch_enrollment_query { Line 3331  sub fetch_enrollment_query {
     $cmd =~ s/%%$//;      $cmd =~ s/%%$//;
     $cmd = &escape($cmd);      $cmd = &escape($cmd);
     my $query = 'fetchenrollment';      my $query = 'fetchenrollment';
     my $queryid=&reply("querysend:".$query.':'.$dom.':'.$ENV{'user.name'}.':'.$cmd,$homeserver);      my $queryid=&reply("querysend:".$query.':'.$dom.':'.$env{'user.name'}.':'.$cmd,$homeserver);
     unless ($queryid=~/^\Q$host\E\_/) {       unless ($queryid=~/^\Q$host\E\_/) { 
         &logthis('fetch_enrollment_query: invalid queryid: '.$queryid.' for host: '.$host.' and homeserver: '.$homeserver.' context: '.$context.' '.$cnum);           &logthis('fetch_enrollment_query: invalid queryid: '.$queryid.' for host: '.$host.' and homeserver: '.$homeserver.' context: '.$context.' '.$cnum); 
         return 'error: '.$queryid;          return 'error: '.$queryid;
Line 3245  sub fetch_enrollment_query { Line 3343  sub fetch_enrollment_query {
         $tries ++;          $tries ++;
     }      }
     if ( ($reply =~/^timeout/) || ($reply =~/^error/) ) {      if ( ($reply =~/^timeout/) || ($reply =~/^error/) ) {
         &logthis('fetch_enrollment_query error: '.$reply.' for '.$dom.' '.$ENV{'user.name'}.' for '.$queryid.' context: '.$context.' '.$cnum.' maxtries: '.$maxtries.' tries: '.$tries);          &logthis('fetch_enrollment_query error: '.$reply.' for '.$dom.' '.$env{'user.name'}.' for '.$queryid.' context: '.$context.' '.$cnum.' maxtries: '.$maxtries.' tries: '.$tries);
     } else {      } else {
         my @responses = split/:/,$reply;          my @responses = split/:/,$reply;
         if ($homeserver eq $perlvar{'lonHostID'}) {          if ($homeserver eq $perlvar{'lonHostID'}) {
Line 3310  sub courselog_query { Line 3408  sub courselog_query {
 # end: timestamp  # end: timestamp
 #  #
     my (%filters)=@_;      my (%filters)=@_;
     unless ($ENV{'request.course.id'}) { return 'no_course'; }      unless ($env{'request.course.id'}) { return 'no_course'; }
     if ($filters{'url'}) {      if ($filters{'url'}) {
  $filters{'url'}=&symbclean(&declutter($filters{'url'}));   $filters{'url'}=&symbclean(&declutter($filters{'url'}));
         $filters{'url'}=~s/\.(\w+)$/(\\.\\d+)*\\.$1/;          $filters{'url'}=~s/\.(\w+)$/(\\.\\d+)*\\.$1/;
         $filters{'url'}=~s/\.(\w+)\_\_\_/(\\.\\d+)*\\.$1/;          $filters{'url'}=~s/\.(\w+)\_\_\_/(\\.\\d+)*\\.$1/;
     }      }
     my $cname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'};      my $cname=$env{'course.'.$env{'request.course.id'}.'.num'};
     my $cdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};      my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};
     return &log_query($cname,$cdom,'courselog',%filters);      return &log_query($cname,$cdom,'courselog',%filters);
 }  }
   
Line 3385  sub auto_instcode_format { Line 3483  sub auto_instcode_format {
                 last;                  last;
             }              }
         }          }
         if (($ENV{'user.name'}) && ($ENV{'user.domain'} eq $codedom)) {          if (($env{'user.name'}) && ($env{'user.domain'} eq $codedom)) {
             $homeserver = &homeserver($ENV{'user.name'},$codedom);              $homeserver = &homeserver($env{'user.name'},$codedom);
         }          }
     } else {      } else {
         $homeserver = &homeserver($caller,$codedom);          $homeserver = &homeserver($caller,$codedom);
Line 3425  sub assignrole { Line 3523  sub assignrole {
  unless (&allowed('ccr',$cwosec)) {   unless (&allowed('ccr',$cwosec)) {
            &logthis('Refused custom assignrole: '.             &logthis('Refused custom assignrole: '.
              $udom.' '.$uname.' '.$url.' '.$role.' '.$end.' '.$start.' by '.               $udom.' '.$uname.' '.$url.' '.$role.' '.$end.' '.$start.' by '.
     $ENV{'user.name'}.' at '.$ENV{'user.domain'});      $env{'user.name'}.' at '.$env{'user.domain'});
            return 'refused';              return 'refused'; 
         }          }
         $mrole='cr';          $mrole='cr';
Line 3435  sub assignrole { Line 3533  sub assignrole {
         unless ((&allowed('c'.$role,$cwosec)) || &allowed('c'.$role,$udom)) {           unless ((&allowed('c'.$role,$cwosec)) || &allowed('c'.$role,$udom)) { 
            &logthis('Refused assignrole: '.             &logthis('Refused assignrole: '.
              $udom.' '.$uname.' '.$url.' '.$role.' '.$end.' '.$start.' by '.               $udom.' '.$uname.' '.$url.' '.$role.' '.$end.' '.$start.' by '.
     $ENV{'user.name'}.' at '.$ENV{'user.domain'});      $env{'user.name'}.' at '.$env{'user.domain'});
            return 'refused';              return 'refused'; 
         }          }
         $mrole=$role;          $mrole=$role;
     }      }
     my $command="encrypt:rolesput:$ENV{'user.domain'}:$ENV{'user.name'}:".      my $command="encrypt:rolesput:$env{'user.domain'}:$env{'user.name'}:".
                 "$udom:$uname:$url".'_'."$mrole=$role";                  "$udom:$uname:$url".'_'."$mrole=$role";
     if ($end) { $command.='_'.$end; }      if ($end) { $command.='_'.$end; }
     if ($start) {      if ($start) {
Line 3454  sub assignrole { Line 3552  sub assignrole {
     if ($deleteflag) {      if ($deleteflag) {
  if ((&allowed('dro',$udom)) || (&allowed('dro',$url))) {   if ((&allowed('dro',$udom)) || (&allowed('dro',$url))) {
 # modify command to delete the role  # modify command to delete the role
            $command="encrypt:rolesdel:$ENV{'user.domain'}:$ENV{'user.name'}:".             $command="encrypt:rolesdel:$env{'user.domain'}:$env{'user.name'}:".
                 "$udom:$uname:$url".'_'."$mrole";                  "$udom:$uname:$url".'_'."$mrole";
    &logthis("$ENV{'user.name'} at $ENV{'user.domain'} deletes $mrole in $url for $uname at $udom");      &logthis("$env{'user.name'} at $env{'user.domain'} deletes $mrole in $url for $uname at $udom"); 
 # set start and finish to negative values for userrolelog  # set start and finish to negative values for userrolelog
            $start=-1;             $start=-1;
            $end=-1;             $end=-1;
Line 3479  sub modifyuserauth { Line 3577  sub modifyuserauth {
     my $uhome=&homeserver($uname,$udom);      my $uhome=&homeserver($uname,$udom);
     unless (&allowed('mau',$udom)) { return 'refused'; }      unless (&allowed('mau',$udom)) { return 'refused'; }
     &logthis('Call to modify user authentication '.$udom.', '.$uname.', '.      &logthis('Call to modify user authentication '.$udom.', '.$uname.', '.
              $umode.' by '.$ENV{'user.name'}.' at '.$ENV{'user.domain'}.               $umode.' by '.$env{'user.name'}.' at '.$env{'user.domain'}.
              ' in domain '.$ENV{'request.role.domain'});                 ' in domain '.$env{'request.role.domain'});  
     my $reply=&reply('encrypt:changeuserauth:'.$udom.':'.$uname.':'.$umode.':'.      my $reply=&reply('encrypt:changeuserauth:'.$udom.':'.$uname.':'.$umode.':'.
      &escape($upass),$uhome);       &escape($upass),$uhome);
     &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.home'},      &log($env{'user.domain'},$env{'user.name'},$env{'user.home'},
         'Authentication changed for '.$udom.', '.$uname.', '.$umode.          'Authentication changed for '.$udom.', '.$uname.', '.$umode.
          '(Remote '.$ENV{'REMOTE_ADDR'}.'): '.$reply);           '(Remote '.$ENV{'REMOTE_ADDR'}.'): '.$reply);
     &log($udom,,$uname,$uhome,      &log($udom,,$uname,$uhome,
         'Authentication changed by '.$ENV{'user.domain'}.', '.          'Authentication changed by '.$env{'user.domain'}.', '.
                                      $ENV{'user.name'}.', '.$umode.                                       $env{'user.name'}.', '.$umode.
          '(Remote '.$ENV{'REMOTE_ADDR'}.'): '.$reply);           '(Remote '.$ENV{'REMOTE_ADDR'}.'): '.$reply);
     unless ($reply eq 'ok') {      unless ($reply eq 'ok') {
         &logthis('Authentication mode error: '.$reply);          &logthis('Authentication mode error: '.$reply);
Line 3511  sub modifyuser { Line 3609  sub modifyuser {
      $last.', '.$gene.'(forceid: '.$forceid.')'.       $last.', '.$gene.'(forceid: '.$forceid.')'.
              (defined($desiredhome) ? ' desiredhome = '.$desiredhome :               (defined($desiredhome) ? ' desiredhome = '.$desiredhome :
                                      ' desiredhome not specified').                                        ' desiredhome not specified'). 
              ' by '.$ENV{'user.name'}.' at '.$ENV{'user.domain'}.               ' by '.$env{'user.name'}.' at '.$env{'user.domain'}.
              ' in domain '.$ENV{'request.role.domain'});               ' in domain '.$env{'request.role.domain'});
     my $uhome=&homeserver($uname,$udom,'true');      my $uhome=&homeserver($uname,$udom,'true');
 # ----------------------------------------------------------------- Create User  # ----------------------------------------------------------------- Create User
     if (($uhome eq 'no_host') &&       if (($uhome eq 'no_host') && 
Line 3520  sub modifyuser { Line 3618  sub modifyuser {
         my $unhome='';          my $unhome='';
         if (defined($desiredhome) && $hostdom{$desiredhome} eq $udom) {           if (defined($desiredhome) && $hostdom{$desiredhome} eq $udom) { 
             $unhome = $desiredhome;              $unhome = $desiredhome;
  } elsif($ENV{'course.'.$ENV{'request.course.id'}.'.domain'} eq $udom) {   } elsif($env{'course.'.$env{'request.course.id'}.'.domain'} eq $udom) {
     $unhome=$ENV{'course.'.$ENV{'request.course.id'}.'.home'};      $unhome=$env{'course.'.$env{'request.course.id'}.'.home'};
         } else { # load balancing routine for determining $unhome          } else { # load balancing routine for determining $unhome
             my $tryserver;              my $tryserver;
             my $loadm=10000000;              my $loadm=10000000;
Line 3581  sub modifyuser { Line 3679  sub modifyuser {
     if (defined($middle)) { $names{'middlename'} = $middle; }      if (defined($middle)) { $names{'middlename'} = $middle; }
     if ($last)   { $names{'lastname'}   = $last; }      if ($last)   { $names{'lastname'}   = $last; }
     if (defined($gene))   { $names{'generation'} = $gene; }      if (defined($gene))   { $names{'generation'} = $gene; }
     if ($email)  { $names{'notification'} = $email;      if ($email) {
                    $names{'critnotification'} = $email; }         $email=~s/[^\w\@\.\-\,]//gs;
          if ($email=~/\@/) { $names{'notification'} = $email;
      $names{'critnotification'} = $email;
      $names{'permanentemail'} = $email; }
       }
     my $reply = &put('environment', \%names, $udom,$uname);      my $reply = &put('environment', \%names, $udom,$uname);
     if ($reply ne 'ok') { return 'error: '.$reply; }      if ($reply ne 'ok') { return 'error: '.$reply; }
     &logthis('Success modifying user '.$udom.', '.$uname.', '.$uid.', '.      &logthis('Success modifying user '.$udom.', '.$uname.', '.$uid.', '.
              $umode.', '.$first.', '.$middle.', '.               $umode.', '.$first.', '.$middle.', '.
      $last.', '.$gene.' by '.       $last.', '.$gene.' by '.
              $ENV{'user.name'}.' at '.$ENV{'user.domain'});               $env{'user.name'}.' at '.$env{'user.domain'});
     return 'ok';      return 'ok';
 }  }
   
Line 3599  sub modifystudent { Line 3700  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,$locktype,$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 3620  sub modify_student_enrollment { Line 3721  sub modify_student_enrollment {
     my ($udom,$uname,$uid,$first,$middle,$last,$gene,$usec,$end,$start,$type,$locktype,$cid) = @_;      my ($udom,$uname,$uid,$first,$middle,$last,$gene,$usec,$end,$start,$type,$locktype,$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'}) {
     return 'not_in_class';      return 'not_in_class';
  }   }
  $cdom=$ENV{'course.'.$cid.'.domain'};   $cdom=$env{'course.'.$cid.'.domain'};
  $cnum=$ENV{'course.'.$cid.'.num'};   $cnum=$env{'course.'.$cid.'.num'};
     } else {      } else {
  ($cdom,$cnum)=split(/_/,$cid);   ($cdom,$cnum)=split(/_/,$cid);
     }      }
     $chome=$ENV{'course.'.$cid.'.home'};      $chome=$env{'course.'.$cid.'.home'};
     if (!$chome) {      if (!$chome) {
  $chome=&homeserver($cnum,$cdom);   $chome=&homeserver($cnum,$cdom);
     }      }
Line 3737  sub createcourse { Line 3838  sub createcourse {
        }          } 
    }     }
 # ------------------------------------------------ Check supplied server name  # ------------------------------------------------ Check supplied server name
     $course_server = $ENV{'user.homeserver'} if (! defined($course_server));      $course_server = $env{'user.homeserver'} if (! defined($course_server));
     if (! exists($libserv{$course_server})) {      if (! exists($libserv{$course_server})) {
         return 'error:bad server name '.$course_server;          return 'error:bad server name '.$course_server;
     }      }
Line 3760  sub createcourse { Line 3861  sub createcourse {
 # ------------------------------------------ For standard courses, make top url  # ------------------------------------------ For standard courses, make top url
         my $mapurl=&clutter($url);          my $mapurl=&clutter($url);
         if ($mapurl eq '/res/') { $mapurl=''; }          if ($mapurl eq '/res/') { $mapurl=''; }
         $ENV{'form.initmap'}=(<<ENDINITMAP);          $env{'form.initmap'}=(<<ENDINITMAP);
 <map>  <map>
 <resource id="1" type="start"></resource>  <resource id="1" type="start"></resource>
 <resource id="2" src="$mapurl"></resource>  <resource id="2" src="$mapurl"></resource>
Line 3770  sub createcourse { Line 3871  sub createcourse {
 </map>  </map>
 ENDINITMAP  ENDINITMAP
         $topurl=&declutter(          $topurl=&declutter(
         &finishuserfileupload($uname,$udom,$uhome,'initmap','default.sequence')          &finishuserfileupload($uname,$udom,'initmap','default.sequence')
                           );                            );
     }      }
 # ----------------------------------------------------------- Write preferences  # ----------------------------------------------------------- Write preferences
Line 3818  sub is_locked { Line 3919  sub is_locked {
     my @check;      my @check;
     my $is_locked;      my $is_locked;
     push @check, $file_name;      push @check, $file_name;
     my %locked = &Apache::lonnet::get('file_permissions',\@check,      my %locked = &get('file_permissions',\@check,
                                         $ENV{'user.domain'},$ENV{'user.name'});        $env{'user.domain'},$env{'user.name'});
       my ($tmp)=keys(%locked);
       if ($tmp=~/^error:/) { undef(%locked); }
   
     if (ref($locked{$file_name}) eq 'ARRAY') {      if (ref($locked{$file_name}) eq 'ARRAY') {
         $is_locked = 'true';          $is_locked = 'true';
     } else {      } else {
Line 3831  sub is_locked { Line 3935  sub is_locked {
   
 sub mark_as_readonly {  sub mark_as_readonly {
     my ($domain,$user,$files,$what) = @_;      my ($domain,$user,$files,$what) = @_;
     my %current_permissions = &Apache::lonnet::dump('file_permissions',$domain,$user);      my %current_permissions = &dump('file_permissions',$domain,$user);
       my ($tmp)=keys(%current_permissions);
       if ($tmp=~/^error:/) { undef(%current_permissions); }
     foreach my $file (@{$files}) {      foreach my $file (@{$files}) {
         push(@{$current_permissions{$file}},$what);          push(@{$current_permissions{$file}},$what);
     }      }
     &Apache::lonnet::put('file_permissions',\%current_permissions,$domain,$user);      &put('file_permissions',\%current_permissions,$domain,$user);
     return;      return;
 }  }
   
Line 3847  sub save_selected_files { Line 3953  sub save_selected_files {
     my @other_files = &files_not_in_path($user, $path);      my @other_files = &files_not_in_path($user, $path);
     open (OUT, '>'.$Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/'.$filename);      open (OUT, '>'.$Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/'.$filename);
     foreach my $file (@files) {      foreach my $file (@files) {
         print (OUT $ENV{'form.currentpath'}.$file."\n");          print (OUT $env{'form.currentpath'}.$file."\n");
     }      }
     foreach my $file (@other_files) {      foreach my $file (@other_files) {
         print (OUT $file."\n");          print (OUT $file."\n");
Line 3910  sub files_not_in_path { Line 4016  sub files_not_in_path {
   
 #--------------------------------------------------------------Get Marked as Read Only  #--------------------------------------------------------------Get Marked as Read Only
   
   
 sub get_marked_as_readonly {  sub get_marked_as_readonly {
     my ($domain,$user,$what) = @_;      my ($domain,$user,$what) = @_;
     my %current_permissions = &Apache::lonnet::dump('file_permissions',$domain,$user);      my %current_permissions = &dump('file_permissions',$domain,$user);
       my ($tmp)=keys(%current_permissions);
       if ($tmp=~/^error:/) { undef(%current_permissions); }
     my @readonly_files;      my @readonly_files;
       my $cmp1=$what;
       if (ref($what)) { $cmp1=join('',@{$what}) };
     while (my ($file_name,$value) = each(%current_permissions)) {      while (my ($file_name,$value) = each(%current_permissions)) {
         if (ref($value) eq "ARRAY"){          if (ref($value) eq "ARRAY"){
             foreach my $stored_what (@{$value}) {              foreach my $stored_what (@{$value}) {
                 if ($stored_what eq $what) {                  my $cmp2=$stored_what;
                   if (ref($stored_what)) { $cmp2=join('',@{$stored_what}) };
                   if ($cmp1 eq $cmp2) {
                     push(@readonly_files, $file_name);                      push(@readonly_files, $file_name);
                 } elsif (!defined($what)) {                  } elsif (!defined($what)) {
                     push(@readonly_files, $file_name);                      push(@readonly_files, $file_name);
Line 3931  sub get_marked_as_readonly { Line 4044  sub get_marked_as_readonly {
   
 sub get_marked_as_readonly_hash {  sub get_marked_as_readonly_hash {
     my ($domain,$user,$what) = @_;      my ($domain,$user,$what) = @_;
     my %current_permissions = &Apache::lonnet::dump('file_permissions',$domain,$user);      my %current_permissions = &dump('file_permissions',$domain,$user);
       my ($tmp)=keys(%current_permissions);
       if ($tmp=~/^error:/) { undef(%current_permissions); }
   
     my %readonly_files;      my %readonly_files;
     while (my ($file_name,$value) = each(%current_permissions)) {      while (my ($file_name,$value) = each(%current_permissions)) {
         if (ref($value) eq "ARRAY"){          if (ref($value) eq "ARRAY"){
Line 3949  sub get_marked_as_readonly_hash { Line 4065  sub get_marked_as_readonly_hash {
 # ------------------------------------------------------------ Unmark as Read Only  # ------------------------------------------------------------ Unmark as Read Only
   
 sub unmark_as_readonly {  sub unmark_as_readonly {
     # unmarks all files locked by $what       # unmarks $file_name (if $file_name is defined), or all files locked by $what 
     # for portfolio submissions, $what contains $crsid and $symb      # for portfolio submissions, $what contains [$symb,$crsid] 
     my ($domain,$user,$what) = @_;      my ($domain,$user,$what,$file_name) = @_;
     my %current_permissions = &Apache::lonnet::dump('file_permissions',$domain,$user);      my $symb_crs = $what;
     my @readonly_files = &Apache::lonnet::get_marked_as_readonly($domain,$user,$what);      if (ref($what)) { $symb_crs=join('',@$what); }
       my %current_permissions = &dump('file_permissions',$domain,$user);
       my ($tmp)=keys(%current_permissions);
       if ($tmp=~/^error:/) { undef(%current_permissions); }
       my @readonly_files = &get_marked_as_readonly($domain,$user,$what);
     foreach my $file(@readonly_files){      foreach my $file(@readonly_files){
         my $current_locks = $current_permissions{$file};          my $current_locks = $current_permissions{$file};
         my @new_locks;          my @new_locks;
         my @del_keys;          my @del_keys;
         if (ref($current_locks) eq "ARRAY"){          if (ref($current_locks) eq "ARRAY"){
             foreach my $locker (@{$current_locks}) {              foreach my $locker (@{$current_locks}) {
                 unless ($locker eq $what) {                  my $compare=$locker;
                   if (ref($locker)) { $compare=join('',@{$locker}) };
                   if ($compare eq $symb_crs) {
                       if (defined($file_name) && ($file_name ne $file)) {
                           push(@new_locks, $what);
                       }
                   } else {
                     push(@new_locks, $what);                      push(@new_locks, $what);
                 }                  }
             }              }
Line 3968  sub unmark_as_readonly { Line 4094  sub unmark_as_readonly {
                 $current_permissions{$file} = \@new_locks;                  $current_permissions{$file} = \@new_locks;
             } else {              } else {
                 push(@del_keys, $file);                  push(@del_keys, $file);
                 &Apache::lonnet::del('file_permissions',\@del_keys, $domain, $user);                  &del('file_permissions',\@del_keys, $domain, $user);
                 delete $current_permissions{$file};                  delete $current_permissions{$file};
             }              }
         }          }
     }      }
     &Apache::lonnet::put('file_permissions',\%current_permissions,$domain,$user);      &put('file_permissions',\%current_permissions,$domain,$user);
     return;      return;
 }  }
   
Line 4001  sub dirlist { Line 4127  sub dirlist {
   
     if($udom) {      if($udom) {
         if($uname) {          if($uname) {
             my $listing=reply('ls:'.$dirRoot.'/'.$uri,              my $listing=reply('ls2:'.$dirRoot.'/'.$uri,
                               homeserver($uname,$udom));                                homeserver($uname,$udom));
             return split(/:/,$listing);              my @listing_results;
               if ($listing eq 'unknown_cmd') {
                   $listing=reply('ls:'.$dirRoot.'/'.$uri,
                                  homeserver($uname,$udom));
                   @listing_results = split(/:/,$listing);
               } else {
                   @listing_results = map { &unescape($_); } split(/:/,$listing);
               }
               return @listing_results;
         } elsif(!defined($alternateDirectoryRoot)) {          } elsif(!defined($alternateDirectoryRoot)) {
             my $tryserver;              my $tryserver;
             my %allusers=();              my %allusers=();
             foreach $tryserver (keys %libserv) {              foreach $tryserver (keys %libserv) {
                 if($hostdom{$tryserver} eq $udom) {                  if($hostdom{$tryserver} eq $udom) {
                     my $listing=reply('ls:'.$perlvar{'lonDocRoot'}.'/res/'.                      my $listing=reply('ls2:'.$perlvar{'lonDocRoot'}.'/res/'.
                                       $udom, $tryserver);                                        $udom, $tryserver);
                     if (($listing ne 'no_such_dir') && ($listing ne 'empty')                      my @listing_results;
                         && ($listing ne 'con_lost')) {                      if ($listing eq 'unknown_cmd') {
                         foreach (split(/:/,$listing)) {                          $listing=reply('ls:'.$perlvar{'lonDocRoot'}.'/res/'.
                                          $udom, $tryserver);
                           @listing_results = split(/:/,$listing);
                       } else {
                           @listing_results =
                               map { &unescape($_); } split(/:/,$listing);
                       }
                       if ($listing_results[0] ne 'no_such_dir' && 
                           $listing_results[0] ne 'empty'       &&
                           $listing_results[0] ne 'con_lost') {
                           foreach (@listing_results) {
                             my ($entry,@stat)=split(/&/,$_);                              my ($entry,@stat)=split(/&/,$_);
                             $allusers{$entry}=1;                              $allusers{$entry}=1;
                         }                          }
Line 4085  sub GetFileTimestamp { Line 4229  sub GetFileTimestamp {
   
 sub directcondval {  sub directcondval {
     my $number=shift;      my $number=shift;
     if (!defined($ENV{'user.state.'.$ENV{'request.course.id'}})) {      if (!defined($env{'user.state.'.$env{'request.course.id'}})) {
  &Apache::lonuserstate::evalstate();   &Apache::lonuserstate::evalstate();
     }      }
     if ($ENV{'user.state.'.$ENV{'request.course.id'}}) {      if ($env{'user.state.'.$env{'request.course.id'}}) {
        return substr($ENV{'user.state.'.$ENV{'request.course.id'}},$number,1);         return substr($env{'user.state.'.$env{'request.course.id'}},$number,1);
     } else {      } else {
        return 2;         return 2;
     }      }
Line 4100  sub condval { Line 4244  sub condval {
     my $result=0;      my $result=0;
     my $allpathcond='';      my $allpathcond='';
     foreach (split(/\|/,$condidx)) {      foreach (split(/\|/,$condidx)) {
        if (defined($ENV{'acc.cond.'.$ENV{'request.course.id'}.'.'.$_})) {         if (defined($env{'acc.cond.'.$env{'request.course.id'}.'.'.$_})) {
    $allpathcond.=     $allpathcond.=
                '('.$ENV{'acc.cond.'.$ENV{'request.course.id'}.'.'.$_}.')|';                 '('.$env{'acc.cond.'.$env{'request.course.id'}.'.'.$_}.')|';
        }         }
     }      }
     $allpathcond=~s/\|$//;      $allpathcond=~s/\|$//;
     if ($ENV{'request.course.id'}) {      if ($env{'request.course.id'}) {
        if ($allpathcond) {         if ($allpathcond) {
           my $operand='|';            my $operand='|';
   my @stack;    my @stack;
Line 4141  sub condval { Line 4285  sub condval {
 sub devalidatecourseresdata {  sub devalidatecourseresdata {
     my ($coursenum,$coursedomain)=@_;      my ($coursenum,$coursedomain)=@_;
     my $hashid=$coursenum.':'.$coursedomain;      my $hashid=$coursenum.':'.$coursedomain;
     &devalidate_cache(\%courseresdatacache,$hashid,'courseres');      &devalidate_cache_new('courseres',$hashid);
 }  }
   
 # --------------------------------------------------- Course Resourcedata Query  # --------------------------------------------------- Course Resourcedata Query
   
 sub courseresdata {  sub get_courseresdata {
     my ($coursenum,$coursedomain,@which)=@_;      my ($coursenum,$coursedomain)=@_;
     my $coursehom=&homeserver($coursenum,$coursedomain);      my $coursehom=&homeserver($coursenum,$coursedomain);
     my $hashid=$coursenum.':'.$coursedomain;      my $hashid=$coursenum.':'.$coursedomain;
     my ($result,$cached)=&is_cached(\%courseresdatacache,$hashid,'courseres');      my ($result,$cached)=&is_cached_new('courseres',$hashid);
       my %dumpreply;
     unless (defined($cached)) {      unless (defined($cached)) {
  my %dumpreply=&dump('resourcedata',$coursedomain,$coursenum);   %dumpreply=&dump('resourcedata',$coursedomain,$coursenum);
  $result=\%dumpreply;   $result=\%dumpreply;
  my ($tmp) = keys(%dumpreply);   my ($tmp) = keys(%dumpreply);
  if ($tmp !~ /^(con_lost|error|no_such_host)/i) {   if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
     &do_cache(\%courseresdatacache,$hashid,$result,'courseres');      &do_cache_new('courseres',$hashid,$result,600);
  } elsif ($tmp =~ /^(con_lost|no_such_host)/) {   } elsif ($tmp =~ /^(con_lost|no_such_host)/) {
     return $tmp;      return $tmp;
  } elsif ($tmp =~ /^(error)/) {   } elsif ($tmp =~ /^(error)/) {
     $result=undef;      $result=undef;
     &do_cache(\%courseresdatacache,$hashid,$result,'courseres');      &do_cache_new('courseres',$hashid,$result,600);
  }   }
     }      }
       return $result;
   }
   
   sub devalidateuserresdata {
       my ($uname,$udom)=@_;
       my $hashid="$udom:$uname";
       &devalidate_cache_new('userres',$hashid);
   }
   
   sub get_userresdata {
       my ($uname,$udom)=@_;
       #most student don\'t have any data set, check if there is some data
       if (&EXT_cache_status($udom,$uname)) { return undef; }
   
       my $hashid="$udom:$uname";
       my ($result,$cached)=&is_cached_new('userres',$hashid);
       if (!defined($cached)) {
    my %resourcedata=&dump('resourcedata',$udom,$uname);
    $result=\%resourcedata;
    &do_cache_new('userres',$hashid,$result,600);
       }
       my ($tmp)=keys(%$result);
       if (($tmp!~/^error\:/) && ($tmp!~/^con_lost/)) {
    return $result;
       }
       #error 2 occurs when the .db doesn't exist
       if ($tmp!~/error: 2 /) {
    &logthis("<font color=blue>WARNING:".
    " Trying to get resource data for ".
    $uname." at ".$udom.": ".
    $tmp."</font>");
       } elsif ($tmp=~/error: 2 /) {
    #&EXT_cache_set($udom,$uname);
    &do_cache_new('userres',$hashid,undef,600);
    undef($tmp); # not really an error so don't send it back
       }
       return $tmp;
   }
   
   sub resdata {
       my ($name,$domain,$type,@which)=@_;
       my $result;
       if ($type eq 'course') {
    $result=&get_courseresdata($name,$domain);
       } elsif ($type eq 'user') {
    $result=&get_userresdata($name,$domain);
       }
       if (!ref($result)) { return $result; }    
     foreach my $item (@which) {      foreach my $item (@which) {
  if (defined($result->{$item})) {   if (defined($result->{$item})) {
     return $result->{$item};      return $result->{$item};
Line 4183  sub clear_EXT_cache_status { Line 4376  sub clear_EXT_cache_status {
 sub EXT_cache_status {  sub EXT_cache_status {
     my ($target_domain,$target_user) = @_;      my ($target_domain,$target_user) = @_;
     my $cachename = 'cache.EXT.'.$target_user.'.'.$target_domain;      my $cachename = 'cache.EXT.'.$target_user.'.'.$target_domain;
     if (exists($ENV{$cachename}) && ($ENV{$cachename}+600) > time) {      if (exists($env{$cachename}) && ($env{$cachename}+600) > time) {
         # We know already the user has no data          # We know already the user has no data
         return 1;          return 1;
     } else {      } else {
Line 4194  sub EXT_cache_status { Line 4387  sub EXT_cache_status {
 sub EXT_cache_set {  sub EXT_cache_set {
     my ($target_domain,$target_user) = @_;      my ($target_domain,$target_user) = @_;
     my $cachename = 'cache.EXT.'.$target_user.'.'.$target_domain;      my $cachename = 'cache.EXT.'.$target_user.'.'.$target_domain;
     &appenv($cachename => time);      #&appenv($cachename => time);
 }  }
   
 # --------------------------------------------------------- Value of a Variable  # --------------------------------------------------------- Value of a Variable
Line 4213  sub EXT { Line 4406  sub EXT {
   &Apache::lonxml::whichuser($symbparm);    &Apache::lonxml::whichuser($symbparm);
       if (!$symbparm) { $symbparm=$cursymb; }        if (!$symbparm) { $symbparm=$cursymb; }
     } else {      } else {
  $courseid=$ENV{'request.course.id'};   $courseid=$env{'request.course.id'};
     }      }
     my ($realm,$space,$qualifier,@therest)=split(/\./,$varname);      my ($realm,$space,$qualifier,@therest)=split(/\./,$varname);
     my $rest;      my $rest;
Line 4230  sub EXT { Line 4423  sub EXT {
     if ($realm eq 'user') {      if ($realm eq 'user') {
 # --------------------------------------------------------------- user.resource  # --------------------------------------------------------------- user.resource
  if ($space eq 'resource') {   if ($space eq 'resource') {
     if (defined($Apache::lonhomework::parsing_a_problem)) {      if (defined($Apache::lonhomework::parsing_a_problem) ||
    defined($Apache::lonhomework::parsing_a_task)) {
  return $Apache::lonhomework::history{$qualifierrest};   return $Apache::lonhomework::history{$qualifierrest};
     } else {      } else {
  my %restored;   my %restored;
  if ($publicuser || $ENV{'request.state'} eq 'construct') {   if ($publicuser || $env{'request.state'} eq 'construct') {
     %restored=&tmprestore($symbparm,$courseid,$udom,$uname);      %restored=&tmprestore($symbparm,$courseid,$udom,$uname);
  } else {   } else {
     %restored=&restore($symbparm,$courseid,$udom,$uname);      %restored=&restore($symbparm,$courseid,$udom,$uname);
Line 4247  sub EXT { Line 4441  sub EXT {
             return &allowed($qualifier,$rest);              return &allowed($qualifier,$rest);
 # ------------------------------------------ user.preferences, user.environment  # ------------------------------------------ user.preferences, user.environment
         } elsif (($space eq 'preferences') || ($space eq 'environment')) {          } elsif (($space eq 'preferences') || ($space eq 'environment')) {
     if (($uname eq $ENV{'user.name'}) &&      if (($uname eq $env{'user.name'}) &&
  ($udom eq $ENV{'user.domain'})) {   ($udom eq $env{'user.domain'})) {
  return $ENV{join('.',('environment',$qualifierrest))};   return $env{join('.',('environment',$qualifierrest))};
     } else {      } else {
  my %returnhash;   my %returnhash;
  if (!$publicuser) {   if (!$publicuser) {
Line 4261  sub EXT { Line 4455  sub EXT {
 # ----------------------------------------------------------------- user.course  # ----------------------------------------------------------------- user.course
         } elsif ($space eq 'course') {          } elsif ($space eq 'course') {
     # FIXME - not supporting calls for a specific user      # FIXME - not supporting calls for a specific user
             return $ENV{join('.',('request.course',$qualifier))};              return $env{join('.',('request.course',$qualifier))};
 # ------------------------------------------------------------------- user.role  # ------------------------------------------------------------------- user.role
         } elsif ($space eq 'role') {          } elsif ($space eq 'role') {
     # FIXME - not supporting calls for a specific user      # FIXME - not supporting calls for a specific user
             my ($role,$where)=split(/\./,$ENV{'request.role'});              my ($role,$where)=split(/\./,$env{'request.role'});
             if ($qualifier eq 'value') {              if ($qualifier eq 'value') {
  return $role;   return $role;
             } elsif ($qualifier eq 'extent') {              } elsif ($qualifier eq 'extent') {
Line 4289  sub EXT { Line 4483  sub EXT {
 # ---------------------------------------------- pull stuff out of query string  # ---------------------------------------------- pull stuff out of query string
         &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},          &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
  [$spacequalifierrest]);   [$spacequalifierrest]);
  return $ENV{'form.'.$spacequalifierrest};    return $env{'form.'.$spacequalifierrest}; 
    } elsif ($realm eq 'request') {     } elsif ($realm eq 'request') {
 # ------------------------------------------------------------- request.browser  # ------------------------------------------------------------- request.browser
         if ($space eq 'browser') {          if ($space eq 'browser') {
Line 4300  sub EXT { Line 4494  sub EXT {
     return 0;      return 0;
  }   }
     } else {      } else {
  return $ENV{'browser.'.$qualifier};   return $env{'browser.'.$qualifier};
     }      }
 # ------------------------------------------------------------ request.filename  # ------------------------------------------------------------ request.filename
         } else {          } else {
             return $ENV{'request.'.$spacequalifierrest};              return $env{'request.'.$spacequalifierrest};
         }          }
     } elsif ($realm eq 'course') {      } elsif ($realm eq 'course') {
 # ---------------------------------------------------------- course.description  # ---------------------------------------------------------- course.description
         return $ENV{'course.'.$courseid.'.'.$spacequalifierrest};          return $env{'course.'.$courseid.'.'.$spacequalifierrest};
     } elsif ($realm eq 'resource') {      } elsif ($realm eq 'resource') {
   
  my $section;   my $section;
  if (defined($courseid) && $courseid eq $ENV{'request.course.id'}) {   if (defined($courseid) && $courseid eq $env{'request.course.id'}) {
     if (!$symbparm) { $symbparm=&symbread(); }      if (!$symbparm) { $symbparm=&symbread(); }
  }   }
    my ($courselevelm,$courselevel);
  if ($symbparm && defined($courseid) &&    if ($symbparm && defined($courseid) && 
     $courseid eq $ENV{'request.course.id'}) {      $courseid eq $env{'request.course.id'}) {
   
     #print '<br>'.$space.' - '.$qualifier.' - '.$spacequalifierrest;      #print '<br>'.$space.' - '.$qualifier.' - '.$spacequalifierrest;
   
Line 4327  sub EXT { Line 4522  sub EXT {
     my $symbparm=$symbp.'.'.$spacequalifierrest;      my $symbparm=$symbp.'.'.$spacequalifierrest;
     my $mapparm=$mapp.'___(all).'.$spacequalifierrest;      my $mapparm=$mapp.'___(all).'.$spacequalifierrest;
   
     if (($ENV{'user.name'} eq $uname) &&      if (($env{'user.name'} eq $uname) &&
  ($ENV{'user.domain'} eq $udom)) {   ($env{'user.domain'} eq $udom)) {
  $section=$ENV{'request.course.sec'};   $section=$env{'request.course.sec'};
     } else {      } else {
  if (! defined($usection)) {   if (! defined($usection)) {
     $section=&getsection($udom,$uname,$courseid);      $section=&getsection($udom,$uname,$courseid);
Line 4342  sub EXT { Line 4537  sub EXT {
     my $seclevelr=$courseid.'.['.$section.'].'.$symbparm;      my $seclevelr=$courseid.'.['.$section.'].'.$symbparm;
     my $seclevelm=$courseid.'.['.$section.'].'.$mapparm;      my $seclevelm=$courseid.'.['.$section.'].'.$mapparm;
   
     my $courselevel=$courseid.'.'.$spacequalifierrest;      $courselevel=$courseid.'.'.$spacequalifierrest;
     my $courselevelr=$courseid.'.'.$symbparm;      my $courselevelr=$courseid.'.'.$symbparm;
     my $courselevelm=$courseid.'.'.$mapparm;      $courselevelm=$courseid.'.'.$mapparm;
   
 # ----------------------------------------------------------- first, check user  # ----------------------------------------------------------- first, check user
     #most student don\'t have any data set, check if there is some data  
     if (! &EXT_cache_status($udom,$uname)) {  
  my $hashid="$udom:$uname";  
  my ($result,$cached)=&is_cached(\%userresdatacache,$hashid,  
  'userres');  
  if (!defined($cached)) {  
     my %resourcedata=&dump('resourcedata',$udom,$uname);  
     $result=\%resourcedata;  
     &do_cache(\%userresdatacache,$hashid,$result,'userres');  
  }  
  my ($tmp)=keys(%$result);  
  if (($tmp!~/^error\:/) && ($tmp!~/^con_lost/)) {  
     if ($$result{$courselevelr}) {  
  return $$result{$courselevelr}; }  
     if ($$result{$courselevelm}) {  
  return $$result{$courselevelm}; }  
     if ($$result{$courselevel}) {  
  return $$result{$courselevel}; }  
  } else {  
     #error 2 occurs when the .db doesn't exist  
     if ($tmp!~/error: 2 /) {  
  &logthis("<font color=blue>WARNING:".  
  " Trying to get resource data for ".  
  $uname." at ".$udom.": ".  
  $tmp."</font>");  
     } elsif ($tmp=~/error: 2 /) {  
  &EXT_cache_set($udom,$uname);  
     } elsif ($tmp =~ /^(con_lost|no_such_host)/) {  
  return $tmp;  
     }  
  }  
     }  
   
 # -------------------------------------------------------- second, check course      my $userreply=&resdata($uname,$udom,'user',
          ($courselevelr,$courselevelm,
     my $coursereply=&courseresdata($ENV{'course.'.$courseid.'.num'},   $courselevel));
    $ENV{'course.'.$courseid.'.domain'},  
    ($seclevelr,$seclevelm,$seclevel,      if (defined($userreply)) { return $userreply; }
     $courselevelr,$courselevelm,  
     $courselevel));  # ------------------------------------------------ second, check some of course
   
       my $coursereply=&resdata($env{'course.'.$courseid.'.num'},
        $env{'course.'.$courseid.'.domain'},
        'course',
        ($seclevelr,$seclevelm,$seclevel,
         $courselevelr));
     if (defined($coursereply)) { return $coursereply; }      if (defined($coursereply)) { return $coursereply; }
   
 # ------------------------------------------------------ third, check map parms  # ------------------------------------------------------ third, check map parms
     my %parmhash=();      my %parmhash=();
     my $thisparm='';      my $thisparm='';
     if (tie(%parmhash,'GDBM_File',      if (tie(%parmhash,'GDBM_File',
     $ENV{'request.course.fn'}.'_parms.db',      $env{'request.course.fn'}.'_parms.db',
     &GDBM_READER(),0640)) {      &GDBM_READER(),0640)) {
  $thisparm=$parmhash{$symbparm};   $thisparm=$parmhash{$symbparm};
  untie(%parmhash);   untie(%parmhash);
     }      }
     if ($thisparm) { return $thisparm; }      if ($thisparm) { return $thisparm; }
  }   }
 # --------------------------------------------- last, look in resource metadata  # ------------------------------------------ fourth, look in resource metadata
   
  $spacequalifierrest=~s/\./\_/;   $spacequalifierrest=~s/\./\_/;
  my $filename;   my $filename;
Line 4408  sub EXT { Line 4577  sub EXT {
  if ($symbparm) {   if ($symbparm) {
     $filename=(&decode_symb($symbparm))[2];      $filename=(&decode_symb($symbparm))[2];
  } else {   } else {
     $filename=$ENV{'request.filename'};      $filename=$env{'request.filename'};
  }   }
  my $metadata=&metadata($filename,$spacequalifierrest);   my $metadata=&metadata($filename,$spacequalifierrest);
  if (defined($metadata)) { return $metadata; }   if (defined($metadata)) { return $metadata; }
  $metadata=&metadata($filename,'parameter_'.$spacequalifierrest);   $metadata=&metadata($filename,'parameter_'.$spacequalifierrest);
  if (defined($metadata)) { return $metadata; }   if (defined($metadata)) { return $metadata; }
   
   # ---------------------------------------------- fourth, look in rest pf course
    if ($symbparm && defined($courseid) && 
       $courseid eq $env{'request.course.id'}) {
       my $coursereply=&resdata($env{'course.'.$courseid.'.num'},
        $env{'course.'.$courseid.'.domain'},
        'course',
        ($courselevelm,$courselevel));
       if (defined($coursereply)) { return $coursereply; }
    }
 # ------------------------------------------------------------------ Cascade up  # ------------------------------------------------------------------ Cascade up
  unless ($space eq '0') {   unless ($space eq '0') {
     my @parts=split(/_/,$space);      my @parts=split(/_/,$space);
Line 4432  sub EXT { Line 4610  sub EXT {
 # ---------------------------------------------------- Any other user namespace  # ---------------------------------------------------- Any other user namespace
     } elsif ($realm eq 'environment') {      } elsif ($realm eq 'environment') {
 # ----------------------------------------------------------------- environment  # ----------------------------------------------------------------- environment
  if (($uname eq $ENV{'user.name'})&&($udom eq $ENV{'user.domain'})) {   if (($uname eq $env{'user.name'})&&($udom eq $env{'user.domain'})) {
     return $ENV{'environment.'.$spacequalifierrest};      return $env{'environment.'.$spacequalifierrest};
  } else {   } else {
     my %returnhash=&userenvironment($udom,$uname,      my %returnhash=&userenvironment($udom,$uname,
     $spacequalifierrest);      $spacequalifierrest);
Line 4483  sub add_prefix_and_part { Line 4661  sub add_prefix_and_part {
   
 # ---------------------------------------------------------------- Get metadata  # ---------------------------------------------------------------- Get metadata
   
   my %metaentry;
 sub metadata {  sub metadata {
     my ($uri,$what,$liburi,$prefix,$depthcount)=@_;      my ($uri,$what,$liburi,$prefix,$depthcount)=@_;
     $uri=&declutter($uri);      $uri=&declutter($uri);
Line 4502  sub metadata { Line 4681  sub metadata {
 # Everything is cached by the main uri, libraries are never directly cached  # Everything is cached by the main uri, libraries are never directly cached
 #  #
     if (!defined($liburi)) {      if (!defined($liburi)) {
  my ($result,$cached)=&is_cached(\%metacache,$uri,'meta');   my ($result,$cached)=&is_cached_new('meta',$uri);
  if (defined($cached)) { return $result->{':'.$what}; }   if (defined($cached)) { return $result->{':'.$what}; }
     }      }
     {      {
 #  #
 # Is this a recursive call for a library?  # Is this a recursive call for a library?
 #  #
  if (! exists($metacache{$uri})) {  # if (! exists($metacache{$uri})) {
     $metacache{$uri}={};  #    $metacache{$uri}={};
  }  # }
         if ($liburi) {          if ($liburi) {
     $liburi=&declutter($liburi);      $liburi=&declutter($liburi);
             $filename=$liburi;              $filename=$liburi;
         } else {          } else {
     &devalidate_cache(\%metacache,$uri,'meta');      &devalidate_cache_new('meta',$uri);
       undef(%metaentry);
  }   }
         my %metathesekeys=();          my %metathesekeys=();
         unless ($filename=~/\.meta$/) { $filename.='.meta'; }          unless ($filename=~/\.meta$/) { $filename.='.meta'; }
  my $metastring;   my $metastring;
  if ($uri !~ m|^uploaded/|) {   if ($uri !~ m -^(uploaded|editupload)/-) {
     my $file=&filelocation('',&clutter($filename));      my $file=&filelocation('',&clutter($filename));
     push(@{$metacache{$uri.'.file'}},$file);      #push(@{$metaentry{$uri.'.file'}},$file);
     $metastring=&getfile($file);      $metastring=&getfile($file);
  }   }
         my $parser=HTML::LCParser->new(\$metastring);          my $parser=HTML::LCParser->new(\$metastring);
Line 4540  sub metadata { Line 4720  sub metadata {
     if (defined($token->[2]->{'id'})) {       if (defined($token->[2]->{'id'})) { 
  $keyroot.='_'.$token->[2]->{'id'};    $keyroot.='_'.$token->[2]->{'id'}; 
     }      }
     if ($metacache{$uri}->{':packages'}) {      if ($metaentry{':packages'}) {
  $metacache{$uri}->{':packages'}.=','.$package.$keyroot;   $metaentry{':packages'}.=','.$package.$keyroot;
     } else {      } else {
  $metacache{$uri}->{':packages'}=$package.$keyroot;   $metaentry{':packages'}=$package.$keyroot;
     }      }
     foreach (keys %packagetab) {      foreach (sort keys %packagetab) {
  my $part=$keyroot;   my $part=$keyroot;
  $part=~s/^\_//;   $part=~s/^\_//;
  if ($_=~/^\Q$package\E\&/ ||    if ($_=~/^\Q$package\E\&/ || 
Line 4565  sub metadata { Line 4745  sub metadata {
     if ($subp eq 'display') {      if ($subp eq 'display') {
  $value.=' [Part: '.$part.']';   $value.=' [Part: '.$part.']';
     }      }
     $metacache{$uri}->{':'.$unikey.'.part'}=$part;      $metaentry{':'.$unikey.'.part'}=$part;
     $metathesekeys{$unikey}=1;      $metathesekeys{$unikey}=1;
     unless (defined($metacache{$uri}->{':'.$unikey.'.'.$subp})) {      unless (defined($metaentry{':'.$unikey.'.'.$subp})) {
  $metacache{$uri}->{':'.$unikey.'.'.$subp}=$value;   $metaentry{':'.$unikey.'.'.$subp}=$value;
     }      }
     if (defined($metacache{$uri}->{':'.$unikey.'.default'})) {      if (defined($metaentry{':'.$unikey.'.default'})) {
  $metacache{$uri}->{':'.$unikey}=   $metaentry{':'.$unikey}=
     $metacache{$uri}->{':'.$unikey.'.default'};      $metaentry{':'.$unikey.'.default'};
     }      }
  }   }
     }      }
Line 4605  sub metadata { Line 4785  sub metadata {
     foreach (sort(split(/\,/,&metadata($uri,'keys',      foreach (sort(split(/\,/,&metadata($uri,'keys',
        $location,$unikey,         $location,$unikey,
        $depthcount+1)))) {         $depthcount+1)))) {
  $metacache{$uri}->{':'.$_}=$metacache{$uri}->{':'.$_};   $metaentry{':'.$_}=$metaentry{':'.$_};
  $metathesekeys{$_}=1;   $metathesekeys{$_}=1;
     }      }
  }   }
Line 4616  sub metadata { Line 4796  sub metadata {
  }   }
  $metathesekeys{$unikey}=1;   $metathesekeys{$unikey}=1;
  foreach (@{$token->[3]}) {   foreach (@{$token->[3]}) {
     $metacache{$uri}->{':'.$unikey.'.'.$_}=$token->[2]->{$_};      $metaentry{':'.$unikey.'.'.$_}=$token->[2]->{$_};
  }   }
  my $internaltext=&HTML::Entities::decode($parser->get_text('/'.$entry));   my $internaltext=&HTML::Entities::decode($parser->get_text('/'.$entry));
  my $default=$metacache{$uri}->{':'.$unikey.'.default'};   my $default=$metaentry{':'.$unikey.'.default'};
  if ( $internaltext =~ /^\s*$/ && $default !~ /^\s*$/) {   if ( $internaltext =~ /^\s*$/ && $default !~ /^\s*$/) {
  # only ws inside the tag, and not in default, so use default   # only ws inside the tag, and not in default, so use default
  # as value   # as value
     $metacache{$uri}->{':'.$unikey}=$default;      $metaentry{':'.$unikey}=$default;
  } else {   } else {
   # either something interesting inside the tag or default    # either something interesting inside the tag or default
                   # uninteresting                    # uninteresting
     $metacache{$uri}->{':'.$unikey}=$internaltext;      $metaentry{':'.$unikey}=$internaltext;
  }   }
 # end of not-a-package not-a-library import  # end of not-a-package not-a-library import
     }      }
Line 4638  sub metadata { Line 4818  sub metadata {
  }   }
  my ($extension) = ($uri =~ /\.(\w+)$/);   my ($extension) = ($uri =~ /\.(\w+)$/);
  foreach my $key (sort(keys(%packagetab))) {   foreach my $key (sort(keys(%packagetab))) {
     #&logthis("extsion1 $extension $key !!");  
     #no specific packages #how's our extension      #no specific packages #how's our extension
     if ($key!~/^extension_\Q$extension\E&/) { next; }      if ($key!~/^extension_\Q$extension\E&/) { next; }
     &metadata_create_package_def($uri,$key,'extension_'.$extension,      &metadata_create_package_def($uri,$key,'extension_'.$extension,
  \%metathesekeys);   \%metathesekeys);
  }   }
  if (!exists($metacache{$uri}->{':packages'})) {   if (!exists($metaentry{':packages'})) {
     foreach my $key (sort(keys(%packagetab))) {      foreach my $key (sort(keys(%packagetab))) {
  #no specific packages well let's get default then   #no specific packages well let's get default then
  if ($key!~/^default&/) { next; }   if ($key!~/^default&/) { next; }
Line 4653  sub metadata { Line 4832  sub metadata {
     }      }
  }   }
 # are there custom rights to evaluate  # are there custom rights to evaluate
  if ($metacache{$uri}->{':copyright'} eq 'custom') {   if ($metaentry{':copyright'} eq 'custom') {
   
     #      #
     # Importing a rights file here      # Importing a rights file here
     #      #
     unless ($depthcount) {      unless ($depthcount) {
  my $location=$metacache{$uri}->{':customdistributionfile'};   my $location=$metaentry{':customdistributionfile'};
  my $dir=$filename;   my $dir=$filename;
  $dir=~s|[^/]*$||;   $dir=~s|[^/]*$||;
  $location=&filelocation($dir,$location);   $location=&filelocation($dir,$location);
  foreach (sort(split(/\,/,&metadata($uri,'keys',   foreach (sort(split(/\,/,&metadata($uri,'keys',
    $location,'_rights',     $location,'_rights',
    $depthcount+1)))) {     $depthcount+1)))) {
     $metacache{$uri}->{':'.$_}=$metacache{$uri}->{':'.$_};      #$metaentry{':'.$_}=$metacache{$uri}->{':'.$_};
     $metathesekeys{$_}=1;      $metathesekeys{$_}=1;
  }   }
     }      }
  }   }
  $metacache{$uri}->{':keys'}=join(',',keys %metathesekeys);   $metaentry{':keys'}=join(',',keys %metathesekeys);
  &metadata_generate_part0(\%metathesekeys,$metacache{$uri},$uri);   &metadata_generate_part0(\%metathesekeys,\%metaentry,$uri);
  $metacache{$uri}->{':allpossiblekeys'}=join(',',keys %metathesekeys);   $metaentry{':allpossiblekeys'}=join(',',keys %metathesekeys);
  &do_cache(\%metacache,$uri,$metacache{$uri},'meta');   &do_cache_new('meta',$uri,\%metaentry,60*60*24);
 # this is the end of "was not already recently cached  # this is the end of "was not already recently cached
     }      }
     return $metacache{$uri}->{':'.$what};      return $metaentry{':'.$what};
 }  }
   
 sub metadata_create_package_def {  sub metadata_create_package_def {
Line 4685  sub metadata_create_package_def { Line 4864  sub metadata_create_package_def {
     my ($pack,$name,$subp)=split(/\&/,$key);      my ($pack,$name,$subp)=split(/\&/,$key);
     if ($subp eq 'default') { next; }      if ($subp eq 'default') { next; }
           
     if (defined($metacache{$uri}->{':packages'})) {      if (defined($metaentry{':packages'})) {
  $metacache{$uri}->{':packages'}.=','.$package;   $metaentry{':packages'}.=','.$package;
     } else {      } else {
  $metacache{$uri}->{':packages'}=$package;   $metaentry{':packages'}=$package;
     }      }
     my $value=$packagetab{$key};      my $value=$packagetab{$key};
     my $unikey;      my $unikey;
     $unikey='parameter_0_'.$name;      $unikey='parameter_0_'.$name;
     $metacache{$uri}->{':'.$unikey.'.part'}=0;      $metaentry{':'.$unikey.'.part'}=0;
     $$metathesekeys{$unikey}=1;      $$metathesekeys{$unikey}=1;
     unless (defined($metacache{$uri}->{':'.$unikey.'.'.$subp})) {      unless (defined($metaentry{':'.$unikey.'.'.$subp})) {
  $metacache{$uri}->{':'.$unikey.'.'.$subp}=$value;   $metaentry{':'.$unikey.'.'.$subp}=$value;
     }      }
     if (defined($metacache{$uri}->{':'.$unikey.'.default'})) {      if (defined($metaentry{':'.$unikey.'.default'})) {
  $metacache{$uri}->{':'.$unikey}=   $metaentry{':'.$unikey}=
     $metacache{$uri}->{':'.$unikey.'.default'};      $metaentry{':'.$unikey.'.default'};
     }      }
 }  }
   
Line 4726  sub metadata_generate_part0 { Line 4905  sub metadata_generate_part0 {
    '.type'};     '.type'};
       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/\Q$expr\E/\[Part: 0\]/;        $olddis=~s/\Q$expr\E/\[Part: 0\]/;
       $$metacache{"$key.display"}=$olddis;        $$metacache{"$key.display"}=$olddis;
     }      }
Line 4738  sub gettitle { Line 4917  sub gettitle {
     my $urlsymb=shift;      my $urlsymb=shift;
     my $symb=&symbread($urlsymb);      my $symb=&symbread($urlsymb);
     if ($symb) {      if ($symb) {
  my ($result,$cached)=&is_cached(\%titlecache,$symb,'title',600);   my $key=$env{'request.course.id'}."\0".$symb;
    my ($result,$cached)=&is_cached_new('title',$key);
  if (defined($cached)) {    if (defined($cached)) { 
     return $result;      return $result;
  }   }
  my ($map,$resid,$url)=&decode_symb($symb);   my ($map,$resid,$url)=&decode_symb($symb);
  my $title='';   my $title='';
  my %bighash;   my %bighash;
  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 $mapid=$bighash{'map_pc_'.&clutter($map)};      my $mapid=$bighash{'map_pc_'.&clutter($map)};
     $title=$bighash{'title_'.$mapid.'.'.$resid};      $title=$bighash{'title_'.$mapid.'.'.$resid};
Line 4753  sub gettitle { Line 4933  sub gettitle {
  }   }
  $title=~s/\&colon\;/\:/gs;   $title=~s/\&colon\;/\:/gs;
  if ($title) {   if ($title) {
     return &do_cache(\%titlecache,$symb,$title,'title');      return &do_cache_new('title',$key,$title,600);
  }   }
  $urlsymb=$url;   $urlsymb=$url;
     }      }
Line 4761  sub gettitle { Line 4941  sub gettitle {
     if (!$title) { $title=(split('/',$urlsymb))[-1]; }          if (!$title) { $title=(split('/',$urlsymb))[-1]; }    
     return $title;      return $title;
 }  }
       
   sub get_slot {
       my ($which,$cnum,$cdom)=@_;
       if (!$cnum || !$cdom) {
    (undef,my $courseid)=&Apache::lonxml::whichuser();
    $cdom=$env{'course.'.$courseid.'.domain'};
    $cnum=$env{'course.'.$courseid.'.num'};
       }
       my %slotinfo=&get('slots',[$which],$cdom,$cnum);
       &Apache::lonhomework::showhash(%slotinfo);
       my ($tmp)=keys(%slotinfo);
       if ($tmp=~/^error:/) { return (); }
       if (ref($slotinfo{$which}) eq 'HASH') {
    return %{$slotinfo{$which}};
       }
       return $slotinfo{$which};
   }
 # ------------------------------------------------- Update symbolic store links  # ------------------------------------------------- Update symbolic store links
   
 sub symblist {  sub symblist {
     my ($mapname,%newhash)=@_;      my ($mapname,%newhash)=@_;
     $mapname=&deversion(&declutter($mapname));      $mapname=&deversion(&declutter($mapname));
     my %hash;      my %hash;
     if (($ENV{'request.course.fn'}) && (%newhash)) {      if (($env{'request.course.fn'}) && (%newhash)) {
         if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.'_symb.db',          if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                       &GDBM_WRCREAT(),0640)) {                        &GDBM_WRCREAT(),0640)) {
     foreach (keys %newhash) {      foreach (keys %newhash) {
                 $hash{declutter($_)}=$mapname.'___'.&deversion($newhash{$_});                  $hash{declutter($_)}=&encode_symb($mapname,$newhash{$_}->[1],
     $newhash{$_}->[0]);
             }              }
             if (untie(%hash)) {              if (untie(%hash)) {
  return 'ok';   return 'ok';
Line 4804  sub symbverify { Line 5001  sub symbverify {
     my %bighash;      my %bighash;
     my $okay=0;      my $okay=0;
   
     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($thisurl)};          my $ids=$bighash{'ids_'.&clutter($thisurl)};
         unless ($ids) {           unless ($ids) { 
Line 4813  sub symbverify { Line 5010  sub symbverify {
         if ($ids) {          if ($ids) {
 # ------------------------------------------------------------------- Has ID(s)  # ------------------------------------------------------------------- Has ID(s)
     foreach (split(/\,/,$ids)) {      foreach (split(/\,/,$ids)) {
                my ($mapid,$resid)=split(/\./,$_);         my ($mapid,$resid)=split(/\./,$_);
                if (                 if (
   &symbclean(&declutter($bighash{'map_id_'.$mapid}).'___'.$resid.'___'.$thisfn)    &symbclean(&declutter($bighash{'map_id_'.$mapid}).'___'.$resid.'___'.$thisfn)
    eq $symb) {      eq $symb) { 
    if (($ENV{'request.role.adv'}) ||     if (($env{'request.role.adv'}) ||
        $bighash{'encrypted_'.$_} eq $ENV{'request.enc'}) {         $bighash{'encrypted_'.$_} eq $env{'request.enc'}) {
        $okay=1;          $okay=1; 
    }     }
        }         }
Line 4862  sub decode_symb { Line 5059  sub decode_symb {
   
 sub fixversion {  sub fixversion {
     my $fn=shift;      my $fn=shift;
     if ($fn=~/^(adm|uploaded|public)/) { return $fn; }      if ($fn=~/^(adm|uploaded|editupload|public)/) { return $fn; }
     my %bighash;      my %bighash;
     my $uri=&clutter($fn);      my $uri=&clutter($fn);
     my $key=$ENV{'request.course.id'}.'_'.$uri;      my $key=$env{'request.course.id'}.'_'.$uri;
 # is this cached?  # is this cached?
     my ($result,$cached)=&is_cached(\%courseresversioncache,$key,      my ($result,$cached)=&is_cached_new('courseresversion',$key);
     'courseresversion',600);  
     if (defined($cached)) { return $result; }      if (defined($cached)) { return $result; }
 # unfortunately not cached, or expired  # unfortunately not cached, or expired
     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)) {
   if ($bighash{'version_'.$uri}) {    if ($bighash{'version_'.$uri}) {
      my $version=$bighash{'version_'.$uri};       my $version=$bighash{'version_'.$uri};
Line 4882  sub fixversion { Line 5078  sub fixversion {
   }    }
   untie %bighash;    untie %bighash;
     }      }
     return &do_cache      return &do_cache_new('courseresversion',$key,&declutter($uri),600);
  (\%courseresversioncache,$key,&declutter($uri),'courseresversion');  
 }  }
   
 sub deversion {  sub deversion {
Line 4897  sub deversion { Line 5092  sub deversion {
 sub symbread {  sub symbread {
     my ($thisfn,$donotrecurse)=@_;      my ($thisfn,$donotrecurse)=@_;
     my $cache_str='request.symbread.cached.'.$thisfn;      my $cache_str='request.symbread.cached.'.$thisfn;
     if (defined($ENV{$cache_str})) { return $ENV{$cache_str}; }      if (defined($env{$cache_str})) { return $env{$cache_str}; }
 # no filename provided? try from environment  # no filename provided? try from environment
     unless ($thisfn) {      unless ($thisfn) {
         if ($ENV{'request.symb'}) {          if ($env{'request.symb'}) {
     return $ENV{$cache_str}=&symbclean($ENV{'request.symb'});      return $env{$cache_str}=&symbclean($env{'request.symb'});
  }   }
  $thisfn=$ENV{'request.filename'};   $thisfn=$env{'request.filename'};
     }      }
     if ($thisfn=~m|^/enc/|) { $thisfn=&Apache::lonenc::unencrypted($thisfn); }      if ($thisfn=~m|^/enc/|) { $thisfn=&Apache::lonenc::unencrypted($thisfn); }
 # is that filename actually a symb? Verify, clean, and return  # is that filename actually a symb? Verify, clean, and return
     if ($thisfn=~/\_\_\_\d+\_\_\_(.*)$/) {      if ($thisfn=~/\_\_\_\d+\_\_\_(.*)$/) {
  if (&symbverify($thisfn,$1)) {   if (&symbverify($thisfn,$1)) {
     return $ENV{$cache_str}=&symbclean($thisfn);      return $env{$cache_str}=&symbclean($thisfn);
  }   }
     }      }
     $thisfn=declutter($thisfn);      $thisfn=declutter($thisfn);
     my %hash;      my %hash;
     my %bighash;      my %bighash;
     my $syval='';      my $syval='';
     if (($ENV{'request.course.fn'}) && ($thisfn)) {      if (($env{'request.course.fn'}) && ($thisfn)) {
         my $targetfn = $thisfn;          my $targetfn = $thisfn;
         if ( ($thisfn =~ m/^uploaded\//) && ($thisfn !~ m/\.(page|sequence)$/) ) {          if ( ($thisfn =~ m/^(uploaded|editupload)\//) && ($thisfn !~ m/\.(page|sequence)$/) ) {
             $targetfn = 'adm/wrapper/'.$thisfn;              $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{$targetfn};      $syval=$hash{$targetfn};
             untie(%hash);              untie(%hash);
         }          }
 # ---------------------------------------------------------- There was an entry  # ---------------------------------------------------------- There was an entry
         if ($syval) {          if ($syval) {
            unless ($syval=~/\_\d+$/) {      #unless ($syval=~/\_\d+$/) {
        unless ($ENV{'form.request.prefix'}=~/\.(\d+)\_$/) {   #unless ($env{'form.request.prefix'}=~/\.(\d+)\_$/) {
                   &appenv('request.ambiguous' => $thisfn);      #&appenv('request.ambiguous' => $thisfn);
   return $ENV{$cache_str}='';      #return $env{$cache_str}='';
                }       #}    
                $syval.=$1;   #$syval.=$1;
    }      #}
         } else {          } else {
 # ------------------------------------------------------- Was not in symb table  # ------------------------------------------------------- Was not in symb table
            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)) {
 # ---------------------------------------------- Get ID(s) for current resource  # ---------------------------------------------- Get ID(s) for current resource
               my $ids=$bighash{'ids_'.&clutter($thisfn)};                my $ids=$bighash{'ids_'.&clutter($thisfn)};
Line 4954  sub symbread { Line 5149  sub symbread {
                  if ($#possibilities==0) {                   if ($#possibilities==0) {
 # ----------------------------------------------- There is only one possibility  # ----------------------------------------------- There is only one possibility
      my ($mapid,$resid)=split(/\./,$ids);       my ($mapid,$resid)=split(/\./,$ids);
                      $syval=declutter($bighash{'map_id_'.$mapid}).'___'.$resid;       $syval=&encode_symb($bighash{'map_id_'.$mapid},
       $resid,$thisfn);
                  } elsif (!$donotrecurse) {                   } elsif (!$donotrecurse) {
 # ------------------------------------------ There is more than one possibility  # ------------------------------------------ There is more than one possibility
                      my $realpossible=0;                       my $realpossible=0;
Line 4964  sub symbread { Line 5160  sub symbread {
              my ($mapid,$resid)=split(/\./,$_);               my ($mapid,$resid)=split(/\./,$_);
                             if ($bighash{'map_type_'.$mapid} ne 'page') {                              if ($bighash{'map_type_'.$mapid} ne 'page') {
  $realpossible++;   $realpossible++;
                                 $syval=declutter($bighash{'map_id_'.$mapid}).                                  $syval=&encode_symb($bighash{'map_id_'.$mapid},
                                        '___'.$resid;      $resid,$thisfn);
                             }                              }
  }   }
                      }                       }
Line 4978  sub symbread { Line 5174  sub symbread {
            }             }
         }          }
         if ($syval) {          if ($syval) {
     return $ENV{$cache_str}=&symbclean($syval.'___'.$thisfn);      return $env{$cache_str}=$syval;
         }          }
     }      }
     &appenv('request.ambiguous' => $thisfn);      &appenv('request.ambiguous' => $thisfn);
     return $ENV{$cache_str}='';      return $env{$cache_str}='';
 }  }
   
 # ---------------------------------------------------------- Return random seed  # ---------------------------------------------------------- Return random seed
Line 5041  sub get_rand_alg { Line 5237  sub get_rand_alg {
     my ($courseid)=@_;      my ($courseid)=@_;
     if (!$courseid) { $courseid=(&Apache::lonxml::whichuser())[1]; }      if (!$courseid) { $courseid=(&Apache::lonxml::whichuser())[1]; }
     if ($courseid) {      if ($courseid) {
  return $ENV{"course.$courseid.rndseed"};   return $env{"course.$courseid.rndseed"};
     }      }
     return &latest_rnd_algorithm_id();      return &latest_rnd_algorithm_id();
 }  }
Line 5053  sub validCODE { Line 5249  sub validCODE {
 }  }
   
 sub getCODE {  sub getCODE {
     if (&validCODE($ENV{'form.CODE'})) { return $ENV{'form.CODE'}; }      if (&validCODE($env{'form.CODE'})) { return $env{'form.CODE'}; }
     if (defined($Apache::lonhomework::parsing_a_problem) &&      if ( (defined($Apache::lonhomework::parsing_a_problem) ||
  &validCODE($Apache::lonhomework::history{'resource.CODE'})) {    defined($Apache::lonhomework::parsing_a_task) ) &&
    &validCODE($Apache::lonhomework::history{'resource.CODE'})) {
  return $Apache::lonhomework::history{'resource.CODE'};   return $Apache::lonhomework::history{'resource.CODE'};
     }      }
     return undef;      return undef;
Line 5255  sub latest_receipt_algorithm_id { Line 5452  sub latest_receipt_algorithm_id {
 sub recunique {  sub recunique {
     my $fucourseid=shift;      my $fucourseid=shift;
     my $unique;      my $unique;
     if ($ENV{"course.$fucourseid.receiptalg"} eq 'receipt2') {      if ($env{"course.$fucourseid.receiptalg"} eq 'receipt2') {
  $unique=$ENV{"course.$fucourseid.internal.encseed"};   $unique=$env{"course.$fucourseid.internal.encseed"};
     } else {      } else {
  $unique=$perlvar{'lonReceipt'};   $unique=$perlvar{'lonReceipt'};
     }      }
Line 5266  sub recunique { Line 5463  sub recunique {
 sub recprefix {  sub recprefix {
     my $fucourseid=shift;      my $fucourseid=shift;
     my $prefix;      my $prefix;
     if ($ENV{"course.$fucourseid.receiptalg"} eq 'receipt2') {      if ($env{"course.$fucourseid.receiptalg"} eq 'receipt2') {
  $prefix=$ENV{"course.$fucourseid.internal.encpref"};   $prefix=$env{"course.$fucourseid.internal.encpref"};
     } else {      } else {
  $prefix=$perlvar{'lonHostID'};   $prefix=$perlvar{'lonHostID'};
     }      }
Line 5283  sub ireceipt { Line 5480  sub ireceipt {
     my $cunique=&recunique($fucourseid);      my $cunique=&recunique($fucourseid);
     my $cpart=unpack("%32S*",$part);      my $cpart=unpack("%32S*",$part);
     my $return =&recprefix($fucourseid).'-';      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).
        " and ".($cpart%$cudom));         " and ".($cpart%$cudom));
                 
Line 5325  sub receipt { Line 5522  sub receipt {
   
 sub getfile {  sub getfile {
     my ($file) = @_;      my ($file) = @_;
       if ($file =~ m -^/*(uploaded|editupload)/-) { $file=&filelocation("",$file); }
     if ($file =~ m|^/*uploaded/|) { $file=&filelocation("",$file); }  
     &repcopy($file);      &repcopy($file);
     return &readfile($file);      return &readfile($file);
 }  }
   
 sub repcopy_userfile {  sub repcopy_userfile {
     my ($file)=@_;      my ($file)=@_;
       if ($file =~ m -^/*(uploaded|editupload)/-) { $file=&filelocation("",$file); }
     if ($file =~ m|^/*uploaded/|) { $file=&filelocation("",$file); }      if ($file =~ m|^/home/httpd/html/lonUsers/|) { return 'ok'; }
     if ($file =~ m|^/home/httpd/html/lonUsers/|) { return OK; }  
   
     my ($cdom,$cnum,$filename) =       my ($cdom,$cnum,$filename) = 
  ($file=~m|^\Q$perlvar{'lonDocRoot'}\E/+userfiles/+([^/]+)/+([^/]+)/+(.*)|);   ($file=~m|^\Q$perlvar{'lonDocRoot'}\E/+userfiles/+([^/]+)/+([^/]+)/+(.*)|);
     my ($info,$rtncode);      my ($info,$rtncode);
Line 5359  sub repcopy_userfile { Line 5553  sub repcopy_userfile {
     return -1;      return -1;
  }   }
  if ($info < $fileinfo[9]) {   if ($info < $fileinfo[9]) {
     return OK;      return 'ok';
  }   }
  $info = '';   $info = '';
  $lwpresp = &getuploaded('GET',$uri,$cdom,$cnum,\$info,\$rtncode);   $lwpresp = &getuploaded('GET',$uri,$cdom,$cnum,\$info,\$rtncode);
Line 5393  sub repcopy_userfile { Line 5587  sub repcopy_userfile {
     open(FILE,">$file");      open(FILE,">$file");
     print FILE $info;      print FILE $info;
     close(FILE);      close(FILE);
     return OK;      return 'ok';
 }  }
   
 sub tokenwrapper {  sub tokenwrapper {
     my $uri=shift;      my $uri=shift;
     $uri=~s|^http\://([^/]+)||;      $uri=~s|^http\://([^/]+)||;
     $uri=~s|^/||;      $uri=~s|^/||;
     $ENV{'user.environment'}=~/\/([^\/]+)\.id/;      $env{'user.environment'}=~/\/([^\/]+)\.id/;
     my $token=$1;      my $token=$1;
     my (undef,$udom,$uname,$file)=split('/',$uri,4);      my (undef,$udom,$uname,$file)=split('/',$uri,4);
     if ($udom && $uname && $file) {      if ($udom && $uname && $file) {
  $file=~s|(\?\.*)*$||;   $file=~s|(\?\.*)*$||;
         &appenv("userfile.$udom/$uname/$file" => $ENV{'request.course.id'});          &appenv("userfile.$udom/$uname/$file" => $env{'request.course.id'});
         return 'http://'.$hostname{ &homeserver($uname,$udom)}.'/'.$uri.          return 'http://'.$hostname{ &homeserver($uname,$udom)}.'/'.$uri.
                (($uri=~/\?/)?'&':'?').'token='.$token.                 (($uri=~/\?/)?'&':'?').'token='.$token.
                                '&tokenissued='.$perlvar{'lonHostID'};                                 '&tokenissued='.$perlvar{'lonHostID'};
Line 5444  sub readfile { Line 5638  sub readfile {
 }  }
   
 sub filelocation {  sub filelocation {
   my ($dir,$file) = @_;      my ($dir,$file) = @_;
   my $location;      my $location;
   $file=~ s/^\s*(\S+)\s*$/$1/; ## strip off leading and trailing spaces      $file=~ s/^\s*(\S+)\s*$/$1/; ## strip off leading and trailing spaces
   if ($file=~m:^/~:) { # is a contruction space reference      if ($file=~m:^/~:) { # is a contruction space reference
     $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|editupload)/) { # is an uploaded file
       my ($udom,$uname,$filename)=          my ($udom,$uname,$filename)=
   ($file=~m|^/+uploaded/+([^/]+)/+([^/]+)/+(.*)$|);       ($file=~m -^/+(?:uploaded|editupload)/+([^/]+)/+([^/]+)/+(.*)$-);
       my $home=&homeserver($uname,$udom);          my $home=&homeserver($uname,$udom);
       my $is_me=0;          my $is_me=0;
       my @ids=&current_machine_ids();          my @ids=&current_machine_ids();
       foreach my $id (@ids) { if ($id eq $home) { $is_me=1; } }          foreach my $id (@ids) { if ($id eq $home) { $is_me=1; } }
       if ($is_me) {          if ($is_me) {
   $location=&Apache::loncommon::propath($udom,$uname).       $location=&Apache::loncommon::propath($udom,$uname).
       '/userfiles/'.$filename;         '/userfiles/'.$filename;
       } else {          } else {
   $location=$Apache::lonnet::perlvar{'lonDocRoot'}.'/userfiles/'.     $location=$Apache::lonnet::perlvar{'lonDocRoot'}.'/userfiles/'.
       $udom.'/'.$uname.'/'.$filename;         $udom.'/'.$uname.'/'.$filename;
       }          }
   } else {  
     $file=~s/^\Q$perlvar{'lonDocRoot'}\E//;  
     $file=~s:^/res/:/:;  
     if ( !( $file =~ m:^/:) ) {  
       $location = $dir. '/'.$file;  
     } else {      } else {
       $location = '/home/httpd/html/res'.$file;          $file=~s/^\Q$perlvar{'lonDocRoot'}\E//;
           $file=~s:^/res/:/:;
           if ( !( $file =~ m:^/:) ) {
               $location = $dir. '/'.$file;
           } else {
               $location = '/home/httpd/html/res'.$file;
           }
     }      }
   }      $location=~s://+:/:g; # remove duplicate /
   $location=~s://+:/:g; # remove duplicate /      while ($location=~m:/\.\./:) {$location=~ s:/[^/]+/\.\./:/:g;} #remove dir/..
   while ($location=~m:/\.\./:) {$location=~ s:/[^/]+/\.\./:/:g;} #remove dir/..      while ($location=~m:/\./:) {$location=~ s:/\./:/:g;} #remove /./
   while ($location=~m:/\./:) {$location=~ s:/\./:/:g;} #remove /./      return $location;
   return $location;  
 }  }
   
 sub hreflocation {  sub hreflocation {
Line 5534  sub declutter { Line 5728  sub declutter {
   
 sub clutter {  sub clutter {
     my $thisfn='/'.&declutter(shift);      my $thisfn='/'.&declutter(shift);
     unless ($thisfn=~/^\/(uploaded|adm|userfiles|ext|raw|priv|public)\//) {       unless ($thisfn=~/^\/(uploaded|editupload|adm|userfiles|ext|raw|priv|public)\//) { 
        $thisfn='/res'.$thisfn;          $thisfn='/res'.$thisfn; 
     }      }
     return $thisfn;      return $thisfn;
Line 5592  sub correct_line_ends { Line 5786  sub correct_line_ends {
 sub goodbye {  sub goodbye {
    &logthis("Starting Shut down");     &logthis("Starting Shut down");
 #not converted to using infrastruture and probably shouldn't be  #not converted to using infrastruture and probably shouldn't be
    &logthis(sprintf("%-20s is %s",'%badServerCache',scalar(%badServerCache)));     &logthis(sprintf("%-20s is %s",'%badServerCache',length(&freeze(\%badServerCache))));
 #converted  #converted
    &logthis(sprintf("%-20s is %s",'%metacache',scalar(%metacache)));  #   &logthis(sprintf("%-20s is %s",'%metacache',scalar(%metacache)));
    &logthis(sprintf("%-20s is %s",'%homecache',scalar(%homecache)));     &logthis(sprintf("%-20s is %s",'%homecache',length(&freeze(\%homecache))));
    &logthis(sprintf("%-20s is %s",'%titlecache',scalar(%titlecache)));  #   &logthis(sprintf("%-20s is %s",'%titlecache',length(&freeze(\%titlecache))));
    &logthis(sprintf("%-20s is %s",'%courseresdatacache',scalar(%courseresdatacache)));  #   &logthis(sprintf("%-20s is %s",'%courseresdatacache',length(&freeze(\%courseresdatacache))));
 #1.1 only  #1.1 only
    &logthis(sprintf("%-20s is %s",'%userresdatacache',scalar(%userresdatacache)));  #   &logthis(sprintf("%-20s is %s",'%userresdatacache',length(&freeze(\%userresdatacache))));
    &logthis(sprintf("%-20s is %s",'%getsectioncache',scalar(%getsectioncache)));  #   &logthis(sprintf("%-20s is %s",'%getsectioncache',length(&freeze(\%getsectioncache))));
    &logthis(sprintf("%-20s is %s",'%courseresversioncache',scalar(%courseresversioncache)));  #   &logthis(sprintf("%-20s is %s",'%courseresversioncache',length(&freeze(\%courseresversioncache))));
    &logthis(sprintf("%-20s is %s",'%resversioncache',scalar(%resversioncache)));  #   &logthis(sprintf("%-20s is %s",'%resversioncache',length(&freeze(\%resversioncache))));
      &logthis(sprintf("%-20s is %s",'%remembered',length(&freeze(\%remembered))));
      &logthis(sprintf("%-20s is %s",'kicks',$kicks));
      &logthis(sprintf("%-20s is %s",'hits',$hits));
    &flushcourselogs();     &flushcourselogs();
    &logthis("Shutting down");     &logthis("Shutting down");
    return DONE;     return DONE;
Line 5673  BEGIN { Line 5870  BEGIN {
     while (my $configline=<$config>) {      while (my $configline=<$config>) {
        next if ($configline =~ /^(\#|\s*$)/);         next if ($configline =~ /^(\#|\s*$)/);
        chomp($configline);         chomp($configline);
        my ($id,$domain,$role,$name,$ip,$domdescr)=split(/:/,$configline);         my ($id,$domain,$role,$name)=split(/:/,$configline);
        if ($id && $domain && $role && $name && $ip) {         $name=~s/\s//g;
          if ($id && $domain && $role && $name) {
  $hostname{$id}=$name;   $hostname{$id}=$name;
  $hostdom{$id}=$domain;   $hostdom{$id}=$domain;
  $hostip{$id}=$ip;  
  $iphost{$ip}=$id;  
  if ($role eq 'library') { $libserv{$id}=$name; }   if ($role eq 'library') { $libserv{$id}=$name; }
        }         }
     }      }
     close($config);      close($config);
       # FIXME: dev server don't want this, production servers _do_ want this
       #&get_iphost();
   }
   
   sub get_iphost {
       if (%iphost) { return %iphost; }
       foreach my $id (keys(%hostname)) {
    my $name=$hostname{$id};
    my $ip = gethostbyname($name);
    if (!$ip || length($ip) ne 4) {
       &logthis("Skipping host $id name $name no IP found\n");
       next;
    }
    $ip=inet_ntoa($ip);
    push(@{$iphost{$ip}},$id);
       }
       return %iphost;
 }  }
   
 # ------------------------------------------------------ Read spare server file  # ------------------------------------------------------ Read spare server file
Line 5748  BEGIN { Line 5961  BEGIN {
   
 }  }
   
 %metacache=();  $memcache=new Cache::Memcached({'servers'=>['127.0.0.1:11211']});
   
 $processmarker='_'.time.'_'.$perlvar{'lonHostID'};  $processmarker='_'.time.'_'.$perlvar{'lonHostID'};
 $dumpcount=0;  $dumpcount=0;
Line 5936  that was requested Line 6149  that was requested
 X<appenv()>  X<appenv()>
 B<appenv(%hash)>: the value of %hash is written to  B<appenv(%hash)>: the value of %hash is written to
 the user envirnoment file, and will be restored for each access this  the user envirnoment file, and will be restored for each access this
 user makes during this session, also modifies the %ENV for the current  user makes during this session, also modifies the %env for the current
 process  process
   
 =item *  =item *
 X<delenv()>  X<delenv()>
 B<delenv($regexp)>: removes all items from the session  B<delenv($regexp)>: removes all items from the session
 environment file that matches the regular expression in $regexp. The  environment file that matches the regular expression in $regexp. The
 values are also delted from the current processes %ENV.  values are also delted from the current processes %env.
   
 =back  =back
   
Line 6156  revokecustomrole($udom,$uname,$url,$role Line 6369  revokecustomrole($udom,$uname,$url,$role
   
 =item *  =item *
   
 coursedescription($courseid) : course description  coursedescription($courseid) : returns a hash of information about the
   specified course id, including all environment settings for the
   course, the description of the course will be in the hash under the
   key 'description'
   
 =item *  =item *
   
 courseresdata($coursenum,$coursedomain,@which) : request for current  resdata($name,$domain,$type,@which) : request for current parameter
 parameter setting for a specific course, @what should be a list of  setting for a specific $type, where $type is either 'course' or 'user',
 parameters to ask about. This routine caches answers for 5 minutes.  @what should be a list of parameters to ask about. This routine caches
   answers for 5 minutes.
   
 =back  =back
   
Line 6193  subscribe($fname) : subscribe to a resou Line 6410  subscribe($fname) : subscribe to a resou
   
 repcopy($filename) : subscribes to the requested file, and attempts to  repcopy($filename) : subscribes to the requested file, and attempts to
 replicate from the owning library server, Might return  replicate from the owning library server, Might return
 HTTP_SERVICE_UNAVAILABLE, HTTP_NOT_FOUND, FORBIDDEN, OK, or  'unavailable', 'not_found', 'forbidden', 'ok', or
 HTTP_BAD_REQUEST, also attempts to grab the metadata for the  'bad_request', also attempts to grab the metadata for the
 resource. Expects the local filesystem pathname  resource. Expects the local filesystem pathname
 (/home/httpd/html/res/....)  (/home/httpd/html/res/....)
   
Line 6251  symbverify($symb,$thisfn) : verifies tha Line 6468  symbverify($symb,$thisfn) : verifies tha
 a possible symb for the URL in $thisfn, and if is an encryypted  a possible symb for the URL in $thisfn, and if is an encryypted
 resource that the user accessed using /enc/ returns a 1 on success, 0  resource that the user accessed using /enc/ returns a 1 on success, 0
 on failure, user must be in a course, as it assumes the existance of  on failure, user must be in a course, as it assumes the existance of
 the course initial hash, and uses $ENV('request.course.id'}  the course initial hash, and uses $env('request.course.id'}
   
   
 =item *  =item *
Line 6282  unfakeable, receipt Line 6499  unfakeable, receipt
   
 =item *  =item *
   
 receipt() : API to ireceipt working off of ENV values; given out to users  receipt() : API to ireceipt working off of env values; given out to users
   
 =item *  =item *
   
Line 6316  forcing spreadsheet to reevaluate the re Line 6533  forcing spreadsheet to reevaluate the re
 store($storehash,$symb,$namespace,$udom,$uname) : stores hash permanently  store($storehash,$symb,$namespace,$udom,$uname) : stores hash permanently
 for this url; hashref needs to be given and should be a \%hashname; the  for this url; hashref needs to be given and should be a \%hashname; the
 remaining args aren't required and if they aren't passed or are '' they will  remaining args aren't required and if they aren't passed or are '' they will
 be derived from the ENV  be derived from the env
   
 =item *  =item *
   
Line 6536  declutter() : declutters URLs (remove do Line 6753  declutter() : declutters URLs (remove do
   
 =back  =back
   
   =head2 Usererfile file routines (/uploaded*)
   
   =over 4
   
   =item *
   
   userfileupload(): main rotine for putting a file in a user or course's
                     filespace, arguments are,
   
    formname - required - this is the name of the element in $env where the
              filename, and the contents of the file to create/modifed exist
              the filename is in $env{'form.'.$formname.'.filename'} and the
              contents of the file is located in $env{'form.'.$formname}
    coursedoc - if true, store the file in the course of the active role
                of the current user
    subdir - required - subdirectory to put the file in under ../userfiles/
            if undefined, it will be placed in "unknown"
   
    (This routine calls clean_filename() to remove any dangerous
    characters from the filename, and then calls finuserfileupload() to
    complete the transaction)
   
    returns either the url of the uploaded file (/uploaded/....) if successful
    and /adm/notfound.html if unsuccessful
   
   =item *
   
   clean_filename(): routine for cleaing a filename up for storage in
                    userfile space, argument is:
   
    filename - proposed filename
   
   returns: the new clean filename
   
   =item *
   
   finishuserfileupload(): routine that creaes and sends the file to
   userspace, probably shouldn't be called directly
   
     docuname: username or courseid of destination for the file
     docudom: domain of user/course of destination for the file
     formname: same as for userfileupload()
     fname: filename (inculding subdirectories) for the file
   
    returns either the url of the uploaded file (/uploaded/....) if successful
    and /adm/notfound.html if unsuccessful
   
   =item *
   
   renameuserfile(): renames an existing userfile to a new name
   
     Args:
      docuname: username or courseid of destination for the file
      docudom: domain of user/course of destination for the file
      old: current file name (including any subdirs under userfiles)
      new: desired file name (including any subdirs under userfiles)
   
   =item *
   
   mkdiruserfile(): creates a directory is a userfiles dir
   
     Args:
      docuname: username or courseid of destination for the file
      docudom: domain of user/course of destination for the file
      dir: dir to create (including any subdirs under userfiles)
   
   =item *
   
   removeuserfile(): removes a file that exists in userfiles
   
     Args:
      docuname: username or courseid of destination for the file
      docudom: domain of user/course of destination for the file
      fname: filname to delete (including any subdirs under userfiles)
   
   =item *
   
   removeuploadedurl(): convience function for removeuserfile()
   
     Args:
      url:  a full /uploaded/... url to delete
   
   =back
   
 =head2 HTTP Helper Routines  =head2 HTTP Helper Routines
   
 =over 4  =over 4

Removed from v.1.587  
changed lines
  Added in v.1.648


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