Diff for /loncom/lonnet/perl/lonnet.pm between versions 1.1172.2.28 and 1.1172.2.67

version 1.1172.2.28, 2013/06/27 18:34:21 version 1.1172.2.67, 2015/05/22 17:58:00
Line 75  use LWP::UserAgent(); Line 75  use LWP::UserAgent();
 use HTTP::Date;  use HTTP::Date;
 use Image::Magick;  use Image::Magick;
   
 use vars qw(%perlvar %spareid %pr %prp $memcache %packagetab $tmpdir $apache  use vars qw(%perlvar %spareid %pr %prp $memcache %packagetab $tmpdir
             $_64bit %env %protocol %loncaparevs %serverhomeIDs %needsrelease              $_64bit %env %protocol %loncaparevs %serverhomeIDs %needsrelease
             %managerstab);              %managerstab);
   
Line 352  sub get_remote_globals { Line 352  sub get_remote_globals {
 }  }
   
 sub remote_devalidate_cache {  sub remote_devalidate_cache {
     my ($lonhost,$name,$id) = @_;      my ($lonhost,$cachekeys) = @_;
     my $response = &reply('devalidatecache:'.&escape($name).':'.&escape($id),$lonhost);      my $items;
     return $response;      return unless (ref($cachekeys) eq 'ARRAY');
       my $cachestr = join('&',@{$cachekeys});
       return &reply('devalidatecache:'.&escape($cachestr),$lonhost);
 }  }
   
 # -------------------------------------------------- Non-critical communication  # -------------------------------------------------- Non-critical communication
Line 599  sub transfer_profile_to_env { Line 601  sub transfer_profile_to_env {
   
 # ---------------------------------------------------- Check for valid session   # ---------------------------------------------------- Check for valid session 
 sub check_for_valid_session {  sub check_for_valid_session {
     my ($r,$name) = @_;      my ($r,$name,$userhashref) = @_;
     my %cookies=CGI::Cookie->parse($r->header_in('Cookie'));      my %cookies=CGI::Cookie->parse($r->header_in('Cookie'));
     if ($name eq '') {      if ($name eq '') {
         $name = 'lonID';          $name = 'lonID';
Line 631  sub check_for_valid_session { Line 633  sub check_for_valid_session {
  return undef;   return undef;
     }      }
   
     if (($r->user() eq '') && ($apache >= 2.4)) {      if (ref($userhashref) eq 'HASH') {
         if ($disk_env{'user.domain'} eq $r->dir_config('lonDefDomain')) {          $userhashref->{'name'} = $disk_env{'user.name'};
             $r->user($disk_env{'user.name'});          $userhashref->{'domain'} = $disk_env{'user.domain'};
         } else {  
             $r->user($disk_env{'user.name'}.':'.$disk_env{'user.domain'});  
         }  
     }      }
   
     return $handle;      return $handle;
Line 672  sub appenv { Line 671  sub appenv {
     if (($key =~ /^user\.role/) || ($key =~ /^user\.priv/)) {      if (($key =~ /^user\.role/) || ($key =~ /^user\.priv/)) {
                 $refused = 1;                  $refused = 1;
                 if (ref($roles) eq 'ARRAY') {                  if (ref($roles) eq 'ARRAY') {
                     my ($type,$role) = ($key =~ /^user\.(role|priv)\.([^.]+)\./);                      my ($type,$role) = ($key =~ m{^user\.(role|priv)\.(.+?)\./});
                     if (grep(/^\Q$role\E$/,@{$roles})) {                      if (grep(/^\Q$role\E$/,@{$roles})) {
                         $refused = 0;                          $refused = 0;
                     }                      }
Line 845  sub spareserver { Line 844  sub spareserver {
     if (ref($spareshash) eq 'HASH') {      if (ref($spareshash) eq 'HASH') {
         if (ref($spareshash->{'primary'}) eq 'ARRAY') {          if (ref($spareshash->{'primary'}) eq 'ARRAY') {
             foreach my $try_server (@{ $spareshash->{'primary'} }) {              foreach my $try_server (@{ $spareshash->{'primary'} }) {
                 if ($uint_dom) {                  next unless (&spare_can_host($udom,$uint_dom,$remotesessions,
                     next unless (&spare_can_host($udom,$uint_dom,$remotesessions,                                               $try_server));
                                                  $try_server));  
                 }  
         ($spare_server, $lowest_load) =          ($spare_server, $lowest_load) =
             &compare_server_load($try_server, $spare_server, $lowest_load);              &compare_server_load($try_server, $spare_server, $lowest_load);
             }              }
Line 859  sub spareserver { Line 856  sub spareserver {
         if (!$found_server) {          if (!$found_server) {
             if (ref($spareshash->{'default'}) eq 'ARRAY') {               if (ref($spareshash->{'default'}) eq 'ARRAY') { 
         foreach my $try_server (@{ $spareshash->{'default'} }) {          foreach my $try_server (@{ $spareshash->{'default'} }) {
                     if ($uint_dom) {                      next unless (&spare_can_host($udom,$uint_dom,
                         next unless (&spare_can_host($udom,$uint_dom,                                                   $remotesessions,$try_server));
                                                      $remotesessions,$try_server));  
                     }  
             ($spare_server, $lowest_load) =              ($spare_server, $lowest_load) =
         &compare_server_load($try_server, $spare_server, $lowest_load);          &compare_server_load($try_server, $spare_server, $lowest_load);
                 }                  }
Line 886  sub spareserver { Line 881  sub spareserver {
 }  }
   
 sub compare_server_load {  sub compare_server_load {
     my ($try_server, $spare_server, $lowest_load) = @_;      my ($try_server, $spare_server, $lowest_load, $required) = @_;
   
       if ($required) {
           my ($reqdmajor,$reqdminor) = ($required =~ /^(\d+)\.(\d+)$/);
           my $remoterev = &get_server_loncaparev(undef,$try_server);
           my ($major,$minor) = ($remoterev =~ /^\'?(\d+)\.(\d+)\.[\w.\-]+\'?$/);
           if (($major eq '' && $minor eq '') ||
               (($reqdmajor > $major) || (($reqdmajor == $major) && ($reqdminor > $minor)))) {
               return ($spare_server,$lowest_load);
           }
       }
   
     my $loadans     = &reply('load',    $try_server);      my $loadans     = &reply('load',    $try_server);
     my $userloadans = &reply('userload',$try_server);      my $userloadans = &reply('userload',$try_server);
Line 947  sub has_user_session { Line 952  sub has_user_session {
 # --------- determine least loaded server in a user's domain which allows login  # --------- determine least loaded server in a user's domain which allows login
   
 sub choose_server {  sub choose_server {
     my ($udom,$checkloginvia) = @_;      my ($udom,$checkloginvia,$required,$skiploadbal) = @_;
     my %domconfhash = &Apache::loncommon::get_domainconf($udom);      my %domconfhash = &Apache::loncommon::get_domainconf($udom);
     my %servers = &get_servers($udom);      my %servers = &get_servers($udom);
     my $lowest_load = 30000;      my $lowest_load = 30000;
     my ($login_host,$hostname,$portal_path,$isredirect);      my ($login_host,$hostname,$portal_path,$isredirect,$balancers);
       if ($skiploadbal) {
           ($balancers,my $cached)=&is_cached_new('loadbalancing',$udom);
           unless (defined($cached)) {
               my $cachetime = 60*60*24;
               my %domconfig =
                   &Apache::lonnet::get_dom('configuration',['loadbalancing'],$udom);
               if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
                   $balancers = &do_cache_new('loadbalancing',$udom,$domconfig{'loadbalancing'},
                                              $cachetime);
               }
           }
       }
     foreach my $lonhost (keys(%servers)) {      foreach my $lonhost (keys(%servers)) {
         my $loginvia;          my $loginvia;
           if ($skiploadbal) {
               if (ref($balancers) eq 'HASH') {
                   next if (exists($balancers->{$lonhost}));
               }
           }
         if ($checkloginvia) {          if ($checkloginvia) {
             $loginvia = $domconfhash{$udom.'.login.loginvia_'.$lonhost};              $loginvia = $domconfhash{$udom.'.login.loginvia_'.$lonhost};
             if ($loginvia) {              if ($loginvia) {
                 my ($server,$path) = split(/:/,$loginvia);                  my ($server,$path) = split(/:/,$loginvia);
                 ($login_host, $lowest_load) =                  ($login_host, $lowest_load) =
                     &compare_server_load($server, $login_host, $lowest_load);                      &compare_server_load($server, $login_host, $lowest_load, $required);
                 if ($login_host eq $server) {                  if ($login_host eq $server) {
                     $portal_path = $path;                      $portal_path = $path;
                     $isredirect = 1;                      $isredirect = 1;
                 }                  }
             } else {              } else {
                 ($login_host, $lowest_load) =                  ($login_host, $lowest_load) =
                     &compare_server_load($lonhost, $login_host, $lowest_load);                      &compare_server_load($lonhost, $login_host, $lowest_load, $required);
                 if ($login_host eq $lonhost) {                  if ($login_host eq $lonhost) {
                     $portal_path = '';                      $portal_path = '';
                     $isredirect = '';                       $isredirect = ''; 
Line 974  sub choose_server { Line 996  sub choose_server {
             }              }
         } else {          } else {
             ($login_host, $lowest_load) =              ($login_host, $lowest_load) =
                 &compare_server_load($lonhost, $login_host, $lowest_load);                  &compare_server_load($lonhost, $login_host, $lowest_load, $required);
         }          }
     }      }
     if ($login_host ne '') {      if ($login_host ne '') {
Line 1147  sub can_host_session { Line 1169  sub can_host_session {
 sub spare_can_host {  sub spare_can_host {
     my ($udom,$uint_dom,$remotesessions,$try_server)=@_;      my ($udom,$uint_dom,$remotesessions,$try_server)=@_;
     my $canhost=1;      my $canhost=1;
     my @intdoms;      my $try_server_hostname = &hostname($try_server);
     my $internet_names = &Apache::lonnet::get_internet_names($try_server);      my $serverhomeID = &get_server_homeID($try_server_hostname);
     if (ref($internet_names) eq 'ARRAY') {      my $serverhomedom = &host_domain($serverhomeID);
         @intdoms = @{$internet_names};      my %defdomdefaults = &get_domain_defaults($serverhomedom);
     }      if (ref($defdomdefaults{'offloadnow'}) eq 'HASH') {
     unless (grep(/^\Q$uint_dom\E$/,@intdoms)) {          if ($defdomdefaults{'offloadnow'}{$try_server}) {
         my $serverhomeID = &Apache::lonnet::get_server_homeID($try_server);              $canhost = 0;
         my $serverhomedom = &Apache::lonnet::host_domain($serverhomeID);          }
         my %defdomdefaults = &Apache::lonnet::get_domain_defaults($serverhomedom);      }
         my $remoterev = &Apache::lonnet::get_server_loncaparev(undef,$try_server);      if (($canhost) && ($uint_dom)) {
         $canhost = &can_host_session($udom,$try_server,$remoterev,          my @intdoms;
                                      $remotesessions,          my $internet_names = &get_internet_names($try_server);
                                      $defdomdefaults{'hostedsessions'});          if (ref($internet_names) eq 'ARRAY') {
               @intdoms = @{$internet_names};
           }
           unless (grep(/^\Q$uint_dom\E$/,@intdoms)) {
               my $remoterev = &get_server_loncaparev(undef,$try_server);
               $canhost = &can_host_session($udom,$try_server,$remoterev,
                                            $remotesessions,
                                            $defdomdefaults{'hostedsessions'});
           }
     }      }
     return $canhost;      return $canhost;
 }  }
Line 1321  sub check_loadbalancing { Line 1351  sub check_loadbalancing {
             }              }
         }          }
     } elsif (($homeintdom) && ($udom ne $serverhomedom)) {      } elsif (($homeintdom) && ($udom ne $serverhomedom)) {
         my ($result,$cached)=&is_cached_new('loadbalancing',$serverhomedom);          ($result,$cached)=&is_cached_new('loadbalancing',$serverhomedom);
         unless (defined($cached)) {          unless (defined($cached)) {
             my %domconfig =              my %domconfig =
                 &Apache::lonnet::get_dom('configuration',['loadbalancing'],$serverhomedom);                  &Apache::lonnet::get_dom('configuration',['loadbalancing'],$serverhomedom);
Line 1576  sub idput { Line 1606  sub idput {
     }      }
 }  }
   
   # ---------------------------------------- Delete unwanted IDs from ids.db file
   
   sub iddel {
       my ($udom,$idshashref,$uhome)=@_;
       my %result=();
       unless (ref($idshashref) eq 'HASH') {
           return %result;
       }
       my %servers=();
       while (my ($id,$uname) = each(%{$idshashref})) {
           my $uhom;
           if ($uhome) {
               $uhom = $uhome;
           } else {
               $uhom=&homeserver($uname,$udom);
           }
           if ($uhom ne 'no_host') {
               if ($servers{$uhom}) {
                   $servers{$uhom}.='&'.&escape($id);
               } else {
                   $servers{$uhom}=&escape($id);
               }
           }
       }
       foreach my $server (keys(%servers)) {
           $result{$server} = &critical('iddel:'.$udom.':'.$servers{$server},$uhome);
       }
       return %result;
   }
   
 # ------------------------------dump from db file owned by domainconfig user  # ------------------------------dump from db file owned by domainconfig user
 sub dump_dom {  sub dump_dom {
     my ($namespace, $udom, $regexp) = @_;      my ($namespace, $udom, $regexp) = @_;
Line 1591  sub dump_dom { Line 1651  sub dump_dom {
   
 sub get_dom {  sub get_dom {
     my ($namespace,$storearr,$udom,$uhome)=@_;      my ($namespace,$storearr,$udom,$uhome)=@_;
       return if ($udom eq 'public');
     my $items='';      my $items='';
     foreach my $item (@$storearr) {      foreach my $item (@$storearr) {
         $items.=&escape($item).'&';          $items.=&escape($item).'&';
Line 1598  sub get_dom { Line 1659  sub get_dom {
     $items=~s/\&$//;      $items=~s/\&$//;
     if (!$udom) {      if (!$udom) {
         $udom=$env{'user.domain'};          $udom=$env{'user.domain'};
           return if ($udom eq 'public');
         if (defined(&domain($udom,'primary'))) {          if (defined(&domain($udom,'primary'))) {
             $uhome=&domain($udom,'primary');              $uhome=&domain($udom,'primary');
         } else {          } else {
Line 1701  sub retrieve_inst_usertypes { Line 1763  sub retrieve_inst_usertypes {
     my %domdefs = &Apache::lonnet::get_domain_defaults($udom);      my %domdefs = &Apache::lonnet::get_domain_defaults($udom);
     if ((ref($domdefs{'inststatustypes'}) eq 'HASH') &&       if ((ref($domdefs{'inststatustypes'}) eq 'HASH') && 
         (ref($domdefs{'inststatusorder'}) eq 'ARRAY')) {          (ref($domdefs{'inststatusorder'}) eq 'ARRAY')) {
         %returnhash = %{$domdefs{'inststatustypes'}};          return ($domdefs{'inststatustypes'},$domdefs{'inststatusorder'});
         @order = @{$domdefs{'inststatusorder'}};  
     } else {      } else {
         if (defined(&domain($udom,'primary'))) {          if (defined(&domain($udom,'primary'))) {
             my $uhome=&domain($udom,'primary');              my $uhome=&domain($udom,'primary');
             my $rep=&reply("inst_usertypes:$udom",$uhome);              my $rep=&reply("inst_usertypes:$udom",$uhome);
             if ($rep =~ /^(con_lost|error|no_such_host|refused)/) {              if ($rep =~ /^(con_lost|error|no_such_host|refused)/) {
                 &logthis("get_dom failed - $rep returned from $uhome in domain: $udom");                  &logthis("retrieve_inst_usertypes failed - $rep returned from $uhome in domain: $udom");
                 return (\%returnhash,\@order);                  return (\%returnhash,\@order);
             }              }
             my ($hashitems,$orderitems) = split(/:/,$rep);               my ($hashitems,$orderitems) = split(/:/,$rep); 
Line 1724  sub retrieve_inst_usertypes { Line 1785  sub retrieve_inst_usertypes {
                 push(@order,&unescape($item));                  push(@order,&unescape($item));
             }              }
         } else {          } else {
             &logthis("get_dom failed - no primary domain server for $udom");              &logthis("retrieve_inst_usertypes failed - no primary domain server for $udom");
         }          }
           return (\%returnhash,\@order);
     }      }
     return (\%returnhash,\@order);  
 }  }
   
 sub is_domainimage {  sub is_domainimage {
Line 1952  sub inst_userrules { Line 2013  sub inst_userrules {
 # ------------- Get Authentication, Language and User Tools Defaults for Domain  # ------------- Get Authentication, Language and User Tools Defaults for Domain
   
 sub get_domain_defaults {  sub get_domain_defaults {
     my ($domain) = @_;      my ($domain,$ignore_cache) = @_;
       return if (($domain eq '') || ($domain eq 'public'));
     my $cachetime = 60*60*24;      my $cachetime = 60*60*24;
     my ($result,$cached)=&is_cached_new('domdefaults',$domain);      unless ($ignore_cache) {
     if (defined($cached)) {          my ($result,$cached)=&is_cached_new('domdefaults',$domain);
         if (ref($result) eq 'HASH') {          if (defined($cached)) {
             return %{$result};              if (ref($result) eq 'HASH') {
                   return %{$result};
               }
         }          }
     }      }
     my %domdefaults;      my %domdefaults;
Line 1965  sub get_domain_defaults { Line 2029  sub get_domain_defaults {
          &Apache::lonnet::get_dom('configuration',['defaults','quotas',           &Apache::lonnet::get_dom('configuration',['defaults','quotas',
                                   'requestcourses','inststatus',                                    'requestcourses','inststatus',
                                   'coursedefaults','usersessions',                                    'coursedefaults','usersessions',
                                   'requestauthor'],$domain);                                    'requestauthor','selfenrollment',
                                     'coursecategories'],$domain);
       my @coursetypes = ('official','unofficial','community','textbook');
     if (ref($domconfig{'defaults'}) eq 'HASH') {      if (ref($domconfig{'defaults'}) eq 'HASH') {
         $domdefaults{'lang_def'} = $domconfig{'defaults'}{'lang_def'};           $domdefaults{'lang_def'} = $domconfig{'defaults'}{'lang_def'}; 
         $domdefaults{'auth_def'} = $domconfig{'defaults'}{'auth_def'};          $domdefaults{'auth_def'} = $domconfig{'defaults'}{'auth_def'};
Line 1983  sub get_domain_defaults { Line 2049  sub get_domain_defaults {
             $domdefaults{'defaultquota'} = $domconfig{'quotas'}{'defaultquota'};              $domdefaults{'defaultquota'} = $domconfig{'quotas'}{'defaultquota'};
         } else {          } else {
             $domdefaults{'defaultquota'} = $domconfig{'quotas'};              $domdefaults{'defaultquota'} = $domconfig{'quotas'};
         }           }
         my @usertools = ('aboutme','blog','webdav','portfolio');          my @usertools = ('aboutme','blog','webdav','portfolio');
         foreach my $item (@usertools) {          foreach my $item (@usertools) {
             if (ref($domconfig{'quotas'}{$item}) eq 'HASH') {              if (ref($domconfig{'quotas'}{$item}) eq 'HASH') {
                 $domdefaults{$item} = $domconfig{'quotas'}{$item};                  $domdefaults{$item} = $domconfig{'quotas'}{$item};
             }              }
         }          }
           if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') {
               $domdefaults{'authorquota'} = $domconfig{'quotas'}{'authorquota'};
           }
     }      }
     if (ref($domconfig{'requestcourses'}) eq 'HASH') {      if (ref($domconfig{'requestcourses'}) eq 'HASH') {
         foreach my $item ('official','unofficial','community') {          foreach my $item ('official','unofficial','community','textbook') {
             $domdefaults{$item} = $domconfig{'requestcourses'}{$item};              $domdefaults{$item} = $domconfig{'requestcourses'}{$item};
         }          }
     }      }
Line 2000  sub get_domain_defaults { Line 2069  sub get_domain_defaults {
         $domdefaults{'requestauthor'} = $domconfig{'requestauthor'};          $domdefaults{'requestauthor'} = $domconfig{'requestauthor'};
     }      }
     if (ref($domconfig{'inststatus'}) eq 'HASH') {      if (ref($domconfig{'inststatus'}) eq 'HASH') {
         foreach my $item ('inststatustypes','inststatusorder') {          foreach my $item ('inststatustypes','inststatusorder','inststatusguest') {
             $domdefaults{$item} = $domconfig{'inststatus'}{$item};              $domdefaults{$item} = $domconfig{'inststatus'}{$item};
         }          }
     }      }
     if (ref($domconfig{'coursedefaults'}) eq 'HASH') {      if (ref($domconfig{'coursedefaults'}) eq 'HASH') {
         if (ref($domconfig{'coursedefaults'}{'coursecredits'}) eq 'HASH') {          $domdefaults{'usejsme'} = $domconfig{'coursedefaults'}{'usejsme'};
             $domdefaults{'officialcredits'} = $domconfig{'coursedefaults'}{'coursecredits'}{'official'};          $domdefaults{'uselcmath'} = $domconfig{'coursedefaults'}{'uselcmath'};
             $domdefaults{'unofficialcredits'} = $domconfig{'coursedefaults'}{'coursecredits'}{'unofficial'};          if (ref($domconfig{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
               $domdefaults{'postsubmit'} = $domconfig{'coursedefaults'}{'postsubmit'}{'client'};
           }
           foreach my $type (@coursetypes) {
               if (ref($domconfig{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
                   unless ($type eq 'community') {
                       $domdefaults{$type.'credits'} = $domconfig{'coursedefaults'}{'coursecredits'}{$type};
                   }
               }
               if (ref($domconfig{'coursedefaults'}{'uploadquota'}) eq 'HASH') {
                   $domdefaults{$type.'quota'} = $domconfig{'coursedefaults'}{'uploadquota'}{$type};
               }
               if ($domdefaults{'postsubmit'} eq 'on') {
                   if (ref($domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {
                       $domdefaults{$type.'postsubtimeout'} =
                           $domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}{$type};
                   }
               }
           }
           if (ref($domconfig{'coursedefaults'}{'canclone'}) eq 'HASH') {
               if (ref($domconfig{'coursedefaults'}{'canclone'}{'instcode'}) eq 'ARRAY') {
                   my @clonecodes = @{$domconfig{'coursedefaults'}{'canclone'}{'instcode'}};
                   if (@clonecodes) {
                       $domdefaults{'canclone'} = join('+',@clonecodes);
                   }
               }
           } elsif ($domconfig{'coursedefaults'}{'canclone'}) {
               $domdefaults{'canclone'}=$domconfig{'coursedefaults'}{'canclone'};
         }          }
     }      }
     if (ref($domconfig{'usersessions'}) eq 'HASH') {      if (ref($domconfig{'usersessions'}) eq 'HASH') {
Line 2017  sub get_domain_defaults { Line 2113  sub get_domain_defaults {
         if (ref($domconfig{'usersessions'}{'hosted'}) eq 'HASH') {          if (ref($domconfig{'usersessions'}{'hosted'}) eq 'HASH') {
             $domdefaults{'hostedsessions'} = $domconfig{'usersessions'}{'hosted'};              $domdefaults{'hostedsessions'} = $domconfig{'usersessions'}{'hosted'};
         }          }
           if (ref($domconfig{'usersessions'}{'offloadnow'}) eq 'HASH') {
               $domdefaults{'offloadnow'} = $domconfig{'usersessions'}{'offloadnow'};
           }
       }
       if (ref($domconfig{'selfenrollment'}) eq 'HASH') {
           if (ref($domconfig{'selfenrollment'}{'admin'}) eq 'HASH') {
               my @settings = ('types','registered','enroll_dates','access_dates','section',
                               'approval','limit');
               foreach my $type (@coursetypes) {
                   if (ref($domconfig{'selfenrollment'}{'admin'}{$type}) eq 'HASH') {
                       my @mgrdc = ();
                       foreach my $item (@settings) {
                           if ($domconfig{'selfenrollment'}{'admin'}{$type}{$item} eq '0') {
                               push(@mgrdc,$item);
                           }
                       }
                       if (@mgrdc) {
                           $domdefaults{$type.'selfenrolladmdc'} = join(',',@mgrdc);
                       }
                   }
               }
           }
           if (ref($domconfig{'selfenrollment'}{'default'}) eq 'HASH') {
               foreach my $type (@coursetypes) {
                   if (ref($domconfig{'selfenrollment'}{'default'}{$type}) eq 'HASH') {
                       foreach my $item (keys(%{$domconfig{'selfenrollment'}{'default'}{$type}})) {
                           $domdefaults{$type.'selfenroll'.$item} = $domconfig{'selfenrollment'}{'default'}{$type}{$item};
                       }
                   }
               }
           }
       }
       if (ref($domconfig{'coursecategories'}) eq 'HASH') {
           $domdefaults{'catauth'} = 'std';
           $domdefaults{'catunauth'} = 'std';
           if ($domconfig{'coursecategories'}{'auth'}) {
               $domdefaults{'catauth'} = $domconfig{'coursecategories'}{'auth'};
           }
           if ($domconfig{'coursecategories'}{'unauth'}) {
               $domdefaults{'catunauth'} = $domconfig{'coursecategories'}{'unauth'};
           }
     }      }
     &do_cache_new('domdefaults',$domain,\%domdefaults,$cachetime);      &do_cache_new('domdefaults',$domain,\%domdefaults,$cachetime);
     return %domdefaults;      return %domdefaults;
Line 2608  sub ssi { Line 2745  sub ssi {
     &Apache::lonenc::check_encrypt(\$fn);      &Apache::lonenc::check_encrypt(\$fn);
     if (%form) {      if (%form) {
       $request=new HTTP::Request('POST',&absolute_url().$fn);        $request=new HTTP::Request('POST',&absolute_url().$fn);
       $request->content(join('&',map { &escape($_).'='.&escape($form{$_}) } keys(%form)));        $request->content(join('&',map {
               my $name = escape($_);
               "$name=" . ( ref($form{$_}) eq 'ARRAY'
               ? join("&$name=", map {escape($_) } @{$form{$_}})
               : &escape($form{$_}) );
           } keys(%form)));
     } else {      } else {
       $request=new HTTP::Request('GET',&absolute_url().$fn);        $request=new HTTP::Request('GET',&absolute_url().$fn);
     }      }
Line 2808  sub can_edit_resource { Line 2950  sub can_edit_resource {
                     $cfile =~ s{^http://}{};                      $cfile =~ s{^http://}{};
                     $cfile = '/adm/wrapper/ext/'.$cfile;                      $cfile = '/adm/wrapper/ext/'.$cfile;
                 }                  }
               } elsif ($resurl =~ m{^/?adm/viewclasslist$}) {
                   if ($env{'form.forceedit'}) {
                       $forceview = 1;
                   } else {
                       $forceedit = 1;
                   }
                   $cfile = ($resurl =~ m{^/} ? $resurl : "/$resurl");
             }              }
         }          }
         if ($uploaded || $incourse) {          if ($uploaded || $incourse) {
Line 3445  sub extract_embedded_items { Line 3594  sub extract_embedded_items {
                     }                      }
                 }                  }
     }      }
               if (lc($tagname) eq 'iframe') {
                   my $src = $attr->{'src'} ;
                   if (($src ne '') && ($src !~ m{^(/|https?://)})) {
                       &add_filetype($allfiles,$src,'src');
                   } elsif ($src =~ m{^/}) {
                       if ($env{'request.course.id'}) {
                           my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                           my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                           my $url = &hreflocation('',$fullpath);
                           if ($url =~ m{^/uploaded/$cdom/$cnum/docs/(\w+/\d+)/}) {
                               my $relpath = $1;
                               if ($src =~ m{^/uploaded/$cdom/$cnum/docs/\Q$relpath\E/(.+)$}) {
                                   &add_filetype($allfiles,$1,'src');
                               }
                           }
                       }
                   }
               }
             if ($t->[4] =~ m{/>$}) {              if ($t->[4] =~ m{/>$}) {
                 pop(@state);                    pop(@state);
             }              }
  } elsif ($t->[0] eq 'E') {   } elsif ($t->[0] eq 'E') {
     my ($tagname) = ($t->[1]);      my ($tagname) = ($t->[1]);
Line 4103  sub courseiddump { Line 4270  sub courseiddump {
     my ($domfilter,$descfilter,$sincefilter,$instcodefilter,$ownerfilter,      my ($domfilter,$descfilter,$sincefilter,$instcodefilter,$ownerfilter,
         $coursefilter,$hostidflag,$hostidref,$typefilter,$regexp_ok,          $coursefilter,$hostidflag,$hostidref,$typefilter,$regexp_ok,
         $selfenrollonly,$catfilter,$showhidden,$caller,$cloner,$cc_clone,          $selfenrollonly,$catfilter,$showhidden,$caller,$cloner,$cc_clone,
         $cloneonly,$createdbefore,$createdafter,$creationcontext,$domcloner)=@_;          $cloneonly,$createdbefore,$createdafter,$creationcontext,$domcloner,
           $hasuniquecode)=@_;
     my $as_hash = 1;      my $as_hash = 1;
     my %returnhash;      my %returnhash;
     if (!$domfilter) { $domfilter=''; }      if (!$domfilter) { $domfilter=''; }
Line 4126  sub courseiddump { Line 4294  sub courseiddump {
                                 &escape($catfilter), $showhidden, $caller,                                  &escape($catfilter), $showhidden, $caller,
                                 &escape($cloner), &escape($cc_clone), $cloneonly,                                  &escape($cloner), &escape($cc_clone), $cloneonly,
                                 &escape($createdbefore), &escape($createdafter),                                  &escape($createdbefore), &escape($createdafter),
                                 &escape($creationcontext), $domcloner)));                                  &escape($creationcontext), $domcloner, $hasuniquecode)));
                 } else {                  } else {
                     $rep = &reply('courseiddump:'.&host_domain($tryserver).':'.                      $rep = &reply('courseiddump:'.&host_domain($tryserver).':'.
                              $sincefilter.':'.&escape($descfilter).':'.                               $sincefilter.':'.&escape($descfilter).':'.
Line 4137  sub courseiddump { Line 4305  sub courseiddump {
                              $showhidden.':'.$caller.':'.&escape($cloner).':'.                               $showhidden.':'.$caller.':'.&escape($cloner).':'.
                              &escape($cc_clone).':'.$cloneonly.':'.                               &escape($cc_clone).':'.$cloneonly.':'.
                              &escape($createdbefore).':'.&escape($createdafter).':'.                               &escape($createdbefore).':'.&escape($createdafter).':'.
                              &escape($creationcontext).':'.$domcloner,                               &escape($creationcontext).':'.$domcloner.':'.$hasuniquecode,
                              $tryserver);                               $tryserver);
                 }                  }
   
Line 4277  my $cachedkey=''; Line 4445  my $cachedkey='';
 # The cached times for this user  # The cached times for this user
 my %cachedtimes=();  my %cachedtimes=();
 # When this was last done  # When this was last done
 my $cachedtime=();  my $cachedtime='';
   
 sub load_all_first_access {  sub load_all_first_access {
     my ($uname,$udom)=@_;      my ($uname,$udom)=@_;
Line 4339  sub set_first_access { Line 4507  sub set_first_access {
     return 'already_set';      return 'already_set';
 }  }
 }  }
   
   sub checkout {
       my ($symb,$tuname,$tudom,$tcrsid)=@_;
       my $now=time;
       my $lonhost=$perlvar{'lonHostID'};
       my $infostr=&escape(
                    'CHECKOUTTOKEN&'.
                    $tuname.'&'.
                    $tudom.'&'.
                    $tcrsid.'&'.
                    $symb.'&'.
                    $now.'&'.$ENV{'REMOTE_ADDR'});
       my $token=&reply('tmpput:'.$infostr,$lonhost);
       if ($token=~/^error\:/) {
           &logthis("<font color=\"blue\">WARNING: ".
                   "Checkout tmpput failed ".$tudom.' - '.$tuname.' - '.$symb.
                    "</font>");
           return '';
       }
   
       $token=~s/^(\d+)\_.*\_(\d+)$/$1\*$2\*$lonhost/;
       $token=~tr/a-z/A-Z/;
   
       my %infohash=('resource.0.outtoken' => $token,
                     'resource.0.checkouttime' => $now,
                     'resource.0.outremote' => $ENV{'REMOTE_ADDR'});
   
       unless (&cstore(\%infohash,$symb,$tcrsid,$tudom,$tuname) eq 'ok') {
          return '';
       } else {
           &logthis("<font color=\"blue\">WARNING: ".
                   "Checkout cstore failed ".$tudom.' - '.$tuname.' - '.$symb.
                    "</font>");
       }
   
       if (&log($tudom,$tuname,&homeserver($tuname,$tudom),
                            &escape('Checkout '.$infostr.' - '.
                                                    $token)) ne 'ok') {
           return '';
       } else {
           &logthis("<font color=\"blue\">WARNING: ".
                   "Checkout log failed ".$tudom.' - '.$tuname.' - '.$symb.
                    "</font>");
       }
       return $token;
   }
   
   # ------------------------------------------------------------ Check in an item
   
   sub checkin {
       my $token=shift;
       my $now=time;
       my ($ta,$tb,$lonhost)=split(/\*/,$token);
       $lonhost=~tr/A-Z/a-z/;
       my $dtoken=$ta.'_'.&hostname($lonhost).'_'.$tb;
       $dtoken=~s/\W/\_/g;
       my ($dummy,$tuname,$tudom,$tcrsid,$symb,$chtim,$rmaddr)=
                    split(/\&/,&unescape(&reply('tmpget:'.$dtoken,$lonhost)));
   
       unless (($tuname) && ($tudom)) {
           &logthis('Check in '.$token.' ('.$dtoken.') failed');
           return '';
       }
   
       unless (&allowed('mgr',$tcrsid)) {
           &logthis('Check in '.$token.' ('.$dtoken.') unauthorized: '.
                    $env{'user.name'}.' - '.$env{'user.domain'});
           return '';
       }
   
       my %infohash=('resource.0.intoken' => $token,
                     'resource.0.checkintime' => $now,
                     'resource.0.inremote' => $ENV{'REMOTE_ADDR'});
   
       unless (&cstore(\%infohash,$symb,$tcrsid,$tudom,$tuname) eq 'ok') {
          return '';
       }
   
       if (&log($tudom,$tuname,&homeserver($tuname,$tudom),
                            &escape('Checkin - '.$token)) ne 'ok') {
           return '';
       }
   
       return ($symb,$tuname,$tudom,$tcrsid);
   }
   
 # --------------------------------------------- Set Expire Date for Spreadsheet  # --------------------------------------------- Set Expire Date for Spreadsheet
   
 sub expirespread {  sub expirespread {
Line 4709  sub tmprestore { Line 4963  sub tmprestore {
 # ----------------------------------------------------------------------- Store  # ----------------------------------------------------------------------- Store
   
 sub store {  sub store {
     my ($storehash,$symb,$namespace,$domain,$stuname) = @_;      my ($storehash,$symb,$namespace,$domain,$stuname,$laststore) = @_;
     my $home='';      my $home='';
   
     if ($stuname) { $home=&homeserver($stuname,$domain); }      if ($stuname) { $home=&homeserver($stuname,$domain); }
Line 4739  sub store { Line 4993  sub store {
     }      }
     $namevalue=~s/\&$//;      $namevalue=~s/\&$//;
     &courselog($symb.':'.$stuname.':'.$domain.':STORE:'.$namevalue);      &courselog($symb.':'.$stuname.':'.$domain.':STORE:'.$namevalue);
     return reply("store:$domain:$stuname:$namespace:$symb:$namevalue","$home");      return reply("store:$domain:$stuname:$namespace:$symb:$namevalue:$laststore","$home");
 }  }
   
 # -------------------------------------------------------------- Critical Store  # -------------------------------------------------------------- Critical Store
   
 sub cstore {  sub cstore {
     my ($storehash,$symb,$namespace,$domain,$stuname) = @_;      my ($storehash,$symb,$namespace,$domain,$stuname,$laststore) = @_;
     my $home='';      my $home='';
   
     if ($stuname) { $home=&homeserver($stuname,$domain); }      if ($stuname) { $home=&homeserver($stuname,$domain); }
Line 4776  sub cstore { Line 5030  sub cstore {
     $namevalue=~s/\&$//;      $namevalue=~s/\&$//;
     &courselog($symb.':'.$stuname.':'.$domain.':CSTORE:'.$namevalue);      &courselog($symb.':'.$stuname.':'.$domain.':CSTORE:'.$namevalue);
     return critical      return critical
                 ("store:$domain:$stuname:$namespace:$symb:$namevalue","$home");                  ("store:$domain:$stuname:$namespace:$symb:$namevalue:$laststore","$home");
 }  }
   
 # --------------------------------------------------------------------- Restore  # --------------------------------------------------------------------- Restore
Line 4956  sub privileged { Line 5210  sub privileged {
         my %rolesdump = &dump("roles", $domain, $username) or return 0;          my %rolesdump = &dump("roles", $domain, $username) or return 0;
         my $now = time;          my $now = time;
   
         for my $role (@rolesdump{grep { ! /^rolesdef_/ } keys %rolesdump}) {          for my $role (@rolesdump{grep { ! /^rolesdef_/ } keys(%rolesdump)}) {
             my ($trole, $tend, $tstart) = split(/_/, $role);              my ($trole, $tend, $tstart) = split(/_/, $role);
             if (grep(/^\Q$trole\E$/,@{$roles})) {              if (grep(/^\Q$trole\E$/,@{$roles})) {
                 return 1 unless ($tend && $tend < $now)                  return 1 unless ($tend && $tend < $now)
Line 5045  sub rolesinit { Line 5299  sub rolesinit {
     my %allroles=();      my %allroles=();
     my %allgroups=();      my %allgroups=();
   
     for my $area (grep { ! /^rolesdef_/ } keys %rolesdump) {      for my $area (grep { ! /^rolesdef_/ } keys(%rolesdump)) {
         my $role = $rolesdump{$area};          my $role = $rolesdump{$area};
         $area =~ s/\_\w\w$//;          $area =~ s/\_\w\w$//;
   
Line 5137  sub set_arearole { Line 5391  sub set_arearole {
 sub custom_roleprivs {  sub custom_roleprivs {
     my ($allroles,$trole,$tdomain,$trest,$spec,$area) = @_;      my ($allroles,$trole,$tdomain,$trest,$spec,$area) = @_;
     my ($rdummy,$rdomain,$rauthor,$rrole)=split(/\//,$trole);      my ($rdummy,$rdomain,$rauthor,$rrole)=split(/\//,$trole);
     my $homsvr=homeserver($rauthor,$rdomain);      my $homsvr = &homeserver($rauthor,$rdomain);
     if (&hostname($homsvr) ne '') {      if (&hostname($homsvr) ne '') {
         my ($rdummy,$roledef)=          my ($rdummy,$roledef)=
             &get('roles',["rolesdef_$rrole"],$rdomain,$rauthor);              &get('roles',["rolesdef_$rrole"],$rdomain,$rauthor);
Line 5258  sub set_userprivs { Line 5512  sub set_userprivs {
   
 sub role_status {  sub role_status {
     my ($rolekey,$update,$refresh,$now,$role,$where,$trolecode,$tstatus,$tstart,$tend) = @_;      my ($rolekey,$update,$refresh,$now,$role,$where,$trolecode,$tstatus,$tstart,$tend) = @_;
     my @pwhere = ();  
     if (exists($env{$rolekey}) && $env{$rolekey} ne '') {      if (exists($env{$rolekey}) && $env{$rolekey} ne '') {
         (undef,undef,$$role,@pwhere)=split(/\./,$rolekey);          my ($one,$two) = split(m{\./},$rolekey,2);
           (undef,undef,$$role) = split(/\./,$one,3);
         unless (!defined($$role) || $$role eq '') {          unless (!defined($$role) || $$role eq '') {
             $$where=join('.',@pwhere);              $$where = '/'.$two;
             $$trolecode=$$role.'.'.$$where;              $$trolecode=$$role.'.'.$$where;
             ($$tstart,$$tend)=split(/\./,$env{$rolekey});              ($$tstart,$$tend)=split(/\./,$env{$rolekey});
             $$tstatus='is';              $$tstatus='is';
Line 5485  sub dump { Line 5739  sub dump {
     if (!$uname) { $uname=$env{'user.name'}; }      if (!$uname) { $uname=$env{'user.name'}; }
     my $uhome=&homeserver($uname,$udomain);      my $uhome=&homeserver($uname,$udomain);
   
     my $reply;      if ($regexp) {
           $regexp=&escape($regexp);
       } else {
           $regexp='.';
       }
     if (grep { $_ eq $uhome } &current_machine_ids()) {      if (grep { $_ eq $uhome } &current_machine_ids()) {
         # user is hosted on this machine          # user is hosted on this machine
         $reply = LONCAPA::Lond::dump_with_regexp(join(':', ($udomain,          my $reply = LONCAPA::Lond::dump_with_regexp(join(':', ($udomain,
                     $uname, $namespace, $regexp, $range)), $perlvar{'lonVersion'});                      $uname, $namespace, $regexp, $range)), $perlvar{'lonVersion'});
         return %{&unserialize($reply, $escapedkeys)};          return %{&unserialize($reply, $escapedkeys)};
     }      }
     if ($regexp) {  
  $regexp=&escape($regexp);  
     } else {  
  $regexp='.';  
     }  
     my $rep=&reply("dump:$udomain:$uname:$namespace:$regexp:$range",$uhome);      my $rep=&reply("dump:$udomain:$uname:$namespace:$regexp:$range",$uhome);
     my @pairs=split(/\&/,$rep);      my @pairs=split(/\&/,$rep);
     my %returnhash=();      my %returnhash=();
Line 5544  sub currentdump { Line 5797  sub currentdump {
    $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;
   
      if (grep { $_ eq $uhome } current_machine_ids()) {
          $rep = LONCAPA::Lond::dump_profile_database(join(":", ($sdom, $sname,
                      $courseid)));
      } else {
          $rep = reply('currentdump:'.$sdom.':'.$sname.':'.$courseid,$uhome);
      }
   
    return if ($rep =~ /^(error:|no_such_host)/);     return if ($rep =~ /^(error:|no_such_host)/);
    #     #
    my %returnhash=();     my %returnhash=();
Line 5665  sub newput { Line 5926  sub newput {
 # ---------------------------------------------------------  putstore interface  # ---------------------------------------------------------  putstore interface
   
 sub putstore {  sub putstore {
    my ($namespace,$symb,$version,$storehash,$udomain,$uname)=@_;     my ($namespace,$symb,$version,$storehash,$udomain,$uname,$tolog)=@_;
    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);
Line 5679  sub putstore { Line 5940  sub putstore {
    my $reply =     my $reply =
        &reply("putstore:$udomain:$uname:$namespace:$esc_symb:$esc_v:$items",         &reply("putstore:$udomain:$uname:$namespace:$esc_symb:$esc_v:$items",
       $uhome);        $uhome);
      if (($tolog) && ($reply eq 'ok')) {
          my $namevalue='';
          foreach my $key (keys(%{$storehash})) {
              $namevalue.=&escape($key).'='.&freeze_escape($storehash->{$key}).'&';
          }
          $namevalue .= 'ip='.&escape($ENV{'REMOTE_ADDR'}).
                        '&host='.&escape($perlvar{'lonHostID'}).
                        '&version='.$esc_v.
                        '&by='.&escape($env{'user.name'}.':'.$env{'user.domain'});
          &Apache::lonnet::courselog($symb.':'.$uname.':'.$udomain.':PUTSTORE:'.$namevalue);
      }
    if ($reply eq 'unknown_cmd') {     if ($reply eq 'unknown_cmd') {
        # gfall back to way things use to be done         # gfall back to way things use to be done
        return &old_putstore($namespace,$symb,$version,$storehash,$udomain,         return &old_putstore($namespace,$symb,$version,$storehash,$udomain,
Line 5837  sub get_timebased_id { Line 6109  sub get_timebased_id {
         my %inuse = &Apache::lonnet::dump('nohist_'.$namespace,$cdom,$cnum,$prefix);          my %inuse = &Apache::lonnet::dump('nohist_'.$namespace,$cdom,$cnum,$prefix);
         my $id = time;          my $id = time;
         $newid = $id;          $newid = $id;
           if ($idtype eq 'addcode') {
               $newid .= &sixnum_code();
           }
         my $idtries = 0;          my $idtries = 0;
         while (exists($inuse{$prefix."\0".$newid}) && $idtries < $maxtries) {          while (exists($inuse{$prefix."\0".$newid}) && $idtries < $maxtries) {
             if ($idtype eq 'concat') {              if ($idtype eq 'concat') {
                 $newid = $id.$idtries;                  $newid = $id.$idtries;
               } elsif ($idtype eq 'addcode') {
                   $newid = $newid.&sixnum_code();
             } else {              } else {
                 $newid ++;                  $newid ++;
             }              }
Line 5857  sub get_timebased_id { Line 6134  sub get_timebased_id {
                 $error = 'error saving new item: '.$putresult;                  $error = 'error saving new item: '.$putresult;
             }              }
         } else {          } else {
                undef($newid);
              $error = ('error: no unique suffix available for the new item ');               $error = ('error: no unique suffix available for the new item ');
         }          }
 #  remove lock  #  remove lock
Line 5865  sub get_timebased_id { Line 6143  sub get_timebased_id {
     } else {      } else {
         $error = "error: could not obtain lockfile\n";          $error = "error: could not obtain lockfile\n";
         $dellock = 'ok';          $dellock = 'ok';
           if (($prefix eq 'paste') && ($namespace eq 'courseeditor') && ($keyid eq 'num')) {
               $dellock = 'nolock';
           }
     }      }
     return ($newid,$dellock,$error);      return ($newid,$dellock,$error);
 }  }
   
   sub sixnum_code {
       my $code;
       for (0..6) {
           $code .= int( rand(9) );
       }
       return $code;
   }
   
 # -------------------------------------------------- portfolio access checking  # -------------------------------------------------- portfolio access checking
   
 sub portfolio_access {  sub portfolio_access {
Line 6123  sub usertools_access { Line 6412  sub usertools_access {
                       official   => 1,                        official   => 1,
                       unofficial => 1,                        unofficial => 1,
                       community  => 1,                        community  => 1,
                         textbook   => 1,
                  );                   );
     } elsif ($context eq 'requestauthor') {      } elsif ($context eq 'requestauthor') {
         %tools = (          %tools = (
Line 6138  sub usertools_access { Line 6428  sub usertools_access {
     }      }
     return if (!defined($tools{$tool}));      return if (!defined($tools{$tool}));
   
     if ((!defined($udom)) || (!defined($uname))) {      if (($udom eq '') || ($uname eq '')) {
         $udom = $env{'user.domain'};          $udom = $env{'user.domain'};
         $uname = $env{'user.name'};          $uname = $env{'user.name'};
     }      }
Line 6419  sub customaccess { Line 6709  sub customaccess {
 # ------------------------------------------------- Check for a user privilege  # ------------------------------------------------- Check for a user privilege
   
 sub allowed {  sub allowed {
     my ($priv,$uri,$symb,$role)=@_;      my ($priv,$uri,$symb,$role,$clientip,$noblockcheck)=@_;
     my $ver_orguri=$uri;      my $ver_orguri=$uri;
     $uri=&deversion($uri);      $uri=&deversion($uri);
     my $orguri=$uri;      my $orguri=$uri;
Line 6614  sub allowed { Line 6904  sub allowed {
         if ($match) {          if ($match) {
             if ($env{'user.priv.'.$env{'request.role'}.'./'}              if ($env{'user.priv.'.$env{'request.role'}.'./'}
                   =~/\Q$priv\E\&([^\:]*)/) {                    =~/\Q$priv\E\&([^\:]*)/) {
                 my @blockers = &has_comm_blocking($priv,$symb,$uri);                  my $value = $1;
                 if (@blockers > 0) {                  if ($noblockcheck) {
                     $thisallowed = 'B';                      $thisallowed.=$value;
                 } else {                  } else {
                     $thisallowed.=$1;                      my @blockers = &has_comm_blocking($priv,$symb,$uri);
                       if (@blockers > 0) {
                           $thisallowed = 'B';
                       } else {
                           $thisallowed.=$value;
                       }
                 }                  }
             }              }
         } else {          } else {
Line 6630  sub allowed { Line 6925  sub allowed {
                     $refuri=&declutter($refuri);                      $refuri=&declutter($refuri);
                     my ($match) = &is_on_map($refuri);                      my ($match) = &is_on_map($refuri);
                     if ($match) {                      if ($match) {
                         my @blockers = &has_comm_blocking($priv,$symb,$refuri);                          if ($noblockcheck) {
                         if (@blockers > 0) {  
                             $thisallowed = 'B';  
                         } else {  
                             $thisallowed='F';                              $thisallowed='F';
                           } else {
                               my @blockers = &has_comm_blocking($priv,$symb,$refuri);
                               if (@blockers > 0) {
                                   $thisallowed = 'B';
                               } else {
                                   $thisallowed='F';
                               }
                         }                          }
                     }                      }
                 }                  }
Line 6689  sub allowed { Line 6988  sub allowed {
                =~/\Q$priv\E\&([^\:]*)/) {                 =~/\Q$priv\E\&([^\:]*)/) {
                my $value = $1;                 my $value = $1;
                if ($priv eq 'bre') {                 if ($priv eq 'bre') {
                    my @blockers = &has_comm_blocking($priv,$symb,$uri);                     if ($noblockcheck) {
                    if (@blockers > 0) {  
                        $thisallowed = 'B';  
                    } else {  
                        $thisallowed.=$value;                         $thisallowed.=$value;
                      } else {
                          my @blockers = &has_comm_blocking($priv,$symb,$uri);
                          if (@blockers > 0) {
                              $thisallowed = 'B';
                          } else {
                              $thisallowed.=$value;
                          }
                    }                     }
                } else {                 } else {
                    $thisallowed.=$value;                     $thisallowed.=$value;
Line 6727  sub allowed { Line 7030  sub allowed {
                   =~/\Q$priv\E\&([^\:]*)/) {                    =~/\Q$priv\E\&([^\:]*)/) {
                   my $value = $1;                    my $value = $1;
                   if ($priv eq 'bre') {                    if ($priv eq 'bre') {
                       my @blockers = &has_comm_blocking($priv,$symb,$refuri);                        if ($noblockcheck) {
                       if (@blockers > 0) {  
                           $thisallowed = 'B';  
                       } else {  
                           $thisallowed.=$value;                            $thisallowed.=$value;
                         } else {
                             my @blockers = &has_comm_blocking($priv,$symb,$refuri);
                             if (@blockers > 0) {
                                 $thisallowed = 'B';
                             } else {
                                 $thisallowed.=$value;
                             }
                       }                        }
                   } else {                    } else {
                       $thisallowed.=$value;                        $thisallowed.=$value;
Line 6962  sub constructaccess { Line 7269  sub constructaccess {
     return '';      return '';
 }  }
   
   # ----------------------------------------------------------- Content Blocking
   
   {
   # Caches for faster Course Contents display where content blocking
   # is in operation (i.e., interval param set) for timed quiz.
   #
   # User for whom data are being temporarily cached.
   my $cacheduser='';
   # Cached blockers for this user (a hash of blocking items).
   my %cachedblockers=();
   # When the data were last cached.
   my $cachedlast='';
   
   sub load_all_blockers {
       my ($uname,$udom,$blocks)=@_;
       if (($uname ne '') && ($udom ne '')) {
           if (($cacheduser eq $uname.':'.$udom) &&
               (abs($cachedlast-time)<5)) {
               return;
           }
       }
       $cachedlast=time;
       $cacheduser=$uname.':'.$udom;
       %cachedblockers = &get_commblock_resources($blocks);
   }
   
 sub get_comm_blocks {  sub get_comm_blocks {
     my ($cdom,$cnum) = @_;      my ($cdom,$cnum) = @_;
     if ($cdom eq '' || $cnum eq '') {      if ($cdom eq '' || $cnum eq '') {
Line 6982  sub get_comm_blocks { Line 7315  sub get_comm_blocks {
     return %commblocks;      return %commblocks;
 }  }
   
 sub has_comm_blocking {  sub get_commblock_resources {
     my ($priv,$symb,$uri,$blocks) = @_;      my ($blocks) = @_;
     return unless ($env{'request.course.id'});      my %blockers = ();
     return unless ($priv eq 'bre');      return %blockers unless ($env{'request.course.id'});
     return if ($env{'user.priv.'.$env{'request.role'}} =~/evb\&([^\:]*)/);      return %blockers if ($env{'user.priv.'.$env{'request.role'}} =~/evb\&([^\:]*)/);
     my %commblocks;      my %commblocks;
     if (ref($blocks) eq 'HASH') {      if (ref($blocks) eq 'HASH') {
         %commblocks = %{$blocks};          %commblocks = %{$blocks};
     } else {      } else {
         %commblocks = &get_comm_blocks();          %commblocks = &get_comm_blocks();
     }      }
     return unless (keys(%commblocks) > 0);      return %blockers unless (keys(%commblocks) > 0);
     if (!$symb) { $symb=&symbread($uri,1); }  
     my ($map,$resid,undef)=&decode_symb($symb);  
     my %tocheck = (  
                     maps      => $map,  
                     resources => $symb,  
                   );  
     my @blockers;  
     my $now = time;  
     my $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
       return %blockers unless (ref($navmap));
       my $now = time;
     foreach my $block (keys(%commblocks)) {      foreach my $block (keys(%commblocks)) {
         if ($block =~ /^(\d+)____(\d+)$/) {          if ($block =~ /^(\d+)____(\d+)$/) {
             my ($start,$end) = ($1,$2);              my ($start,$end) = ($1,$2);
Line 7010  sub has_comm_blocking { Line 7337  sub has_comm_blocking {
                 if (ref($commblocks{$block}{'blocks'}) eq 'HASH') {                  if (ref($commblocks{$block}{'blocks'}) eq 'HASH') {
                     if (ref($commblocks{$block}{'blocks'}{'docs'}) eq 'HASH') {                      if (ref($commblocks{$block}{'blocks'}{'docs'}) eq 'HASH') {
                         if (ref($commblocks{$block}{'blocks'}{'docs'}{'maps'}) eq 'HASH') {                          if (ref($commblocks{$block}{'blocks'}{'docs'}{'maps'}) eq 'HASH') {
                             if ($commblocks{$block}{'blocks'}{'docs'}{'maps'}{$map}) {                              if (keys(%{$commblocks{$block}{'blocks'}{'docs'}{'maps'}})) {
                                 unless (grep(/^\Q$block\E$/,@blockers)) {                                  $blockers{$block}{maps} = $commblocks{$block}{'blocks'}{'docs'}{'maps'};
                                     push(@blockers,$block);  
                                 }  
                             }                              }
                         }                          }
                         if (ref($commblocks{$block}{'blocks'}{'docs'}{'resources'}) eq 'HASH') {                          if (ref($commblocks{$block}{'blocks'}{'docs'}{'resources'}) eq 'HASH') {
                             if ($commblocks{$block}{'blocks'}{'docs'}{'resources'}{$symb}) {                              if (keys(%{$commblocks{$block}{'blocks'}{'docs'}{'resources'}})) {
                                 unless (grep(/^\Q$block\E$/,@blockers)) {                                    $blockers{$block}{'resources'} = $commblocks{$block}{'blocks'}{'docs'}{'resources'};
                                     push(@blockers,$block);  
                                 }  
                             }                              }
                         }                          }
                     }                      }
Line 7031  sub has_comm_blocking { Line 7354  sub has_comm_blocking {
             my @to_test;              my @to_test;
             if (ref($commblocks{$block}{'blocks'}) eq 'HASH') {              if (ref($commblocks{$block}{'blocks'}) eq 'HASH') {
                 if (ref($commblocks{$block}{'blocks'}{'docs'}) eq 'HASH') {                  if (ref($commblocks{$block}{'blocks'}{'docs'}) eq 'HASH') {
                     my $check_interval;                      my @interval;
                     if (&check_docs_block($commblocks{$block}{'blocks'}{'docs'},\%tocheck)) {                      my $type = 'map';
                         my @interval;                      if ($item eq 'course') {
                         my $type = 'map';                          $type = 'course';
                         if ($item eq 'course') {                          @interval=&EXT("resource.0.interval");
                             $type = 'course';                      } else {
                             @interval=&EXT("resource.0.interval");                          if ($item =~ /___\d+___/) {
                               $type = 'resource';
                               @interval=&EXT("resource.0.interval",$item);
                               if (ref($navmap)) {
                                   my $res = $navmap->getBySymb($item);
                                   push(@to_test,$res);
                               }
                         } else {                          } else {
                             if ($item =~ /___\d+___/) {                              my $mapsymb = &symbread($item,1);
                                 $type = 'resource';                              if ($mapsymb) {
                                 @interval=&EXT("resource.0.interval",$item);                                  if (ref($navmap)) {
                                 if (ref($navmap)) {                                                              my $mapres = $navmap->getBySymb($mapsymb);
                                     my $res = $navmap->getBySymb($item);                                       @to_test = $mapres->retrieveResources($mapres,undef,0,0,0,1);
                                     push(@to_test,$res);                                      foreach my $res (@to_test) {
                                 }                                          my $symb = $res->symb();
                             } else {                                          next if ($symb eq $mapsymb);
                                 my $mapsymb = &symbread($item,1);                                          if ($symb ne '') {
                                 if ($mapsymb) {                                              @interval=&EXT("resource.0.interval",$symb);
                                     if (ref($navmap)) {                                              if ($interval[1] eq 'map') {
                                         my $mapres = $navmap->getBySymb($mapsymb);  
                                         @to_test = $mapres->retrieveResources($mapres,undef,0,1);  
                                         foreach my $res (@to_test) {  
                                             my $symb = $res->symb();  
                                             next if ($symb eq $mapsymb);  
                                             if ($symb ne '') {  
                                                 @interval=&EXT("resource.0.interval",$symb);  
                                                 last;                                                  last;
                                             }                                              }
                                         }                                          }
Line 7064  sub has_comm_blocking { Line 7386  sub has_comm_blocking {
                                 }                                  }
                             }                              }
                         }                          }
                         if ($interval[0] =~ /\d+/) {                      }
                             my $first_access;                      if ($interval[0] =~ /^\d+$/) {
                             if ($type eq 'resource') {                          my $first_access;
                                 $first_access=&get_first_access($interval[1],$item);                          if ($type eq 'resource') {
                             } elsif ($type eq 'map') {                              $first_access=&get_first_access($interval[1],$item);
                                 $first_access=&get_first_access($interval[1],undef,$item);                          } elsif ($type eq 'map') {
                             } else {                              $first_access=&get_first_access($interval[1],undef,$item);
                                 $first_access=&get_first_access($interval[1]);                          } else {
                             }                              $first_access=&get_first_access($interval[1]);
                             if ($first_access) {                          }
                                 my $timesup = $first_access+$interval[0];                          if ($first_access) {
                                 if ($timesup > $now) {                              my $timesup = $first_access+$interval[0];
                                     foreach my $res (@to_test) {                              if ($timesup > $now) {
                                         if ($res->is_problem()) {                                  my $activeblock;
                                             if ($res->completable()) {                                  foreach my $res (@to_test) {
                                                 unless (grep(/^\Q$block\E$/,@blockers)) {                                      if ($res->answerable()) {
                                                     push(@blockers,$block);                                          $activeblock = 1;
                                                 }                                          last;
                                                 last;                                      }
                                             }                                  }
                                   if ($activeblock) {
                                       if (ref($commblocks{$block}{'blocks'}{'docs'}{'maps'}) eq 'HASH') {
                                            if (keys(%{$commblocks{$block}{'blocks'}{'docs'}{'maps'}})) {
                                                $blockers{$block}{'maps'} = $commblocks{$block}{'blocks'}{'docs'}{'maps'};
                                            }
                                       }
                                       if (ref($commblocks{$block}{'blocks'}{'docs'}{'resources'}) eq 'HASH') {
                                           if (keys(%{$commblocks{$block}{'blocks'}{'docs'}{'resources'}})) {
                                               $blockers{$block}{'resources'} = $commblocks{$block}{'blocks'}{'docs'}{'resources'};
                                         }                                          }
                                     }                                      }
                                 }                                  }
Line 7094  sub has_comm_blocking { Line 7425  sub has_comm_blocking {
             }              }
         }          }
     }      }
     return @blockers;      return %blockers;
 }  }
   
 sub check_docs_block {  sub has_comm_blocking {
     my ($docsblock,$tocheck) =@_;      my ($priv,$symb,$uri,$blocks) = @_;
     if ((ref($docsblock) ne 'HASH') || (ref($tocheck) ne 'HASH')) {      my @blockers;
         return;      return unless ($env{'request.course.id'});
       return unless ($priv eq 'bre');
       return if ($env{'user.priv.'.$env{'request.role'}} =~/evb\&([^\:]*)/);
       return if ($env{'request.state'} eq 'construct');
       &load_all_blockers($env{'user.name'},$env{'user.domain'},$blocks);
       return unless (keys(%cachedblockers) > 0);
       my (%possibles,@symbs);
       if (!$symb) {
           $symb = &symbread($uri,1,1,1,\%possibles);
     }      }
     if (ref($docsblock->{'maps'}) eq 'HASH') {      if ($symb) {
         if ($tocheck->{'maps'}) {          @symbs = ($symb);
             if ($docsblock->{'maps'}{$tocheck->{'maps'}}) {      } elsif (keys(%possibles)) {
                 return 1;          @symbs = keys(%possibles);
       }
       my $noblock;
       foreach my $symb (@symbs) {
           last if ($noblock);
           my ($map,$resid,$resurl)=&decode_symb($symb);
           foreach my $block (keys(%cachedblockers)) {
               if ($block =~ /^firstaccess____(.+)$/) {
                   my $item = $1;
                   if (($item eq $map) || ($item eq $symb)) {
                       $noblock = 1;
                       last;
                   }
             }              }
         }              if (ref($cachedblockers{$block}) eq 'HASH') {
     }                  if (ref($cachedblockers{$block}{'resources'}) eq 'HASH') {
     if (ref($docsblock->{'resources'}) eq 'HASH') {                      if ($cachedblockers{$block}{'resources'}{$symb}) {
         if ($tocheck->{'resources'}) {                          unless (grep(/^\Q$block\E$/,@blockers)) {
             if ($docsblock->{'resources'}{$tocheck->{'resources'}}) {                              push(@blockers,$block);
                 return 1;                          }
                       }
                   }
               }
               if (ref($cachedblockers{$block}{'maps'}) eq 'HASH') {
                   if ($cachedblockers{$block}{'maps'}{$map}) {
                       unless (grep(/^\Q$block\E$/,@blockers)) {
                           push(@blockers,$block);
                       }
                   }
             }              }
         }          }
     }      }
     return;      return if ($noblock);
       return @blockers;
   }
 }  }
   
   # -------------------------------- Deversion and split uri into path an filename
   
 #  #
 #   Removes the versino from a URI and  #   Removes the version from a URI and
 #   splits it in to its filename and path to the filename.  #   splits it in to its filename and path to the filename.
 #   Seems like File::Basename could have done this more clearly.  #   Seems like File::Basename could have done this more clearly.
 #   Parameters:  #   Parameters:
Line 7229  sub definerole { Line 7593  sub definerole {
 # ---------------- Make a metadata query against the network of library servers  # ---------------- Make a metadata query against the network of library servers
   
 sub metadata_query {  sub metadata_query {
     my ($query,$custom,$customshow,$server_array)=@_;      my ($query,$custom,$customshow,$server_array,$domains_hash)=@_;
     my %rhash;      my %rhash;
     my %libserv = &all_library();      my %libserv = &all_library();
     my @server_list = (defined($server_array) ? @$server_array      my @server_list = (defined($server_array) ? @$server_array
                                               : keys(%libserv) );                                                : keys(%libserv) );
     for my $server (@server_list) {      for my $server (@server_list) {
           my $domains = '';
           if (ref($domains_hash) eq 'HASH') {
               $domains = $domains_hash->{$server};    
           }
  unless ($custom or $customshow) {   unless ($custom or $customshow) {
     my $reply=&reply("querysend:".&escape($query),$server);      my $reply=&reply("querysend:".&escape($query).':::'.&escape($domains),$server);
     $rhash{$server}=$reply;      $rhash{$server}=$reply;
  }   }
  else {   else {
     my $reply=&reply("querysend:".&escape($query).':'.      my $reply=&reply("querysend:".&escape($query).':'.
      &escape($custom).':'.&escape($customshow),       &escape($custom).':'.&escape($customshow).':'.&escape($domains),
      $server);       $server);
     $rhash{$server}=$reply;      $rhash{$server}=$reply;
  }   }
Line 7730  sub auto_courserequest_checks { Line 8098  sub auto_courserequest_checks {
 }  }
   
 sub auto_courserequest_validation {  sub auto_courserequest_validation {
     my ($dom,$owner,$crstype,$inststatuslist,$instcode,$instseclist) = @_;      my ($dom,$owner,$crstype,$inststatuslist,$instcode,$instseclist,$custominfo) = @_;
     my ($homeserver,$response);      my ($homeserver,$response);
     if ($dom =~ /^$match_domain$/) {      if ($dom =~ /^$match_domain$/) {
         $homeserver = &domain($dom,'primary');          $homeserver = &domain($dom,'primary');
     }      }
     unless ($homeserver eq 'no_host') {        unless ($homeserver eq 'no_host') {
                     my $customdata;
           if (ref($custominfo) eq 'HASH') {
               $customdata = &freeze_escape($custominfo);
           }
         $response=&unescape(&reply('autocrsreqvalidation:'.$dom.':'.&escape($owner).          $response=&unescape(&reply('autocrsreqvalidation:'.$dom.':'.&escape($owner).
                                     ':'.&escape($crstype).':'.&escape($inststatuslist).                                      ':'.&escape($crstype).':'.&escape($inststatuslist).
                                     ':'.&escape($instcode).':'.&escape($instseclist),                                      ':'.&escape($instcode).':'.&escape($instseclist).':'.
                                     $homeserver));                                      $customdata,$homeserver));
     }      }
     return $response;      return $response;
 }  }
Line 7759  sub auto_validate_class_sec { Line 8130  sub auto_validate_class_sec {
     return $response;      return $response;
 }  }
   
   sub auto_crsreq_update {
       my ($cdom,$cnum,$crstype,$action,$ownername,$ownerdomain,$fullname,$title,
           $code,$accessstart,$accessend,$inbound) = @_;
       my ($homeserver,%crsreqresponse);
       if ($cdom =~ /^$match_domain$/) {
           $homeserver = &domain($cdom,'primary');
       }
       unless (($homeserver eq 'no_host') || ($homeserver eq '')) {
           my $info;
           if (ref($inbound) eq 'HASH') {
               $info = &freeze_escape($inbound);
           }
           my $response=&reply('autocrsrequpdate:'.$cdom.':'.$cnum.':'.&escape($crstype).
                               ':'.&escape($action).':'.&escape($ownername).':'.
                               &escape($ownerdomain).':'.&escape($fullname).':'.
                               &escape($title).':'.&escape($code).':'.
                               &escape($accessstart).':'.&escape($accessend).':'.$info,$homeserver);
           unless ($response =~ /(con_lost|error|no_such_host|refused)/) {
               my @items = split(/&/,$response);
               foreach my $item (@items) {
                   my ($key,$value) = split('=',$item);
                   $crsreqresponse{&unescape($key)} = &thaw_unescape($value);
               }
           }
       }
       return \%crsreqresponse;
   }
   
 # ------------------------------------------------------- Course Group routines  # ------------------------------------------------------- Course Group routines
   
 sub get_coursegroups {  sub get_coursegroups {
Line 8440  sub modifystudent { Line 8839  sub modifystudent {
          $desiredhome,$email,$inststatus);           $desiredhome,$email,$inststatus);
     unless ($reply eq 'ok') { return $reply; }      unless ($reply eq 'ok') { return $reply; }
     # This will cause &modify_student_enrollment to get the uid from the      # This will cause &modify_student_enrollment to get the uid from the
     # students environment      # student's environment
     $uid = undef if (!$forceid);      $uid = undef if (!$forceid);
     $reply = &modify_student_enrollment($udom,$uname,$uid,$first,$middle,$last,      $reply = &modify_student_enrollment($udom,$uname,$uid,$first,$middle,$last,
  $gene,$usec,$end,$start,$type,$locktype,   $gene,$usec,$end,$start,$type,$locktype,
Line 9576  sub resdata { Line 9975  sub resdata {
     return undef;      return undef;
 }  }
   
   sub get_numsuppfiles {
       my ($cnum,$cdom,$ignorecache)=@_;
       my $hashid=$cnum.':'.$cdom;
       my ($suppcount,$cached);
       unless ($ignorecache) {
           ($suppcount,$cached) = &is_cached_new('suppcount',$hashid);
       }
       unless (defined($cached)) {
           my $chome=&homeserver($cnum,$cdom);
           unless ($chome eq 'no_host') {
               ($suppcount,my $errors) = (0,0);
               my $suppmap = 'supplemental.sequence';
               ($suppcount,$errors) =
                   &Apache::loncommon::recurse_supplemental($cnum,$cdom,$suppmap,$suppcount,$errors);
           }
           &do_cache_new('suppcount',$hashid,$suppcount,600);
       }
       return $suppcount;
   }
   
 #  #
 # EXT resource caching routines  # EXT resource caching routines
 #  #
Line 9719  sub EXT { Line 10138  sub EXT {
     if (!$symbparm) { $symbparm=&symbread(); }      if (!$symbparm) { $symbparm=&symbread(); }
  }   }
   
  if ($space eq 'title') {          if ($qualifier eq '') {
     if (!$symbparm) { $symbparm = $env{'request.filename'}; }      if ($space eq 'title') {
     return &gettitle($symbparm);          if (!$symbparm) { $symbparm = $env{'request.filename'}; }
  }          return &gettitle($symbparm);
       }
   
  if ($space eq 'map') {      if ($space eq 'map') {
     my ($map) = &decode_symb($symbparm);          my ($map) = &decode_symb($symbparm);
     return &symbread($map);          return &symbread($map);
  }      }
  if ($space eq 'filename') {              if ($space eq 'maptitle') {
     if ($symbparm) {                  my ($map) = &decode_symb($symbparm);
  return &clutter((&decode_symb($symbparm))[2]);                  return &gettitle($map);
               }
       if ($space eq 'filename') {
           if ($symbparm) {
       return &clutter((&decode_symb($symbparm))[2]);
           }
           return &hreflocation('',$env{'request.filename'});
     }      }
     return &hreflocation('',$env{'request.filename'});  
  }              if ((defined($courseid)) && ($courseid eq $env{'request.course.id'}) && $symbparm) {
                   if ($space eq 'visibleparts') {
                       my $navmap = Apache::lonnavmaps::navmap->new();
                       my $item;
                       if (ref($navmap)) {
                           my $res = $navmap->getBySymb($symbparm);
                           my $parts = $res->parts();
                           if (ref($parts) eq 'ARRAY') {
                               $item = join(',',@{$parts});
                           }
                           undef($navmap);
                       }
                       return $item;
                   }
               }
           }
   
  my ($section, $group, @groups);   my ($section, $group, @groups);
  my ($courselevelm,$courselevel);   my ($courselevelm,$courselevel);
Line 9992  sub metadata { Line 10433  sub metadata {
         ($uri =~ m|/$|) || ($uri =~ m|/.meta$|) || ($uri =~ m{^/*uploaded/.+\.sequence$})) {          ($uri =~ m|/$|) || ($uri =~ m|/.meta$|) || ($uri =~ m{^/*uploaded/.+\.sequence$})) {
  return undef;   return undef;
     }      }
     if (($uri =~ /^priv/ || $uri=~/home\/httpd\/html\/priv/)       if (($uri =~ /^priv/ || $uri=~m{^home/httpd/html/priv}) 
  && &Apache::lonxml::get_state('target') =~ /^(|meta)$/) {   && &Apache::lonxml::get_state('target') =~ /^(|meta)$/) {
  return undef;   return undef;
     }      }
Line 10253  sub metadata { Line 10694  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,$cachetime);   &do_cache_new('meta',$uri,\%metaentry,$cachetime);
 # this is the end of "was not already recently cached  # this is the end of "was not already recently cached
     }      }
Line 10624  sub deversion { Line 11065  sub deversion {
 # ------------------------------------------------------ Return symb list entry  # ------------------------------------------------------ Return symb list entry
   
 sub symbread {  sub symbread {
     my ($thisfn,$donotrecurse)=@_;      my ($thisfn,$donotrecurse,$ignorecachednull,$checkforblock,$possibles)=@_;
     my $cache_str;      my $cache_str='request.symbread.cached.'.$thisfn;
     if ($thisfn ne '') {      if (defined($env{$cache_str})) {
         $cache_str='request.symbread.cached.'.$thisfn;          if ($ignorecachednull) {
         if ($env{$cache_str} ne '') {              return $env{$cache_str} unless ($env{$cache_str} eq '');
           } else {
             return $env{$cache_str};              return $env{$cache_str};
         }          }
    } else {      }
 # no filename provided? try from environment  # no filename provided? try from environment
       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'});
         }          }
Line 10692  sub symbread { Line 11135  sub symbread {
      my ($mapid,$resid)=split(/\./,$ids);       my ($mapid,$resid)=split(/\./,$ids);
      $syval=&encode_symb($bighash{'map_id_'.$mapid},       $syval=&encode_symb($bighash{'map_id_'.$mapid},
     $resid,$thisfn);      $resid,$thisfn);
                  } elsif (!$donotrecurse) {                       if (ref($possibles) eq 'HASH') {
                            $possibles->{$syval} = 1;
                        }
                        if ($checkforblock) {
                            my @blockers = &has_comm_blocking('bre',$syval,$bighash{'src_'.$ids});
                            if (@blockers) {
                                $syval = '';
                                return;
                            }
                        }
                    } elsif ((!$donotrecurse) || ($checkforblock) || (ref($possibles) eq 'HASH')) {
 # ------------------------------------------ There is more than one possibility  # ------------------------------------------ There is more than one possibility
                      my $realpossible=0;                       my $realpossible=0;
                      foreach my $id (@possibilities) {                       foreach my $id (@possibilities) {
  my $file=$bighash{'src_'.$id};   my $file=$bighash{'src_'.$id};
                          if (&allowed('bre',$file)) {                           my $canaccess;
              my ($mapid,$resid)=split(/\./,$id);                           if (($donotrecurse) || ($checkforblock) || (ref($possibles) eq 'HASH')) {
                             if ($bighash{'map_type_'.$mapid} ne 'page') {                               $canaccess = 1;
  $realpossible++;                           } else {
                                 $syval=&encode_symb($bighash{'map_id_'.$mapid},                               $canaccess = &allowed('bre',$file);
     $resid,$thisfn);                           }
                             }                           if ($canaccess) {
                 my ($mapid,$resid)=split(/\./,$id);
                                if ($bighash{'map_type_'.$mapid} ne 'page') {
                                    my $poss_syval=&encode_symb($bighash{'map_id_'.$mapid},
                                                                $resid,$thisfn);
                                    if (ref($possibles) eq 'HASH') {
                                        $possibles->{$syval} = 1;
                                    }
                                    if ($checkforblock) {
                                        my @blockers = &has_comm_blocking('bre',$poss_syval,$file);
                                        unless (@blockers > 0) {
                                            $syval = $poss_syval;
                                            $realpossible++;
                                        }
                                    } else {
                                        $syval = $poss_syval;
                                        $realpossible++;
                                    }
                                }
  }   }
                      }                       }
      if ($realpossible!=1) { $syval=''; }       if ($realpossible!=1) { $syval=''; }
Line 10711  sub symbread { Line 11182  sub symbread {
                      $syval='';                       $syval='';
                  }                   }
       }        }
               untie(%bighash)                untie(%bighash);
            }             }
         }          }
         if ($syval) {          if ($syval) {
Line 11049  sub rndseed_CODE_64bit5 { Line 11520  sub rndseed_CODE_64bit5 {
 sub setup_random_from_rndseed {  sub setup_random_from_rndseed {
     my ($rndseed)=@_;      my ($rndseed)=@_;
     if ($rndseed =~/([,:])/) {      if ($rndseed =~/([,:])/) {
  my ($num1,$num2)=split(/[,:]/,$rndseed);   my ($num1,$num2) = map { abs($_); } (split(/[,:]/,$rndseed));
  &Math::Random::random_set_seed(abs($num1),abs($num2));          if ((!$num1) || (!$num2) || ($num1 > 2147483562) || ($num2 > 2147483398)) {
               &Math::Random::random_set_seed_from_phrase($rndseed);
           } else {
               &Math::Random::random_set_seed($num1,$num2);
           }
     } else {      } else {
  &Math::Random::random_set_seed_from_phrase($rndseed);   &Math::Random::random_set_seed_from_phrase($rndseed);
     }      }
Line 11441  sub default_login_domain { Line 11916  sub default_login_domain {
 sub declutter {  sub declutter {
     my $thisfn=shift;      my $thisfn=shift;
     if ($thisfn=~m|^/enc/|) { $thisfn=&Apache::lonenc::unencrypted($thisfn); }      if ($thisfn=~m|^/enc/|) { $thisfn=&Apache::lonenc::unencrypted($thisfn); }
     $thisfn=~s/^\Q$perlvar{'lonDocRoot'}\E//;      unless ($thisfn=~m{^/home/httpd/html/priv/}) {
           $thisfn=~s{^/home/httpd/html}{};
       }
     $thisfn=~s/^\///;      $thisfn=~s/^\///;
     $thisfn=~s|^adm/wrapper/||;      $thisfn=~s|^adm/wrapper/||;
     $thisfn=~s|^adm/coursedocs/showdoc/||;      $thisfn=~s|^adm/coursedocs/showdoc/||;
Line 11568  sub get_dns { Line 12045  sub get_dns {
  $alldns{$host} = $protocol;   $alldns{$host} = $protocol;
     }      }
     while (%alldns) {      while (%alldns) {
  my ($dns) = keys(%alldns);   my ($dns) = sort { $b cmp $a } keys(%alldns);
  my $ua=new LWP::UserAgent;   my $ua=new LWP::UserAgent;
         $ua->timeout(30);          $ua->timeout(30);
  my $request=new HTTP::Request('GET',"$alldns{$dns}://$dns$url");   my $request=new HTTP::Request('GET',"$alldns{$dns}://$dns$url");
Line 11594  sub get_dns { Line 12071  sub get_dns {
 # ------------------------------------------------------Get DNS checksums file  # ------------------------------------------------------Get DNS checksums file
 sub parse_dns_checksums_tab {  sub parse_dns_checksums_tab {
     my ($lines,$hashref) = @_;      my ($lines,$hashref) = @_;
     my $machine_dom = &Apache::lonnet::host_domain($perlvar{'lonHostID'});      my $lonhost = $perlvar{'lonHostID'};
       my $machine_dom = &Apache::lonnet::host_domain($lonhost);
     my $loncaparev = &get_server_loncaparev($machine_dom);      my $loncaparev = &get_server_loncaparev($machine_dom);
       my $distro = (split(/\:/,&get_server_distarch($lonhost)))[0];
       my $webconfdir = '/etc/httpd/conf';
       if ($distro =~ /^(ubuntu|debian)(\d+)$/) {
           $webconfdir = '/etc/apache2';
       } elsif ($distro =~ /^sles(\d+)$/) {
           if ($1 >= 10) {
               $webconfdir = '/etc/apache2';
           }
       } elsif ($distro =~ /^suse(\d+\.\d+)$/) {
           if ($1 >= 10.0) {
               $webconfdir = '/etc/apache2';
           }
       }
     my ($release,$timestamp) = split(/\-/,$loncaparev);      my ($release,$timestamp) = split(/\-/,$loncaparev);
     my (%chksum,%revnum);      my (%chksum,%revnum);
     if (ref($lines) eq 'ARRAY') {      if (ref($lines) eq 'ARRAY') {
         chomp(@{$lines});          chomp(@{$lines});
         my $versions = shift(@{$lines});          my $version = shift(@{$lines});
         my %supported;          if ($version eq $release) {
         if ($versions =~ /^VERSIONS\:([\w\.\,]+)$/) {  
             my $releaseslist = $1;  
             if ($releaseslist =~ /,/) {  
                 map { $supported{$_} = 1; } split(/,/,$releaseslist);  
             } elsif ($releaseslist) {  
                 $supported{$releaseslist} = 1;  
             }  
         }  
         if ($supported{$release}) {  
             my $matchthis = 0;  
             foreach my $line (@{$lines}) {              foreach my $line (@{$lines}) {
                 if ($line =~ /^(\d[\w\.]+)$/) {                  my ($file,$version,$shasum) = split(/,/,$line);
                     if ($matchthis) {                  if ($file =~ m{^/etc/httpd/conf}) {
                         last;                      if ($webconfdir eq '/etc/apache2') {
                     } elsif ($1 eq $release) {                          $file =~ s{^\Q/etc/httpd/conf/\E}{$webconfdir/};
                         $matchthis = 1;  
                     }                      }
                 } elsif ($matchthis) {  
                     my ($file,$version,$shasum) = split(/,/,$line);  
                     $chksum{$file} = $shasum;  
                     $revnum{$file} = $version;  
                 }                  }
                   $chksum{$file} = $shasum;
                   $revnum{$file} = $version;
             }              }
             if (ref($hashref) eq 'HASH') {              if (ref($hashref) eq 'HASH') {
                 %{$hashref} = (                  %{$hashref} = (
Line 11638  sub parse_dns_checksums_tab { Line 12116  sub parse_dns_checksums_tab {
   
 sub fetch_dns_checksums {  sub fetch_dns_checksums {
     my %checksums;      my %checksums;
     &get_dns('/adm/dns/checksums',\&parse_dns_checksums_tab,1,1,      my $machine_dom = &Apache::lonnet::host_domain($perlvar{'lonHostID'});
       my $loncaparev = &get_server_loncaparev($machine_dom,$perlvar{'lonHostID'});
       my ($release,$timestamp) = split(/\-/,$loncaparev);
       &get_dns("/adm/dns/checksums/$release",\&parse_dns_checksums_tab,1,1,
              \%checksums);               \%checksums);
     return \%checksums;      return \%checksums;
 }  }
Line 12016  sub fetch_dns_checksums { Line 12497  sub fetch_dns_checksums {
 }  }
   
 sub all_loncaparevs {  sub all_loncaparevs {
     return qw(1.1 1.2 1.3 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.10);      return qw(1.1 1.2 1.3 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.10 2.11);
 }  }
   
 # ------------------------------------------------------- Read loncaparev table  # ------------------------------------------------------- Read loncaparev table
Line 12194  $readit=1; Line 12675  $readit=1;
  if ($test != 0) { $_64bit=1; } else { $_64bit=0; }   if ($test != 0) { $_64bit=1; } else { $_64bit=0; }
  &logthis(" Detected 64bit platform ($_64bit)");   &logthis(" Detected 64bit platform ($_64bit)");
     }      }
   
     {  
         eval {  
             ($apache) =  
                 (Apache2::ServerUtil::get_server_version() =~ m{Apache/(\d+\.\d+)});  
         };  
         if ($@) {  
            $apache = 1.3;  
         }  
     }  
   
 }  }
 }  }
   
Line 12346  were new keys. I.E. 1:foo will become 1: Line 12816  were new keys. I.E. 1:foo will become 1:
 Calling convention:  Calling convention:
   
  my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$uname);   my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$uname);
  &Apache::lonnet::cstore(\%newrecord,$symb,$courseid,$domain,$uname);   &Apache::lonnet::cstore(\%newrecord,$symb,$courseid,$domain,$uname,$laststore);
   
 For more detailed information, see lonnet specific documentation.  For more detailed information, see lonnet specific documentation.
   
Line 12482  escaped strings of the action recorded i Line 12952  escaped strings of the action recorded i
   
 =item *  =item *
   
 allowed($priv,$uri,$symb,$role) : check for a user privilege; returns codes for allowed actions  allowed($priv,$uri,$symb,$role,$clientip,$noblockcheck) : check for a user privilege; 
   returns codes for allowed actions.
   
   The first argument is required, all others are optional.
   
   $priv is the privilege being checked.
   $uri contains additional information about what is being checked for access (e.g.,
   URL, course ID etc.).
   $symb is the unique resource instance identifier in a course; if needed,
   but not provided, it will be retrieved via a call to &symbread().
   $role is the role for which a priv is being checked (only used if priv is evb).
   $clientip is the user's IP address (only used when checking for access to portfolio
   files).
   $noblockcheck, if true, skips calls to &has_comm_blocking() for the bre priv. This
   prevents recursive calls to &allowed.
   
  F: full access   F: full access
  U,I,K: authentication modes (cxx only)   U,I,K: authentication modes (cxx only)
  '': forbidden   '': forbidden
  1: user needs to choose course   1: user needs to choose course
  2: browse allowed   2: browse allowed
  A: passphrase authentication needed   A: passphrase authentication needed
    B: access temporarily blocked because of a blocking event in a course.
   
 =item *  =item *
   
Line 12613  or when Autoupdate.pl is run by cron in Line 13099  or when Autoupdate.pl is run by cron in
 modifystudent  modifystudent
   
 modify a student's enrollment and identification information.  modify a student's enrollment and identification information.
 The course id is resolved based on the current users environment.    The course id is resolved based on the current user's environment.  
 This means the envoking user must be a course coordinator or otherwise  This means the invoking user must be a course coordinator or otherwise
 associated with a course.  associated with a course.
   
 This call is essentially a wrapper for lonnet::modifyuser and  This call is essentially a wrapper for lonnet::modifyuser and
Line 12674  Inputs: Line 13160  Inputs:
   
 modify_student_enrollment  modify_student_enrollment
   
 Change a students enrollment status in a class.  The environment variable  Change a student's enrollment status in a class.  The environment variable
 'role.request.course' must be defined for this function to proceed.  'role.request.course' must be defined for this function to proceed.
   
 Inputs:  Inputs:
   
 =over 4  =over 4
   
 =item $udom, students domain  =item $udom, student's domain
   
 =item $uname, students name  =item $uname, student's name
   
 =item $uid, students user id  =item $uid, student's user id
   
 =item $first, students first name  =item $first, student's first name
   
 =item $middle  =item $middle
   
Line 12769  If defined, the supplied username is use Line 13255  If defined, the supplied username is use
 resdata($name,$domain,$type,@which) : request for current parameter  resdata($name,$domain,$type,@which) : request for current parameter
 setting for a specific $type, where $type is either 'course' or 'user',  setting for a specific $type, where $type is either 'course' or 'user',
 @what should be a list of parameters to ask about. This routine caches  @what should be a list of parameters to ask about. This routine caches
 answers for 5 minutes.  answers for 10 minutes.
   
 =item *  =item *
   
Line 12778  data base, returning a hash that is keye Line 13264  data base, returning a hash that is keye
 values that are the resource value.  I believe that the timestamps and  values that are the resource value.  I believe that the timestamps and
 versions are also returned.  versions are also returned.
   
   get_numsuppfiles($cnum,$cdom) : retrieve number of files in a course's
   supplemental content area. This routine caches the number of files for
   10 minutes.
   
 =back  =back
   
 =head2 Course Modification  =head2 Course Modification
Line 12878  will be stored for query Line 13368  will be stored for query
   
 =item *  =item *
   
 symbread($filename) : return symbolic list entry (filename argument optional);  symbread($filename,$donotrecurse,$ignorecachednull,$checkforblock,$possibles) :
   return symbolic list entry (all arguments optional).
   
   Args: filename is the filename (including path) for the file for which a symb
   is required; donotrecurse, if true will prevent calls to allowed() being made
   to check access status if more than one resource was found in the bighash
   (see rev. 1.249) to avoid an infinite loop if an ambiguous resource is part of
   a randompick); ignorecachednull, if true will prevent a symb of '' being
   returned if $env{$cache_str} is defined as ''; checkforblock if true will
   cause possible symbs to be checked to determine if they are subject to content
   blocking, if so they will not be included as possible symbs; possibles is a
   ref to a hash, which, as a side effect, will be populated with all possible
   symbs (content blocking not tested).
   
 returns the data handle  returns the data handle
   
 =item *  =item *
Line 12979  homeserver. Line 13482  homeserver.
   
 =item *  =item *
   
 store($storehash,$symb,$namespace,$udom,$uname) : stores hash permanently  store($storehash,$symb,$namespace,$udom,$uname,$laststore) : stores hash 
 for this url; hashref needs to be given and should be a \%hashname; the  permanently for this url; hashref needs to be given and should be a \%hashname;
 remaining args aren't required and if they aren't passed or are '' they will  the 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 (with the exception of $laststore, which is an
   optional arg used when a user's submission is stored in grading).
   $laststore is $version=$timestamp, where $version is the most recent version
   number retrieved for the corresponding $symb in the $namespace db file, and
   $timestamp is the timestamp for that transaction (UNIX time).
   $laststore is currently only passed when cstore() is called by
   structuretags::finalize_storage().
   
 =item *  =item *
   
 cstore($storehash,$symb,$namespace,$udom,$uname) : same as store but  cstore($storehash,$symb,$namespace,$udom,$uname,$laststore) : same as store 
 uses critical subroutine  but uses critical subroutine
   
 =item *  =item *
   
Line 13010  $range should be either an integer '100' Line 13519  $range should be either an integer '100'
   
 =item *  =item *
   
 putstore($namespace,$symb,$version,$storehash,$udomain,$uname) :  putstore($namespace,$symb,$version,$storehash,$udomain,$uname,$tolog) :
 replaces a &store() version of data with a replacement set of data  replaces a &store() version of data with a replacement set of data
 for a particular resource in a namespace passed in the $storehash hash   for a particular resource in a namespace passed in the $storehash hash 
 reference  reference. If $tolog is true, the transaction is logged in the courselog
   with an action=PUTSTORE.
   
 =item *  =item *
   
Line 13123  server ($udom and $uhome are optional) Line 13633  server ($udom and $uhome are optional)
   
 =item *   =item * 
   
 get_domain_defaults($target_domain) : returns hash with defaults for  get_domain_defaults($target_domain,$ignore_cache) : returns hash with defaults
 authentication and language in the domain. Keys are: auth_def, auth_arg_def,  for: authentication, language, quotas, timezone, date locale, and portal URL in
 lang_def; corresponsing values are authentication type (internal, krb4, krb5,  the target domain.
 or localauth), initial password or a kerberos realm, language (e.g., en-us).  
 Values are retrieved from cache (if current), or from domain's configuration.db  May also include additional key => value pairs for the following groups:
 (if available), or lastly from values in lonTabs/dns_domain,tab,   
 or lonTabs/domain.tab.   =over
   
   =item
   disk quotas (MB allocated by default to portfolios and authoring spaces).
   
   =over
   
   =item defaultquota, authorquota
   
   =back
   
   =item
   tools (availability of aboutme page, blog, webDAV access for authoring spaces,
   portfolio for users).
   
   =over
   
   =item
   aboutme, blog, webdav, portfolio
   
   =back
   
   =item
   requestcourses: ability to request courses, and how requests are processed.
   
   =over
   
   =item
   official, unofficial, community, textbook
   
   =back
   
   =item
   inststatus: types of institutional affiliation, and order in which they are displayed.
   
   =over
   
   =item
   inststatustypes, inststatusorder, inststatusguest
   
   =back
   
   =item
   coursedefaults: can PDF forms can be created, default credits for courses, default quotas (MB)
   for course's uploaded content.
   
   =over
   
   =item
   canuse_pdfforms, officialcredits, unofficialcredits, textbookcredits, officialquota, unofficialquota, communityquota, textbookquota
   
   =back
   
   =item
   usersessions: set options for hosting of your users in other domains, and hosting of users from other domains
   on your servers.
   
   =over
   
   =item
   remotesessions, hostedsessions
   
   =back
   
   =back
   
   In cases where a domain coordinator has never used the "Set Domain Configuration"
   utility to create a configuration.db file on a domain's primary library server
   only the following domain defaults: auth_def, auth_arg_def, lang_def
   -- corresponding values are authentication type (internal, krb4, krb5,
   or localauth), initial password or a kerberos realm, language (e.g., en-us) --
   will be available. Values are retrieved from cache (if current), unless the
   optional $ignore_cache arg is true, or from domain's configuration.db (if available),
   or lastly from values in lonTabs/dns_domain,tab, or lonTabs/domain.tab.
   
   Typical usage:
   
 %domdefaults = &get_auth_defaults($target_domain);  %domdefaults = &get_domain_defaults($target_domain);
   
 =back  =back
   
Line 13356  filelocation except for hrefs Line 13941  filelocation except for hrefs
   
 =item *  =item *
   
 declutter() : declutters URLs (remove docroot, beginning slashes, 'res' etc)  declutter() : declutters URLs -- remove beginning slashes, 'res' etc.
   also removes beginning /home/httpd/html unless /priv/ follows it.
   
 =back  =back
   

Removed from v.1.1172.2.28  
changed lines
  Added in v.1.1172.2.67


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