Diff for /loncom/lonnet/perl/lonnet.pm between versions 1.616 and 1.683.2.12

version 1.616, 2005/03/28 17:54:06 version 1.683.2.12, 2006/01/13 19:22:29
Line 37  use HTTP::Date; Line 37  use HTTP::Date;
 use vars   use vars 
 qw(%perlvar %hostname %badServerCache %iphost %spareid %hostdom   qw(%perlvar %hostname %badServerCache %iphost %spareid %hostdom 
    %libserv %pr %prp $memcache %packagetab      %libserv %pr %prp $memcache %packagetab 
    %courselogs %accesshash %userrolehash $processmarker $dumpcount      %courselogs %accesshash %userrolehash %domainrolehash $processmarker $dumpcount 
    %coursedombuf %coursenumbuf %coursehombuf %coursedescrbuf %courseinstcodebuf %courseownerbuf     %coursedombuf %coursenumbuf %coursehombuf %coursedescrbuf %courseinstcodebuf %courseownerbuf
    %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 %domain_primary
      $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 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;  use Cache::Memcached;
   use Digest::MD5;
   
 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 159  sub reply { Line 167  sub reply {
     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=~/^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>");
     }      }
     return $answer;      return $answer;
Line 183  sub reconlonc { Line 191  sub reconlonc {
             sleep 5;              sleep 5;
             if (-e "$peerfile") { return; }              if (-e "$peerfile") { return; }
             &logthis(              &logthis(
   "<font color=blue>WARNING: $peerfile still not there, giving up</font>");    "<font color=\"blue\">WARNING: $peerfile still not there, giving up</font>");
         } else {          } else {
     &logthis(      &logthis(
                "<font color=blue>WARNING:".                 "<font color=\"blue\">WARNING:".
                " lonc at pid $loncpid not responding, giving up</font>");                 " lonc at pid $loncpid not responding, giving up</font>");
         }          }
     } else {      } else {
      &logthis('<font color=blue>WARNING: lonc not running, giving up</font>');       &logthis('<font color="blue">WARNING: lonc not running, giving up</font>');
     }      }
 }  }
   
Line 199  sub reconlonc { Line 207  sub reconlonc {
 sub critical {  sub critical {
     my ($cmd,$server)=@_;      my ($cmd,$server)=@_;
     unless ($hostname{$server}) {      unless ($hostname{$server}) {
         &logthis("<font color=blue>WARNING:".          &logthis("<font color=\"blue\">WARNING:".
                " Critical message to unknown server ($server)</font>");                 " Critical message to unknown server ($server)</font>");
         return 'no_such_host';          return 'no_such_host';
     }      }
Line 233  sub critical { Line 241  sub critical {
             }              }
             chomp($wcmd);              chomp($wcmd);
             if ($wcmd eq $cmd) {              if ($wcmd eq $cmd) {
  &logthis("<font color=blue>WARNING: ".   &logthis("<font color=\"blue\">WARNING: ".
                          "Connection buffer $dfilename: $cmd</font>");                           "Connection buffer $dfilename: $cmd</font>");
                 &logperm("D:$server:$cmd");                  &logperm("D:$server:$cmd");
         return 'con_delayed';          return 'con_delayed';
             } else {              } else {
                 &logthis("<font color=red>CRITICAL:"                  &logthis("<font color=\"red\">CRITICAL:"
                         ." Critical connection failed: $server $cmd</font>");                          ." Critical connection failed: $server $cmd</font>");
                 &logperm("F:$server:$cmd");                  &logperm("F:$server:$cmd");
                 return 'con_failed';                  return 'con_failed';
Line 248  sub critical { Line 256  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 277  sub transfer_profile_to_env { Line 271  sub transfer_profile_to_env {
     my %Remove;      my %Remove;
     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],2);
  $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 297  sub appenv { Line 291  sub appenv {
     my %newenv=@_;      my %newenv=@_;
     foreach (keys %newenv) {      foreach (keys %newenv) {
  if (($newenv{$_}=~/^user\.role/) || ($newenv{$_}=~/^user\.priv/)) {   if (($newenv{$_}=~/^user\.role/) || ($newenv{$_}=~/^user\.priv/)) {
             &logthis("<font color=blue>WARNING: ".              &logthis("<font color=\"blue\">WARNING: ".
                 "Attempt to modify environment ".$_." to ".$newenv{$_}                  "Attempt to modify environment ".$_." to ".$newenv{$_}
                 .'</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)) {
          &logthis("<font color=blue>WARNING: ".           &logthis("<font color=\"blue\">WARNING: ".
                   'Could not obtain exclusive lock in appenv: '.$!);                    'Could not obtain exclusive lock in appenv: '.$!);
          close($lockfh);           close($lockfh);
          return 'error: '.$!;           return 'error: '.$!;
Line 320  sub appenv { Line 314  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 329  sub appenv { Line 323  sub appenv {
     for (my $i=0; $i<=$#oldenv; $i++) {      for (my $i=0; $i<=$#oldenv; $i++) {
         chomp($oldenv[$i]);          chomp($oldenv[$i]);
         if ($oldenv[$i] ne '') {          if ($oldenv[$i] ne '') {
     my ($name,$value)=split(/=/,$oldenv[$i]);      my ($name,$value)=split(/=/,$oldenv[$i],2);
     unless (defined($newenv{$name})) {      unless (defined($newenv{$name})) {
  $newenv{$name}=$value;   $newenv{$name}=$value;
     }      }
Line 337  sub appenv { Line 331  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 356  sub delenv { Line 350  sub delenv {
     my $delthis=shift;      my $delthis=shift;
     my %newenv=();      my %newenv=();
     if (($delthis=~/user\.role/) || ($delthis=~/user\.priv/)) {      if (($delthis=~/user\.role/) || ($delthis=~/user\.priv/)) {
         &logthis("<font color=blue>WARNING: ".          &logthis("<font color=\"blue\">WARNING: ".
                 "Attempt to delete from environment ".$delthis);                  "Attempt to delete from environment ".$delthis);
         return 'error';          return 'error';
     }      }
     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)) {
     &logthis("<font color=blue>WARNING: ".      &logthis("<font color=\"blue\">WARNING: ".
      'Could not obtain shared lock in delenv: '.$!);       'Could not obtain shared lock in delenv: '.$!);
     close($fh);      close($fh);
     return 'error: '.$!;      return 'error: '.$!;
Line 377  sub delenv { Line 371  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)) {
     &logthis("<font color=blue>WARNING: ".      &logthis("<font color=\"blue\">WARNING: ".
      'Could not obtain exclusive lock in delenv: '.$!);       'Could not obtain exclusive lock in delenv: '.$!);
     close($fh);      close($fh);
     return 'error: '.$!;      return 'error: '.$!;
  }   }
  foreach (@oldenv) {   foreach (@oldenv) {
     if ($_=~/^$delthis/) {       if ($_=~/^$delthis/) { 
                 my ($key,undef) = split('=',$_);                  my ($key,undef) = split('=',$_,2);
                 delete($ENV{$key});                  delete($env{$key});
             } else {              } else {
                 print $fh $_;                   print $fh $_; 
             }              }
Line 450  sub overloaderror { Line 444  sub overloaderror {
 # ------------------------------ Find server with least workload from spare.tab  # ------------------------------ Find server with least workload from spare.tab
   
 sub spareserver {  sub spareserver {
     my ($loadpercent,$userloadpercent) = @_;      my ($loadpercent,$userloadpercent,$want_server_name) = @_;
     my $tryserver;      my $tryserver;
     my $spareserver='';      my $spareserver='';
     if ($userloadpercent !~ /\d/) { $userloadpercent=0; }      if ($userloadpercent !~ /\d/) { $userloadpercent=0; }
     my $lowestserver=$loadpercent > $userloadpercent?      my $lowestserver=$loadpercent > $userloadpercent?
              $loadpercent :  $userloadpercent;               $loadpercent :  $userloadpercent;
     foreach $tryserver (keys %spareid) {      foreach $tryserver (keys(%spareid)) {
  my $loadans=reply('load',$tryserver);   my $loadans=&reply('load',$tryserver);
  my $userloadans=reply('userload',$tryserver);   my $userloadans=&reply('userload',$tryserver);
  if ($loadans !~ /\d/ && $userloadans !~ /\d/) {   if ($loadans !~ /\d/ && $userloadans !~ /\d/) {
     next; #didn't get a number from the server      next; #didn't get a number from the server
  }   }
Line 475  sub spareserver { Line 469  sub spareserver {
     $answer = $userloadans;      $answer = $userloadans;
  }   }
  if (($answer =~ /\d/) && ($answer<$lowestserver)) {   if (($answer =~ /\d/) && ($answer<$lowestserver)) {
     $spareserver="http://$hostname{$tryserver}";      if ($want_server_name) {
    $spareserver=$tryserver;
       } else {
    $spareserver="http://$hostname{$tryserver}";
       }
     $lowestserver=$answer;      $lowestserver=$answer;
  }   }
     }      }
Line 652  sub assign_access_key { Line 650  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 702  sub comment_access_key { Line 700  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 726  sub comment_access_key { Line 724  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 747  sub generate_access_keys { Line 745  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 764  sub generate_access_keys { Line 762  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\#/);
 }  }
   
 # ------------------------------------- Find the section of student in a course  # ------------------------------------- Find the section of student in a course
   sub devalidate_getsection_cache {
       my ($udom,$unam,$courseid)=@_;
       $courseid=~s/\_/\//g;
       $courseid=~s/^(\w)/\/$1/;
       my $hashid="$udom:$unam:$courseid";
       &devalidate_cache_new('getsection',$hashid);
   }
   
 sub getsection {  sub getsection {
     my ($udom,$unam,$courseid)=@_;      my ($udom,$unam,$courseid)=@_;
Line 835  sub getsection { Line 840  sub getsection {
 }  }
   
 sub save_cache {  sub save_cache {
       my ($r)=@_;
       if (! $r->is_initial_req()) { return DECLINED; }
     &purge_remembered();      &purge_remembered();
       undef(%env);
       return OK;
 }  }
   
 my $to_remember=-1;  my $to_remember=-1;
Line 882  sub do_cache_new { Line 891  sub do_cache_new {
     if (!defined($setvalue)) {      if (!defined($setvalue)) {
  $setvalue='__undef__';   $setvalue='__undef__';
     }      }
       if (!defined($time) ) {
    $time=600;
       }
     if ($debug) { &Apache::lonnet::logthis("Setting $id to $value"); }      if ($debug) { &Apache::lonnet::logthis("Setting $id to $value"); }
     $memcache->set($id,$setvalue,$time);      $memcache->set($id,$setvalue,$time);
     # need to make a copy of $value      # need to make a copy of $value
Line 931  sub userenvironment { Line 943  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 1040  sub repcopy { Line 1065  sub repcopy {
            if ($response->is_error()) {             if ($response->is_error()) {
        unlink($transname);         unlink($transname);
                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 'unavailable';                 return 'unavailable';
            } else {             } else {
Line 1050  sub repcopy { Line 1075  sub repcopy {
                   if ($mresponse->is_error()) {                    if ($mresponse->is_error()) {
       unlink($filename.'.meta');        unlink($filename.'.meta');
                       &logthis(                        &logthis(
                      "<font color=yellow>INFO: No metadata: $filename</font>");                       "<font color=\"yellow\">INFO: No metadata: $filename</font>");
                   }                    }
        }         }
                rename($transname,$filename);                 rename($transname,$filename);
Line 1119  sub allowuploaded { Line 1144  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 1139  sub allowuploaded { Line 1167  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 $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 1175  sub process_coursefile { Line 1194  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;
 }  }
   
   sub build_filepath {
       my ($fpath) = @_;
       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)=@_;
 # Replace Windows backslashes by forward slashes  # Replace Windows backslashes by forward slashes
Line 1221  sub clean_filename { Line 1285  sub clean_filename {
   
   
 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 1240  sub userfileupload { Line 1304  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 1288  sub finishuserfileupload { Line 1352  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
 #  #
       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 1305  sub finishuserfileupload { Line 1378  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);
Line 1362  sub flushcourselogs { Line 1543  sub flushcourselogs {
         } else {          } else {
             &logthis('Failed to flush log buffer for '.$crsid);              &logthis('Failed to flush log buffer for '.$crsid);
             if (length($courselogs{$crsid})>40000) {              if (length($courselogs{$crsid})>40000) {
                &logthis("<font color=blue>WARNING: Buffer for ".$crsid.                 &logthis("<font color=\"blue\">WARNING: Buffer for ".$crsid.
                         " exceeded maximum size, deleting.</font>");                          " exceeded maximum size, deleting.</font>");
                delete $courselogs{$crsid};                 delete $courselogs{$crsid};
             }              }
Line 1394  sub flushcourselogs { Line 1575  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 1433  sub flushcourselogs { Line 1614  sub flushcourselogs {
     delete $userrolehash{$entry};      delete $userrolehash{$entry};
         }          }
     }      }
   #
   # Reverse lookup of domain roles (dc, ad, li, sc, au)
   #
       my %domrolebuffer = ();
       foreach my $entry (keys %domainrolehash) {
           my ($role,$uname,$udom,$runame,$rudom,$rsec)=split/:/,$entry;
           if ($domrolebuffer{$rudom}) {
               $domrolebuffer{$rudom}.='&'.&escape($entry).
                         '='.&escape($domainrolehash{$entry});
           } else {
               $domrolebuffer{$rudom}.=&escape($entry).
                         '='.&escape($domainrolehash{$entry});
           }
           delete $domainrolehash{$entry};
       }
       foreach my $dom (keys(%domrolebuffer)) {
           foreach my $tryserver (keys %libserv) {
               if ($hostdom{$tryserver} eq $dom) {
                   unless (&reply('domroleput:'.$dom.':'.
                     $domrolebuffer{$dom},$tryserver) eq 'ok') {
                       &logthis('Put of domain roles failed for '.$dom.' and  '.$tryserver);
                   }
               }
           }
       }
     $dumpcount++;      $dumpcount++;
 }  }
   
 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|task|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 1492  sub courseacclog { Line 1698  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 1508  sub linklog { Line 1714  sub linklog {
       
 sub userrolelog {  sub userrolelog {
     my ($trole,$username,$domain,$area,$tstart,$tend)=@_;      my ($trole,$username,$domain,$area,$tstart,$tend)=@_;
     if (($trole=~/^ca/) || ($trole=~/^in/) ||       if (($trole=~/^ca/) || ($trole=~/^aa/) ||
         ($trole=~/^cc/) || ($trole=~/^ep/) ||          ($trole=~/^in/) || ($trole=~/^cc/) ||
         ($trole=~/^cr/) || ($trole=~/^ta/)) {          ($trole=~/^ep/) || ($trole=~/^cr/) ||
           ($trole=~/^ta/)) {
        my (undef,$rudom,$runame,$rsec)=split(/\//,$area);         my (undef,$rudom,$runame,$rsec)=split(/\//,$area);
        $userrolehash         $userrolehash
          {$trole.':'.$username.':'.$domain.':'.$runame.':'.$rudom.':'.$rsec}           {$trole.':'.$username.':'.$domain.':'.$runame.':'.$rudom.':'.$rsec}
                     =$tend.':'.$tstart;                      =$tend.':'.$tstart;
    }      }
       if (($trole=~/^dc/) || ($trole=~/^ad/) ||
           ($trole=~/^li/) || ($trole=~/^li/) ||
           ($trole=~/^au/) || ($trole=~/^dg/) ||
           ($trole=~/^sc/)) {
          my (undef,$rudom,$runame,$rsec)=split(/\//,$area);
          $domainrolehash
            {$trole.':'.$username.':'.$domain.':'.$runame.':'.$rudom.':'.$rsec}
                       = $tend.':'.$tstart;
       }
 }  }
   
 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 1539  sub get_course_adv_roles { Line 1755  sub get_course_adv_roles {
  if ($username eq '' || $domain eq '') { next; }   if ($username eq '' || $domain eq '') { next; }
  if ((&privileged($username,$domain)) &&    if ((&privileged($username,$domain)) && 
     (!$nothide{$username.':'.$domain})) { next; }      (!$nothide{$username.':'.$domain})) { next; }
    if ($role eq 'cr') { next; }
         my $key=&plaintext($role);          my $key=&plaintext($role);
    if ($role =~ /^cr/) {
       $key=(split('/',$role))[3];
    }
         if ($section) { $key.=' (Sec/Grp '.$section.')'; }          if ($section) { $key.=' (Sec/Grp '.$section.')'; }
         if ($returnhash{$key}) {          if ($returnhash{$key}) {
     $returnhash{$key}.=','.$username.':'.$domain;      $returnhash{$key}.=','.$username.':'.$domain;
Line 1552  sub get_course_adv_roles { Line 1772  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 1608  sub courseidput { Line 1828  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 1617  sub courseiddump { Line 1837  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 1630  sub courseiddump { Line 1850  sub courseiddump {
     return %returnhash;      return %returnhash;
 }  }
   
 #  # ---------------------------------------------------------- DC e-mail
   
   sub dcmailput {
       my ($domain,$msgid,$message,$server)=@_;
       my $status = &Apache::lonnet::critical(
          'dcmailput:'.$domain.':'.&Apache::lonnet::escape($msgid).'='.
          &Apache::lonnet::escape($message),$server);
       return $status;
   }
   
   sub dcmaildump {
       my ($dom,$startdate,$enddate,$senders) = @_;
       my %returnhash=();
       if (exists($domain_primary{$dom})) {
           my $cmd='dcmaildump:'.$dom.':'.&escape($startdate).':'.
                                                            &escape($enddate).':';
    my @esc_senders=map { &escape($_)} @$senders;
    $cmd.=&escape(join('&',@esc_senders));
    foreach (split(/\&/,&reply($cmd,$domain_primary{$dom}))) {
               my ($key,$value) = split(/\=/,$_);
               if (($key) && ($value)) {
                   $returnhash{&unescape($key)} = &unescape($value);
               }
           }
       }
       return %returnhash;
   }
   # ---------------------------------------------------------- Domain roles
   
   sub get_domain_roles {
       my ($dom,$roles,$startdate,$enddate)=@_;
       if (undef($startdate) || $startdate eq '') {
           $startdate = '.';
       }
       if (undef($enddate) || $enddate eq '') {
           $enddate = '.';
       }
       my $rolelist = join(':',@{$roles});
       my %personnel = ();
       foreach my $tryserver (keys(%libserv)) {
           if ($hostdom{$tryserver} eq $dom) {
               %{$personnel{$tryserver}}=();
               foreach (
                   split(/\&/,&reply('domrolesdump:'.$dom.':'.
                      &escape($startdate).':'.&escape($enddate).':'.
                      &escape($rolelist), $tryserver))) {
                   my($key,$value) = split(/\=/,$_);
                   if (($key) && ($value)) {
                       $personnel{$tryserver}{&unescape($key)} = &unescape($value);
                   }
               }
           }
       }
       return %personnel;
   }
   
 # ----------------------------------------------------------- Check out an item  # ----------------------------------------------------------- Check out an item
   
 sub get_first_access {  sub get_first_access {
Line 1676  sub checkout { Line 1951  sub checkout {
  $now.'&'.$ENV{'REMOTE_ADDR'});   $now.'&'.$ENV{'REMOTE_ADDR'});
     my $token=&reply('tmpput:'.$infostr,$lonhost);      my $token=&reply('tmpput:'.$infostr,$lonhost);
     if ($token=~/^error\:/) {       if ($token=~/^error\:/) { 
         &logthis("<font color=blue>WARNING: ".          &logthis("<font color=\"blue\">WARNING: ".
                 "Checkout tmpput failed ".$tudom.' - '.$tuname.' - '.$symb.                  "Checkout tmpput failed ".$tudom.' - '.$tuname.' - '.$symb.
                  "</font>");                   "</font>");
         return '';           return ''; 
Line 1692  sub checkout { Line 1967  sub checkout {
     unless (&cstore(\%infohash,$symb,$tcrsid,$tudom,$tuname) eq 'ok') {      unless (&cstore(\%infohash,$symb,$tcrsid,$tudom,$tuname) eq 'ok') {
        return '';         return '';
     } else {      } else {
         &logthis("<font color=blue>WARNING: ".          &logthis("<font color=\"blue\">WARNING: ".
                 "Checkout cstore failed ".$tudom.' - '.$tuname.' - '.$symb.                  "Checkout cstore failed ".$tudom.' - '.$tuname.' - '.$symb.
                  "</font>");                   "</font>");
     }          }    
Line 1702  sub checkout { Line 1977  sub checkout {
                                                  $token)) ne 'ok') {                                                   $token)) ne 'ok') {
  return '';   return '';
     } else {      } else {
         &logthis("<font color=blue>WARNING: ".          &logthis("<font color=\"blue\">WARNING: ".
                 "Checkout log failed ".$tudom.' - '.$tuname.' - '.$symb.                  "Checkout log failed ".$tudom.' - '.$tuname.' - '.$symb.
                  "</font>");                   "</font>");
     }      }
Line 1728  sub checkin { Line 2003  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 1752  sub checkin { Line 2027  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 1769  sub expirespread { Line 2044  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 1780  sub devalidate { Line 2055  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 1991  sub tmpreset { Line 2266  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;
   
   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') {    if ($domain eq 'public' && $stuname eq 'public') {
       $stuname=$ENV{'REMOTE_ADDR'};        $stuname=$ENV{'REMOTE_ADDR'};
   }    }
Line 2022  sub tmpstore { Line 2297  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;
   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') {    if ($domain eq 'public' && $stuname eq 'public') {
       $stuname=$ENV{'REMOTE_ADDR'};        $stuname=$ENV{'REMOTE_ADDR'};
   }    }
Line 2074  sub tmprestore { Line 2349  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'}; }
   
   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') {    if ($domain eq 'public' && $stuname eq 'public') {
       $stuname=$ENV{'REMOTE_ADDR'};        $stuname=$ENV{'REMOTE_ADDR'};
   }    }
Line 2126  sub store { Line 2401  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'};
Line 2162  sub cstore { Line 2437  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'};
Line 2202  sub restore { Line 2477  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=();
Line 2250  sub coursedescription { Line 2525  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 2297  sub rolesinit { Line 2572  sub rolesinit {
     my $rolesdump=reply("dump:$domain:$username:roles",$authhost);      my $rolesdump=reply("dump:$domain:$username:roles",$authhost);
     if (($rolesdump eq 'con_lost') || ($rolesdump eq '')) { return ''; }      if (($rolesdump eq 'con_lost') || ($rolesdump eq '')) { return ''; }
     my %allroles=();      my %allroles=();
       my %allgroups=();   
     my $now=time;      my $now=time;
     my $userroles="user.login.time=$now\n";      my $userroles="user.login.time=$now\n";
       my $group_privs;
   
     if ($rolesdump ne '') {      if ($rolesdump ne '') {
         foreach (split(/&/,$rolesdump)) {          foreach (split(/&/,$rolesdump)) {
   if ($_!~/^rolesdef_/) {    if ($_!~/^rolesdef_/) {
             my ($area,$role)=split(/=/,$_);              my ($area,$role)=split(/=/,$_);
     $area=~s/\_\w\w$//;      $area=~s/\_\w\w$//;
                   my ($trole,$tend,$tstart,$group_privs);
             my ($trole,$tend,$tstart);  
     if ($role=~/^cr/) {       if ($role=~/^cr/) { 
  ($trole,my $trest)=($role=~m|^(cr/\w+/\w+/[a-zA-Z0-9]+)_(.*)$|);   if ($role=~m|^(cr/\w+/\w+/[a-zA-Z0-9]+)_(.*)$|) {
  ($tend,$tstart)=split('_',$trest);      ($trole,my $trest)=($role=~m|^(cr/\w+/\w+/[a-zA-Z0-9]+)_(.*)$|);
       ($tend,$tstart)=split('_',$trest);
    } else {
       $trole=$role;
    }
               } elsif ($role =~ m|^gr/|) {
                   ($trole,$tend,$tstart) = split(/_/,$role);
                   ($trole,$group_privs) = split(/\//,$trole);
                   $group_privs = &unescape($group_privs);
     } else {      } else {
  ($trole,$tend,$tstart)=split(/_/,$role);   ($trole,$tend,$tstart)=split(/_/,$role);
     }      }
Line 2321  sub rolesinit { Line 2605  sub rolesinit {
  my ($tdummy,$tdomain,$trest)=split(/\//,$area);   my ($tdummy,$tdomain,$trest)=split(/\//,$area);
  if ($trole =~ /^cr\//) {   if ($trole =~ /^cr\//) {
                     &custom_roleprivs(\%allroles,$trole,$tdomain,$trest,$spec,$area);                      &custom_roleprivs(\%allroles,$trole,$tdomain,$trest,$spec,$area);
                   } elsif ($trole eq 'gr') {
                       &group_roleprivs(\%allgroups,$area,$group_privs,$tend,$tstart);
  } else {   } else {
                     &standard_roleprivs(\%allroles,$trole,$tdomain,$spec,$trest,$area);                      &standard_roleprivs(\%allroles,$trole,$tdomain,$spec,$trest,$area);
  }   }
             }              }
           }             }
         }          }
         my ($author,$adv) = &set_userprivs(\$userroles,\%allroles);          my ($author,$adv) = &set_userprivs(\$userroles,\%allroles,\%allgroups);
         $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 2369  sub custom_roleprivs { Line 2655  sub custom_roleprivs {
     }      }
 }  }
   
   sub group_roleprivs {
       my ($allgroups,$area,$group_privs,$tend,$tstart) = @_;
       my $access = 1;
       my $now = time;
       if (($tend!=0) && ($tend<$now)) { $access = 0; }
       if (($tstart!=0) && ($tstart>$now)) { $access=0; }
       if ($access) {
           my ($course,$group) = ($area =~ m|(/\w+/\w+)/([^/]+)$|);
           $$allgroups{$course}{$group} .=':'.$group_privs;
       }
   }
   
 sub standard_roleprivs {  sub standard_roleprivs {
     my ($allroles,$trole,$tdomain,$spec,$trest,$area) = @_;      my ($allroles,$trole,$tdomain,$spec,$trest,$area) = @_;
Line 2389  sub standard_roleprivs { Line 2686  sub standard_roleprivs {
 }  }
   
 sub set_userprivs {  sub set_userprivs {
     my ($userroles,$allroles) = @_;       my ($userroles,$allroles,$allgroups) = @_; 
     my $author=0;      my $author=0;
     my $adv=0;      my $adv=0;
       my %grouproles = ();
       if (keys(%{$allgroups}) > 0) {
           foreach my $role (keys %{$allroles}) {
               my ($trole,$area,$sec,$extendedarea);
               if ($role =~ m|^(\w+)\.(/\w+/\w+)(/?\w*)|) {
                   $trole = $1;
                   $area = $2;
                   $sec = $3;
                   $extendedarea = $area.$sec;
                   if (exists($$allgroups{$area})) {
                       foreach my $group (keys(%{$$allgroups{$area}})) {
                           my $spec = $trole.'.'.$extendedarea;
                           $grouproles{$spec.'.'.$area.'/'.$group} = 
                                                   $$allgroups{$area}{$group};
                       }
                   }
               }
           }
       }
       foreach (keys(%grouproles)) {
           $$allroles{$_} = $grouproles{$_};
       }
     foreach (keys %{$allroles}) {      foreach (keys %{$allroles}) {
         my %thesepriv=();          my %thesepriv=();
         if (($_=~/^au/) || ($_=~/^ca/)) { $author=1; }          if (($_=~/^au/) || ($_=~/^ca/)) { $author=1; }
Line 2422  sub get { Line 2741  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 2449  sub del { Line 2768  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 2460  sub del { Line 2779  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 2482  sub dump { Line 2801  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 2496  sub getkeys { Line 2815  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 2552  sub convert_dump_to_currentdump{ Line 2871  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 2573  sub inc { Line 2898  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 2591  sub put { Line 2920  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 2619  sub putstore { Line 2963  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 2639  sub eget { Line 2983  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 2653  sub eget { Line 2997  sub eget {
    return %returnhash;     return %returnhash;
 }  }
   
   # ------------------------------------------------------------ tmpput interface
   sub tmpput {
       my ($storehash,$server)=@_;
       my $items='';
       foreach (keys(%$storehash)) {
    $items.=&escape($_).'='.&freeze_escape($$storehash{$_}).'&';
       }
       $items=~s/\&$//;
       return &reply("tmpput:$items",$server);
   }
   
   # ------------------------------------------------------------ tmpget interface
   sub tmpget {
       my ($token,$server)=@_;
       if (!defined($server)) { $server = $perlvar{'lonHostID'}; }
       my $rep=&reply("tmpget:$token",$server);
       my %returnhash;
       foreach my $item (split(/\&/,$rep)) {
    my ($key,$value)=split(/=/,$item);
    $returnhash{&unescape($key)}=&thaw_unescape($value);
       }
       return %returnhash;
   }
   
   # ------------------------------------------------------------ tmpget interface
   sub tmpdel {
       my ($token,$server)=@_;
       if (!defined($server)) { $server = $perlvar{'lonHostID'}; }
       return &reply("tmpdel:$token",$server);
   }
   
 # ---------------------------------------------- Custom access rule evaluation  # ---------------------------------------------- Custom access rule evaluation
   
 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 2695  sub allowed { Line 3070  sub allowed {
     my $orguri=$uri;      my $orguri=$uri;
     $uri=&declutter($uri);      $uri=&declutter($uri);
           
           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 2706  sub allowed { Line 3079  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 (($space=~/^(uploaded|ediupload)$/) && ($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 2715  sub allowed { Line 3088  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 2740  sub allowed { Line 3113  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 2753  sub allowed { Line 3126  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 2769  sub allowed { Line 3142  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\&([^\:]*)/) {
          $thisallowed.=$1;
       }
   
   # Group: uri itself is a group
       my $groupuri=$uri;
       $groupuri=~s/^([^\/])/\/$1/;
       if ($env{'user.priv.'.$env{'request.role'}.'.'.$groupuri}
        =~/\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, default permissions don't matter
 # not allowing 'edit' access (editupload) to uploaded course docs  # 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};   $thisallowed='';
  if ($refuri) {          my ($match)=&is_on_map($uri);
     if ($refuri =~ m|^/adm/|) {          if ($match) {
  $thisallowed='F';              if ($env{'user.priv.'.$env{'request.role'}.'./'}
     }                    =~/\Q$priv\E\&([^\:]*)/) {
  }                  $thisallowed.=$1;
               }
           } else {
               my $refuri=$env{'httpref.'.$orguri};
               if ($refuri) {
                   if ($refuri =~ m|^/adm/|) {
                       $thisallowed='F';
                   } else {
                       $refuri=&declutter($refuri);
                       my ($match) = &is_on_map($refuri);
                       if ($match) {
                           $thisallowed='F';
                       }
                   }
               }
           }
     }      }
   
 # Full access at system, domain or course-wide level? Exit.  # Full access at system, domain or course-wide level? Exit.
Line 2793  sub allowed { Line 3189  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 2802  sub allowed { Line 3207  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 2821  sub allowed { Line 3226  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 2841  sub allowed { Line 3246  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 2881  sub allowed { Line 3286  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 2925  sub allowed { Line 3330  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 2937  sub allowed { Line 3342  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'},     if ($priv ne 'pch') { 
                 'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode.' in '.         &logthis($env{'user.domain'}.':'.$env{'user.name'}.':'.$env{'user.home'}.':'.
                 $ENV{'request.course.id'});   'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode.' in '.
    $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'},     if ($priv ne 'pch') { 
                 'Denied by user: '.$priv.' for '.$uri.' as '.$unamedom.' in '.         &logthis($env{'user.domain'}.':'.$env{'user.name'}.':'.$env{'user.home'}.
                 $ENV{'request.course.id'});   'Denied by user: '.$priv.' for '.$uri.' as '.$unamedom.' in '.
    $env{'request.course.id'});
      }
            return '';             return '';
        }         }
    }     }
Line 2959  sub allowed { Line 3368  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'},     if ($priv ne 'pch') { 
                     'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode);         &logthis($env{'user.domain'}.':'.$env{'user.name'}.':'.$env{'user.home'}.':'.
           return '';   'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode);
      }
      return '';
        }         }
    }     }
   
 # 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 2989  sub allowed { Line 3400  sub allowed {
 # --------------------------------------------------- Is a resource on the map?  # --------------------------------------------------- Is a resource on the map?
   
 sub is_on_map {  sub is_on_map {
     my $uri=&declutter(shift);      my $uri=&deversion(&declutter(shift));
     $uri=~s/\.\d+\.(\w+)$/\.$1/;  
     my @uriparts=split(/\//,$uri);      my @uriparts=split(/\//,$uri);
     my $filename=$uriparts[$#uriparts];      my $filename=$uriparts[$#uriparts];
     my $pathname=$uri;      my $pathname=$uri;
     $pathname=~s|/\Q$filename\E$||;      $pathname=~s|/\Q$filename\E$||;
     $pathname=~s/^adm\/wrapper\///;          $pathname=~s/^adm\/wrapper\///;
       $pathname=~s/^adm\/coursedocs\/showdoc\///;
     #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 3016  sub get_symb_from_alias { Line 3427  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 3061  sub definerole { Line 3472  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 3127  sub fetch_enrollment_query { Line 3538  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 3139  sub fetch_enrollment_query { Line 3550  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 3204  sub courselog_query { Line 3615  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 3279  sub auto_instcode_format { Line 3690  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 3301  sub auto_instcode_format { Line 3712  sub auto_instcode_format {
     return $response;      return $response;
 }  }
   
   # ------------------------------------------------------- Course Group routines
   
   sub get_coursegroups {
       my ($cdom,$cnum,$group) = @_;
       return(&dump('coursegroups',$cdom,$cnum,$group));
   }
   
   sub modify_coursegroup {
       my ($cdom,$cnum,$groupsettings) = @_;
       return(&put('coursegroups',$groupsettings,$cdom,$cnum));
   }
   
   sub modify_group_roles {
       my ($cdom,$cnum,$group_id,$user,$end,$start,$userprivs) = @_;
       my $url = '/'.$cdom.'/'.$cnum.'/'.$group_id;
       my $role = 'gr/'.&escape($userprivs);
       my ($uname,$udom) = split(/:/,$user);
       my $result = &assignrole($udom,$uname,$url,$role,$end,$start);
       return $result;
   }
   
   sub modify_coursegroup_membership {
       my ($cdom,$cnum,$membership) = @_;
       my $result = &put('groupmembership',$membership,$cdom,$cnum);
       return $result;
   }
   
   sub get_active_groups {
       my ($udom,$uname,$cdom,$cnum) = @_;
       my $now = time;
       my %groups = ();
       foreach my $key (keys(%env)) {
           if ($key =~ m-user\.role\.gr\./([^/]+)/([^/]+)/(\w+)$-) {
               my ($start,$end) = split(/\./,$env{$key});
               if (($end!=0) && ($end<$now)) { next; }
               if (($start!=0) && ($start>$now)) { next; }
               if ($1 eq $cdom && $2 eq $cnum) {
                   $groups{$3} = $env{$key} ;
               }
           }
       }
       return %groups;
   }
   
   sub get_group_membership {
       my ($cdom,$cnum,$group) = @_;
       return(&dump('groupmembership',$cdom,$cnum,$group));
   }
   
   sub get_users_groups {
       my ($udom,$uname,$courseid) = @_;
       my $cachetime=1800;
       $courseid=~s/\_/\//g;
       $courseid=~s/^(\w)/\/$1/;
   
       my $hashid="$udom:$uname:$courseid";
       my ($result,$cached)=&is_cached_new('getgroups',$hashid);
       if (defined($cached)) { return $result; }
   
       my %roleshash = &dump('roles',$udom,$uname,$courseid);
       my ($tmp) = keys(%roleshash);
       if ($tmp=~/^error:/) {
           &logthis('Error retrieving roles: '.$tmp.' for '.$uname.':'.$udom);
           return '';
       } else {
           my $grouplist;
           foreach my $key (keys %roleshash) {
               if ($key =~ /^\Q$courseid\E\/(\w+)\_gr$/) {
                   unless ($roleshash{$key} =~ /_1_1$/) {   # deleted membership
                       $grouplist .= $1.':';
                   }
               }
           }
           $grouplist =~ s/:$//;
           return &do_cache_new('getgroups',$hashid,$grouplist,$cachetime);
       }
   }
   
   sub devalidate_getgroups_cache {
       my ($udom,$uname,$cdom,$cnum)=@_;
       my $courseid = $cdom.'_'.$cnum;
       $courseid=~s/\_/\//g;
       $courseid=~s/^(\w)/\/$1/;
       my $hashid="$udom:$uname:$courseid";
       &devalidate_cache_new('getgroups',$hashid);
   }
   
 # ------------------------------------------------------------------ Plain Text  # ------------------------------------------------------------------ Plain Text
   
 sub plaintext {  sub plaintext {
     my $short=shift;      my $short=shift;
     return &mt($prp{$short});      return &Apache::lonlocal::mt($prp{$short});
 }  }
   
 # ----------------------------------------------------------------- Assign Role  # ----------------------------------------------------------------- Assign Role
Line 3319  sub assignrole { Line 3817  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';
       } elsif ($role =~ /^gr\//) {
           my $cwogrp=$url;
           $cwogrp=~s/^\/(\w+)\/(\w+)\/.*/$1\/$2/;
           unless (&allowed('mdg',$cwogrp)) {
               &logthis('Refused group assignrole: '.
                 $udom.' '.$uname.' '.$url.' '.$role.' '.$end.' '.$start.' by '.
                       $env{'user.name'}.' at '.$env{'user.domain'});
               return 'refused';
           }
           $mrole='gr';
     } else {      } else {
         my $cwosec=$url;          my $cwosec=$url;
         $cwosec=~s/^\/(\w+)\/(\w+)\/.*/$1\/$2/;          $cwosec=~s/^\/(\w+)\/(\w+)\/.*/$1\/$2/;
         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 3348  sub assignrole { Line 3856  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 3360  sub assignrole { Line 3868  sub assignrole {
     my $answer=&reply($command,&homeserver($uname,$udom));      my $answer=&reply($command,&homeserver($uname,$udom));
 # log new user role if status is ok  # log new user role if status is ok
     if ($answer eq 'ok') {      if ($answer eq 'ok') {
  &userrolelog($mrole,$uname,$udom,$url,$start,$end);   &userrolelog($role,$uname,$udom,$url,$start,$end);
     }      }
     return $answer;      return $answer;
 }  }
Line 3373  sub modifyuserauth { Line 3881  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 3405  sub modifyuser { Line 3913  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 3414  sub modifyuser { Line 3922  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 3483  sub modifyuser { Line 3991  sub modifyuser {
     }      }
     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; }
       &devalidate_cache_new('namescache',$uname.':'.$udom);
     &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 3496  sub modifystudent { Line 4005  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 3517  sub modify_student_enrollment { Line 4026  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 3563  sub modify_student_enrollment { Line 4072  sub modify_student_enrollment {
    $cdom,$cnum);     $cdom,$cnum);
     unless (($reply eq 'ok') || ($reply eq 'delayed')) {      unless (($reply eq 'ok') || ($reply eq 'delayed')) {
  return 'error: '.$reply;   return 'error: '.$reply;
       } else {
    &devalidate_getsection_cache($udom,$uname,$cid);
     }      }
     # Add student role to user      # Add student role to user
     my $uurl='/'.$cid;      my $uurl='/'.$cid;
Line 3621  sub createcourse { Line 4132  sub createcourse {
         return 'refused';          return 'refused';
     }      }
 # ------------------------------------------------------------------- Create ID  # ------------------------------------------------------------------- Create ID
    my $uname=substr($$.time,0,5).unpack("H8",pack("I32",time)).     my $uname=int(1+rand(9)).
          ('a'..'z','A'..'Z','0'..'9')[int(rand(62))].
          substr($$.time,0,5).unpack("H8",pack("I32",time)).
        unpack("H2",pack("I32",int(rand(255)))).$perlvar{'lonHostID'};         unpack("H2",pack("I32",int(rand(255)))).$perlvar{'lonHostID'};
 # ----------------------------------------------- Make sure that does not exist  # ----------------------------------------------- Make sure that does not exist
    my $uhome=&homeserver($uname,$udom,'true');     my $uhome=&homeserver($uname,$udom,'true');
Line 3634  sub createcourse { Line 4147  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 3657  sub createcourse { Line 4170  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 3667  sub createcourse { Line 4180  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 3716  sub is_locked { Line 4229  sub is_locked {
     my $is_locked;      my $is_locked;
     push @check, $file_name;      push @check, $file_name;
     my %locked = &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);      my ($tmp)=keys(%locked);
     if ($tmp=~/^error:/) { undef(%locked); }      if ($tmp=~/^error:/) { undef(%locked); }
   
Line 3734  sub mark_as_readonly { Line 4247  sub mark_as_readonly {
     my %current_permissions = &dump('file_permissions',$domain,$user);      my %current_permissions = &dump('file_permissions',$domain,$user);
     my ($tmp)=keys(%current_permissions);      my ($tmp)=keys(%current_permissions);
     if ($tmp=~/^error:/) { undef(%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);
     }      }
Line 3750  sub save_selected_files { Line 4262  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 3813  sub files_not_in_path { Line 4325  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 = &dump('file_permissions',$domain,$user);      my %current_permissions = &dump('file_permissions',$domain,$user);
     my ($tmp)=keys(%current_permissions);      my ($tmp)=keys(%current_permissions);
     if ($tmp=~/^error:/) { undef(%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 3858  sub get_marked_as_readonly_hash { Line 4374  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 $symb_crs = $what;
       if (ref($what)) { $symb_crs=join('',@$what); }
     my %current_permissions = &dump('file_permissions',$domain,$user);      my %current_permissions = &dump('file_permissions',$domain,$user);
     my ($tmp)=keys(%current_permissions);      my ($tmp)=keys(%current_permissions);
     if ($tmp=~/^error:/) { undef(%current_permissions); }      if ($tmp=~/^error:/) { undef(%current_permissions); }
   
     my @readonly_files = &get_marked_as_readonly($domain,$user,$what);      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};   if (defined($file_name) && ($file_name ne $file)) { next; }
    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;
                     push(@new_locks, $what);                  if (ref($locker)) { $compare=join('',@{$locker}) };
                   if ($compare ne $symb_crs) {
                       push(@new_locks, $locker);
                 }                  }
             }              }
             if (@new_locks > 0) {              if (scalar(@new_locks) > 0) {
                 $current_permissions{$file} = \@new_locks;                  $current_permissions{$file} = \@new_locks;
             } else {              } else {
                 push(@del_keys, $file);                  push(@del_keys, $file);
                 &del('file_permissions',\@del_keys, $domain, $user);                  &del('file_permissions',\@del_keys, $domain, $user);
                 delete $current_permissions{$file};                  delete($current_permissions{$file});
             }              }
         }          }
     }      }
Line 4015  sub GetFileTimestamp { Line 4535  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 4030  sub condval { Line 4550  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 4076  sub devalidatecourseresdata { Line 4596  sub devalidatecourseresdata {
   
 # --------------------------------------------------- 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_new('courseres',$hashid);      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) {
Line 4094  sub courseresdata { Line 4615  sub courseresdata {
     &do_cache_new('courseres',$hashid,$result,600);      &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 4113  sub clear_EXT_cache_status { Line 4682  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 4124  sub EXT_cache_status { Line 4693  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 4143  sub EXT { Line 4712  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 4160  sub EXT { Line 4729  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))
    &&
    ($symbparm eq &symbread()) ) {
  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 4177  sub EXT { Line 4749  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 4191  sub EXT { Line 4763  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 4219  sub EXT { Line 4791  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') {
     if ($qualifier eq 'textremote') {      if ($qualifier eq 'textremote') {
  if (&mt('textual_remote_display') eq 'on') {   if (&Apache::lonlocal::mt('textual_remote_display') eq 'on') {
     return 1;      return 1;
  } else {   } else {
     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);   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 4258  sub EXT { Line 4830  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 4278  sub EXT { Line 4850  sub EXT {
     $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 $userreply=&resdata($uname,$udom,'user',
  my $hashid="$udom:$uname";         ($courselevelr,$courselevelm,
  my ($result,$cached)=&is_cached_new('userres',$hashid);   $courselevel));
  if (!defined($cached)) {  
     my %resourcedata=&dump('resourcedata',$udom,$uname);      if (defined($userreply)) { return $userreply; }
     $result=\%resourcedata;  
     &do_cache_new('userres',$hashid,$result);  
  }  
  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 some of course  # ------------------------------------------------ second, check some of course
   
     my $coursereply=&courseresdata($ENV{'course.'.$courseid.'.num'},      my $coursereply=&resdata($env{'course.'.$courseid.'.num'},
    $ENV{'course.'.$courseid.'.domain'},       $env{'course.'.$courseid.'.domain'},
    ($seclevelr,$seclevelm,$seclevel,       'course',
     $courselevelr));       ($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);
Line 4337  sub EXT { Line 4885  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; }
Line 4346  sub EXT { Line 4894  sub EXT {
   
 # ---------------------------------------------- fourth, look in rest pf course  # ---------------------------------------------- fourth, look in rest pf course
  if ($symbparm && defined($courseid) &&    if ($symbparm && defined($courseid) && 
     $courseid eq $ENV{'request.course.id'}) {      $courseid eq $env{'request.course.id'}) {
     my $coursereply=&courseresdata($ENV{'course.'.$courseid.'.num'},      my $coursereply=&resdata($env{'course.'.$courseid.'.num'},
    $ENV{'course.'.$courseid.'.domain'},       $env{'course.'.$courseid.'.domain'},
    ($courselevelm,$courselevel));       'course',
        ($courselevelm,$courselevel));
     if (defined($coursereply)) { return $coursereply; }      if (defined($coursereply)) { return $coursereply; }
  }   }
 # ------------------------------------------------------------------ Cascade up  # ------------------------------------------------------------------ Cascade up
Line 4369  sub EXT { Line 4918  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 4381  sub EXT { Line 4930  sub EXT {
  if ($space eq 'time') {   if ($space eq 'time') {
     return time;      return time;
         }          }
       } elsif ($realm eq 'server') {
   # ----------------------------------------------------------------- system.time
    if ($space eq 'name') {
       return $ENV{'SERVER_NAME'};
           }
     }      }
     return '';      return '';
 }  }
Line 4577  sub metadata { Line 5131  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,
Line 4613  sub metadata { Line 5166  sub metadata {
  $metaentry{':keys'}=join(',',keys %metathesekeys);   $metaentry{':keys'}=join(',',keys %metathesekeys);
  &metadata_generate_part0(\%metathesekeys,\%metaentry,$uri);   &metadata_generate_part0(\%metathesekeys,\%metaentry,$uri);
  $metaentry{':allpossiblekeys'}=join(',',keys %metathesekeys);   $metaentry{':allpossiblekeys'}=join(',',keys %metathesekeys);
  &do_cache_new('meta',$uri,\%metaentry);   &do_cache_new('meta',$uri,\%metaentry,60*60);
 # this is the end of "was not already recently cached  # this is the end of "was not already recently cached
     }      }
     return $metaentry{':'.$what};      return $metaentry{':'.$what};
Line 4665  sub metadata_generate_part0 { Line 5218  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 4677  sub gettitle { Line 5230  sub gettitle {
     my $urlsymb=shift;      my $urlsymb=shift;
     my $symb=&symbread($urlsymb);      my $symb=&symbread($urlsymb);
     if ($symb) {      if ($symb) {
  my $key=$ENV{'request.course.id'}."\0".$symb;   my $key=$env{'request.course.id'}."\0".$symb;
  my ($result,$cached)=&is_cached_new('title',$key);   my ($result,$cached)=&is_cached_new('title',$key);
  if (defined($cached)) {    if (defined($cached)) { 
     return $result;      return $result;
Line 4685  sub gettitle { Line 5238  sub gettitle {
  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 4706  sub get_slot { Line 5259  sub get_slot {
     my ($which,$cnum,$cdom)=@_;      my ($which,$cnum,$cdom)=@_;
     if (!$cnum || !$cdom) {      if (!$cnum || !$cdom) {
  (undef,my $courseid)=&Apache::lonxml::whichuser();   (undef,my $courseid)=&Apache::lonxml::whichuser();
  $cdom=$ENV{'course.'.$courseid.'.domain'};   $cdom=$env{'course.'.$courseid.'.domain'};
  $cnum=$ENV{'course.'.$courseid.'.num'};   $cnum=$env{'course.'.$courseid.'.num'};
     }      }
     my %slotinfo=&get('slots',[$which],$cdom,$cnum);      my %slotinfo=&get('slots',[$which],$cdom,$cnum);
     &Apache::lonhomework::showhash(%slotinfo);      &Apache::lonhomework::showhash(%slotinfo);
Line 4724  sub symblist { Line 5277  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($_)}=&encode_symb($mapname,$newhash{$_}->[1],                  $hash{declutter($_)}=&encode_symb($mapname,$newhash{$_}->[1],
Line 4746  sub symbverify { Line 5299  sub symbverify {
     my $thisfn=$thisurl;      my $thisfn=$thisurl;
 # wrapper not part of symbs  # wrapper not part of symbs
     $thisfn=~s/^\/adm\/wrapper//;      $thisfn=~s/^\/adm\/wrapper//;
       $thisfn=~s/^\/adm\/coursedocs\/showdoc\///;
     $thisfn=&declutter($thisfn);      $thisfn=&declutter($thisfn);
 # direct jump to resource in page or to a sequence - will construct own symbs  # direct jump to resource in page or to a sequence - will construct own symbs
     if ($thisfn=~/\.(page|sequence)$/) { return 1; }      if ($thisfn=~/\.(page|sequence)$/) { return 1; }
Line 4761  sub symbverify { Line 5315  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 4770  sub symbverify { Line 5324  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 4800  sub symbclean { Line 5354  sub symbclean {
 # remove wrapper  # remove wrapper
   
     $symb=~s/(\_\_\_\d+\_\_\_)adm\/wrapper\/(res\/)*/$1/;      $symb=~s/(\_\_\_\d+\_\_\_)adm\/wrapper\/(res\/)*/$1/;
       $symb=~s/(\_\_\_\d+\_\_\_)adm\/coursedocs\/showdoc\/(res\/)*/$1/;
     return $symb;      return $symb;
 }  }
   
Line 4822  sub fixversion { Line 5377  sub fixversion {
     if ($fn=~/^(adm|uploaded|editupload|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_new('courseresversion',$key);      my ($result,$cached)=&is_cached_new('courseresversion',$key);
     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 4852  sub deversion { Line 5407  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|editupload)\//) && ($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 ($targetfn =~ m|^adm/wrapper/(ext/.*)|) {
       $targetfn=$1;
    }
           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);
Line 4884  sub symbread { Line 5442  sub symbread {
 # ---------------------------------------------------------- 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 4909  sub symbread { Line 5467  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 4919  sub symbread { Line 5478  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 4933  sub symbread { Line 5492  sub symbread {
            }             }
         }          }
         if ($syval) {          if ($syval) {
     return $ENV{$cache_str}=$syval;      return $env{$cache_str}=$syval;
     #return $ENV{$cache_str}=&symbclean($syval.'___'.$thisfn);  
         }          }
     }      }
     &appenv('request.ambiguous' => $thisfn);      &appenv('request.ambiguous' => $thisfn);
     return $ENV{$cache_str}='';      return $env{$cache_str}='';
 }  }
   
 # ---------------------------------------------------------- Return random seed  # ---------------------------------------------------------- Return random seed
Line 4989  sub numval3 { Line 5547  sub numval3 {
     return $total;      return $total;
 }  }
   
   sub digest {
       my ($data)=@_;
       my $digest=&Digest::MD5::md5($data);
       my ($a,$b,$c,$d)=unpack("iiii",$digest);
       my ($e,$f);
       {
           use integer;
           $e=($a+$b);
           $f=($c+$d);
           if ($_64bit) {
               $e=(($e<<32)>>32);
               $f=(($f<<32)>>32);
           }
       }
       if (wantarray) {
    return ($e,$f);
       } else {
    my $g;
    {
       use integer;
       $g=($e+$f);
       if ($_64bit) {
    $g=(($g<<32)>>32);
       }
    }
    return $g;
       }
   }
   
 sub latest_rnd_algorithm_id {  sub latest_rnd_algorithm_id {
     return '64bit4';      return '64bit5';
 }  }
   
 sub get_rand_alg {  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 5009  sub validCODE { Line 5596  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 5029  sub rndseed { Line 5617  sub rndseed {
     if (!$username) { $username=$wusername }      if (!$username) { $username=$wusername }
     my $which=&get_rand_alg();      my $which=&get_rand_alg();
     if (defined(&getCODE())) {      if (defined(&getCODE())) {
  if ($which eq '64bit4') {   if ($which eq '64bit5') {
       return &rndseed_CODE_64bit5($symb,$courseid,$domain,$username);
    } elsif ($which eq '64bit4') {
     return &rndseed_CODE_64bit4($symb,$courseid,$domain,$username);      return &rndseed_CODE_64bit4($symb,$courseid,$domain,$username);
  } else {   } else {
     return &rndseed_CODE_64bit($symb,$courseid,$domain,$username);      return &rndseed_CODE_64bit($symb,$courseid,$domain,$username);
  }   }
       } elsif ($which eq '64bit5') {
    return &rndseed_64bit5($symb,$courseid,$domain,$username);
     } elsif ($which eq '64bit4') {      } elsif ($which eq '64bit4') {
  return &rndseed_64bit4($symb,$courseid,$domain,$username);   return &rndseed_64bit4($symb,$courseid,$domain,$username);
     } elsif ($which eq '64bit3') {      } elsif ($which eq '64bit3') {
Line 5156  sub rndseed_64bit4 { Line 5748  sub rndseed_64bit4 {
     }      }
 }  }
   
   sub rndseed_64bit5 {
       my ($symb,$courseid,$domain,$username)=@_;
       my ($num1,$num2)=&digest("$symb,$courseid,$domain,$username");
       return "$num1:$num2";
   }
   
 sub rndseed_CODE_64bit {  sub rndseed_CODE_64bit {
     my ($symb,$courseid,$domain,$username)=@_;      my ($symb,$courseid,$domain,$username)=@_;
     {      {
Line 5194  sub rndseed_CODE_64bit4 { Line 5792  sub rndseed_CODE_64bit4 {
     }      }
 }  }
   
   sub rndseed_CODE_64bit5 {
       my ($symb,$courseid,$domain,$username)=@_;
       my $code = &getCODE();
       my ($num1,$num2)=&digest("$symb,$courseid,$code");
       return "$num1:$num2";
   }
   
 sub setup_random_from_rndseed {  sub setup_random_from_rndseed {
     my ($rndseed)=@_;      my ($rndseed)=@_;
     if ($rndseed =~/([,:])/) {      if ($rndseed =~/([,:])/) {
Line 5211  sub latest_receipt_algorithm_id { Line 5816  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 5222  sub recunique { Line 5827  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 5239  sub ireceipt { Line 5844  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 5353  sub tokenwrapper { Line 5958  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 5400  sub filelocation { Line 6005  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-^/adm/-) {
    $file=~s-^/adm/wrapper/-/-;
    $file=~s-^/adm/coursedocs/showdoc/-/-;
       }
     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=~m:^/home/[^/]*/public_html/:) {
    # is a correct contruction space reference
           $location = $file;
     } elsif ($file=~/^\/*(uploaded|editupload)/) { # is an uploaded file      } elsif ($file=~/^\/*(uploaded|editupload)/) { # is an uploaded file
         my ($udom,$uname,$filename)=          my ($udom,$uname,$filename)=
      ($file=~m -^/+(?:uploaded|editupload)/+([^/]+)/+([^/]+)/+(.*)$-);       ($file=~m -^/+(?:uploaded|editupload)/+([^/]+)/+([^/]+)/+(.*)$-);
Line 5435  sub filelocation { Line 6048  sub filelocation {
 sub hreflocation {  sub hreflocation {
     my ($dir,$file)=@_;      my ($dir,$file)=@_;
     unless (($file=~m-^http://-i) || ($file=~m-^/-)) {      unless (($file=~m-^http://-i) || ($file=~m-^/-)) {
  my $finalpath=filelocation($dir,$file);   $file=filelocation($dir,$file);
  $finalpath=~s-^/home/httpd/html--;      } elsif ($file=~m-^/adm/-) {
  $finalpath=~s-^/home/(\w+)/public_html/-/~$1/-;   $file=~s-^/adm/wrapper/-/-;
  return $finalpath;   $file=~s-^/adm/coursedocs/showdoc/-/-;
     } elsif ($file=~m-^/home-) {      }
  $file=~s-^/home/httpd/html--;      if ($file=~m-^\Q$perlvar{'lonDocRoot'}\E-) {
    $file=~s-^\Q$perlvar{'lonDocRoot'}\E--;
       } elsif ($file=~m-/home/(\w+)/public_html/-) {
  $file=~s-^/home/(\w+)/public_html/-/~$1/-;   $file=~s-^/home/(\w+)/public_html/-/~$1/-;
  return $file;      } elsif ($file=~m-^\Q$perlvar{'lonUsersDir'}\E-) {
    $file=~s-^/home/httpd/lonUsers/([^/]*)/./././([^/]*)/userfiles/
       -/uploaded/$1/$2/-x;
     }      }
     return $file;      return $file;
 }  }
Line 5478  sub declutter { Line 6095  sub declutter {
     if ($thisfn=~m|^/enc/|) { $thisfn=&Apache::lonenc::unencrypted($thisfn); }      if ($thisfn=~m|^/enc/|) { $thisfn=&Apache::lonenc::unencrypted($thisfn); }
     $thisfn=~s/^\Q$perlvar{'lonDocRoot'}\E//;      $thisfn=~s/^\Q$perlvar{'lonDocRoot'}\E//;
     $thisfn=~s/^\///;      $thisfn=~s/^\///;
       $thisfn=~s|^adm/wrapper/||;
       $thisfn=~s|^adm/coursedocs/showdoc/||;
     $thisfn=~s/^res\///;      $thisfn=~s/^res\///;
     $thisfn=~s/\?.+$//;      $thisfn=~s/\?.+$//;
     return $thisfn;      return $thisfn;
Line 5490  sub clutter { Line 6109  sub clutter {
     unless ($thisfn=~/^\/(uploaded|editupload|adm|userfiles|ext|raw|priv|public)\//) {       unless ($thisfn=~/^\/(uploaded|editupload|adm|userfiles|ext|raw|priv|public)\//) { 
        $thisfn='/res'.$thisfn;          $thisfn='/res'.$thisfn; 
     }      }
       if ($thisfn !~m|/adm|) {
    if ($thisfn =~ m|/ext/|) {
       $thisfn='/adm/wrapper'.$thisfn;
    } else {
       my ($ext) = ($thisfn =~ /\.(\w+)$/);
       my $embstyle=&Apache::loncommon::fileembstyle($ext);
       if ($embstyle eq 'ssi'
    || ($embstyle eq 'hdn')
    || ($embstyle eq 'rat')
    || ($embstyle eq 'prv')
    || ($embstyle eq 'ign')) {
    #do nothing with these
       } elsif (($embstyle eq 'img') 
    || ($embstyle eq 'emb')
    || ($embstyle eq 'wrp')) {
    $thisfn='/adm/wrapper'.$thisfn;
       } elsif ($embstyle eq 'unk'
        && $thisfn!~/\.(sequence|page)$/) {
    $thisfn='/adm/coursedocs/showdoc'.$thisfn;
       } else {
    #&logthis("Got a blank emb style");
       }
    }
       }
     return $thisfn;      return $thisfn;
 }  }
   
Line 5528  sub thaw_unescape { Line 6171  sub thaw_unescape {
     return &unescape($value);      return &unescape($value);
 }  }
   
 sub mod_perl_version {  
     return 1;  
     if (defined($perlvar{'MODPERL2'})) {  
  return 2;  
     }  
 }  
   
 sub correct_line_ends {  sub correct_line_ends {
     my ($result)=@_;      my ($result)=@_;
     $$result =~s/\r\n/\n/mg;      $$result =~s/\r\n/\n/mg;
Line 5605  BEGIN { Line 6241  BEGIN {
 #           next if /^\#/;  #           next if /^\#/;
            chomp;             chomp;
            my ($domain, $domain_description, $def_auth, $def_auth_arg,             my ($domain, $domain_description, $def_auth, $def_auth_arg,
        $def_lang, $city, $longi, $lati) = split(/:/,$_);         $def_lang, $city, $longi, $lati, $primary) = split(/:/,$_);
    $domain_auth_def{$domain}=$def_auth;     $domain_auth_def{$domain}=$def_auth;
            $domain_auth_arg_def{$domain}=$def_auth_arg;             $domain_auth_arg_def{$domain}=$def_auth_arg;
    $domaindescription{$domain}=$domain_description;     $domaindescription{$domain}=$domain_description;
Line 5613  BEGIN { Line 6249  BEGIN {
    $domain_city{$domain}=$city;     $domain_city{$domain}=$city;
    $domain_longi{$domain}=$longi;     $domain_longi{$domain}=$longi;
    $domain_lati{$domain}=$lati;     $domain_lati{$domain}=$lati;
              $domain_primary{$domain}=$primary;
   
  #         &logthis("Domain.tab: $domain, $domain_auth_def{$domain}, $domain_auth_arg_def{$domain},$domaindescription{$domain}");   #         &logthis("Domain.tab: $domain, $domain_auth_def{$domain}, $domain_auth_arg_def{$domain},$domaindescription{$domain}");
 #          &logthis("Domain.tab: $domain ".$domaindescription{$domain} );  #          &logthis("Domain.tab: $domain ".$domaindescription{$domain} );
Line 5638  BEGIN { Line 6275  BEGIN {
        }         }
     }      }
     close($config);      close($config);
       # FIXME: dev server don't want this, production servers _do_ want this
       &get_iphost();
 }  }
   
 sub get_iphost {  sub get_iphost {
     if (%iphost) { return %iphost; }      if (%iphost) { return %iphost; }
       my %name_to_ip;
     foreach my $id (keys(%hostname)) {      foreach my $id (keys(%hostname)) {
  my $name=$hostname{$id};   my $name=$hostname{$id};
  my $ip = gethostbyname($name);   my $ip;
  if (!$ip || length($ip) ne 4) {   if (!exists($name_to_ip{$name})) {
     &logthis("Skipping host $id name $name no IP found\n");      $ip = gethostbyname($name);
     next;      if (!$ip || length($ip) ne 4) {
    &logthis("Skipping host $id name $name no IP found\n");
    next;
       }
       $ip=inet_ntoa($ip);
       $name_to_ip{$name} = $ip;
    } else {
       $ip = $name_to_ip{$name};
  }   }
  $ip=inet_ntoa($ip);  
  push(@{$iphost{$ip}},$id);   push(@{$iphost{$ip}},$id);
     }      }
     return %iphost;      return %iphost;
Line 5724  $processmarker='_'.time.'_'.$perlvar{'lo Line 6370  $processmarker='_'.time.'_'.$perlvar{'lo
 $dumpcount=0;  $dumpcount=0;
   
 &logtouch();  &logtouch();
 &logthis('<font color=yellow>INFO: Read configuration</font>');  &logthis('<font color="yellow">INFO: Read configuration</font>');
 $readit=1;  $readit=1;
     {      {
  use integer;   use integer;
Line 5906  that was requested Line 6552  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 6126  revokecustomrole($udom,$uname,$url,$role Line 6772  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 6221  symbverify($symb,$thisfn) : verifies tha Line 6871  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 6252  unfakeable, receipt Line 6902  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 6286  forcing spreadsheet to reevaluate the re Line 6936  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 6515  declutter() : declutters URLs (remove do Line 7165  declutter() : declutters URLs (remove do
 userfileupload(): main rotine for putting a file in a user or course's  userfileupload(): main rotine for putting a file in a user or course's
                   filespace, arguments are,                    filespace, arguments are,
   
  formname - required - this is the name of the element in $ENV where the   formname - required - this is the name of the element in $env where the
            filename, and the contents of the file to create/modifed exist             filename, and the contents of the file to create/modifed exist
            the filename is in $ENV{'form.'.$formname.'.filename'} and the             the filename is in $env{'form.'.$formname.'.filename'} and the
            contents of the file is located in $ENV{'form.'.$formname}             contents of the file is located in $env{'form.'.$formname}
  coursedoc - if true, store the file in the course of the active role   coursedoc - if true, store the file in the course of the active role
              of the current user               of the current user
  subdir - required - subdirectory to put the file in under ../userfiles/   subdir - required - subdirectory to put the file in under ../userfiles/
Line 6547  userspace, probably shouldn't be called Line 7197  userspace, probably shouldn't be called
   
   docuname: username or courseid of destination for the file    docuname: username or courseid of destination for the file
   docudom: domain of user/course of destination for the file    docudom: domain of user/course of destination for the file
   docuhome: loncapa id of the library server that is getting the file  
   formname: same as for userfileupload()    formname: same as for userfileupload()
   fname: filename (inculding subdirectories) for the file    fname: filename (inculding subdirectories) for the file
   

Removed from v.1.616  
changed lines
  Added in v.1.683.2.12


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