--- loncom/lonnet/perl/lonnet.pm 2012/05/28 12:28:14 1.1174 +++ loncom/lonnet/perl/lonnet.pm 2017/11/13 00:49:31 1.1359 @@ -1,7 +1,7 @@ # The LearningOnline Network # TCP networking package # -# $Id: lonnet.pm,v 1.1174 2012/05/28 12:28:14 raeburn Exp $ +# $Id: lonnet.pm,v 1.1359 2017/11/13 00:49:31 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -71,10 +71,10 @@ delayed. package Apache::lonnet; use strict; -use LWP::UserAgent(); use HTTP::Date; use Image::Magick; + use Encode; use vars qw(%perlvar %spareid %pr %prp $memcache %packagetab $tmpdir @@ -91,7 +91,7 @@ use GDBM_File; use HTML::LCParser; use Fcntl qw(:flock); use Storable qw(thaw nfreeze); -use Time::HiRes qw( gettimeofday tv_interval ); +use Time::HiRes qw( sleep gettimeofday tv_interval ); use Cache::Memcached; use Digest::MD5; use Math::Random; @@ -100,11 +100,12 @@ use LONCAPA qw(:DEFAULT :match); use LONCAPA::Configuration; use LONCAPA::lonmetadata; use LONCAPA::Lond; +use LONCAPA::LWPReq; use File::Copy; my $readit; -my $max_connection_retries = 10; # Or some such value. +my $max_connection_retries = 20; # Or some such value. require Exporter; @@ -112,37 +113,40 @@ our @ISA = qw (Exporter); our @EXPORT = qw(%env); -# --------------------------------------------------------------------- Logging +# ------------------------------------ Logging (parameters, docs, slots, roles) { my $logid; - sub instructor_log { - my ($hash_name,$storehash,$delflag,$uname,$udom,$cnum,$cdom)=@_; - if (($cnum eq '') || ($cdom eq '')) { - $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; - $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + sub write_log { + my ($context,$hash_name,$storehash,$delflag,$uname,$udom,$cnum,$cdom)=@_; + if ($context eq 'course') { + if (($cnum eq '') || ($cdom eq '')) { + $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + } } - $logid++; + $logid ++; my $now = time(); my $id=$now.'00000'.$$.'00000'.$logid; - return &Apache::lonnet::put('nohist_'.$hash_name, - { $id => { - 'exe_uname' => $env{'user.name'}, - 'exe_udom' => $env{'user.domain'}, - 'exe_time' => $now, - 'exe_ip' => $ENV{'REMOTE_ADDR'}, - 'delflag' => $delflag, - 'logentry' => $storehash, - 'uname' => $uname, - 'udom' => $udom, - } - },$cdom,$cnum); + my $logentry = { + $id => { + 'exe_uname' => $env{'user.name'}, + 'exe_udom' => $env{'user.domain'}, + 'exe_time' => $now, + 'exe_ip' => $ENV{'REMOTE_ADDR'}, + 'delflag' => $delflag, + 'logentry' => $storehash, + 'uname' => $uname, + 'udom' => $udom, + } + }; + return &put('nohist_'.$hash_name,$logentry,$cdom,$cnum); } } sub logtouch { my $execdir=$perlvar{'lonDaemons'}; unless (-e "$execdir/logs/lonnet.log") { - open(my $fh,">>$execdir/logs/lonnet.log"); + open(my $fh,">>","$execdir/logs/lonnet.log"); close $fh; } my ($wwwuid,$wwwgid)=(getpwnam('www'))[2,3]; @@ -154,7 +158,7 @@ sub logthis { my $execdir=$perlvar{'lonDaemons'}; my $now=time; my $local=localtime($now); - if (open(my $fh,">>$execdir/logs/lonnet.log")) { + if (open(my $fh,">>","$execdir/logs/lonnet.log")) { my $logstring = $local. " ($$): ".$message."\n"; # Keep any \'s in string. print $fh $logstring; close($fh); @@ -167,7 +171,7 @@ sub logperm { my $execdir=$perlvar{'lonDaemons'}; my $now=time; my $local=localtime($now); - if (open(my $fh,">>$execdir/logs/lonnet.perm.log")) { + if (open(my $fh,">>","$execdir/logs/lonnet.perm.log")) { print $fh "$now:$message:$local\n"; close($fh); } @@ -225,6 +229,52 @@ sub get_server_distarch { return; } +sub get_servercerts_info { + my ($lonhost,$context) = @_; + my ($rep,$uselocal); + if (grep { $_ eq $lonhost } ¤t_machine_ids()) { + $uselocal = 1; + } + if (($context ne 'cgi') && ($uselocal)) { + my $distro = (split(/\:/,&get_server_distarch($lonhost)))[0]; + if ($distro eq '') { + $uselocal = 0; + } elsif ($distro =~ /^(?:centos|redhat|scientific)(\d+)$/) { + if ($1 < 6) { + $uselocal = 0; + } + } elsif ($distro =~ /^(?:sles)(\d+)$/) { + if ($1 < 12) { + $uselocal = 0; + } + } + } + if ($uselocal) { + $rep = LONCAPA::Lond::server_certs(\%perlvar); + } else { + $rep=&reply('servercerts',$lonhost); + } + my ($result,%returnhash); + if (defined($lonhost)) { + if (!defined(&hostname($lonhost))) { + return; + } + } + if (($rep=~/^(refused|rejected|error)/) || ($rep eq 'con_lost') || + ($rep eq 'unknown_cmd')) { + $result = $rep; + } else { + $result = 'ok'; + my @pairs=split(/\&/,$rep); + foreach my $item (@pairs) { + my ($key,$value)=split(/=/,$item,2); + my $what = &unescape($key); + $returnhash{$what}=&thaw_unescape($value); + } + } + return ($result,\%returnhash); +} + sub get_server_loncaparev { my ($dom,$lonhost,$ignore_cache,$caller) = @_; if (defined($lonhost)) { @@ -259,13 +309,11 @@ sub get_server_loncaparev { $answer = &reply('serverloncaparev',$lonhost); if (($answer eq 'unknown_cmd') || ($answer eq 'con_lost')) { if ($caller eq 'loncron') { - my $ua=new LWP::UserAgent; - $ua->timeout(4); my $protocol = $protocol{$lonhost}; $protocol = 'http' if ($protocol ne 'https'); my $url = $protocol.'://'.&hostname($lonhost).'/adm/about.html'; my $request=new HTTP::Request('GET',$url); - my $response=$ua->request($request); + my $response=&LONCAPA::LWPReq::makerequest($lonhost,$request,'',\%perlvar,4,1); unless ($response->is_error()) { my $content = $response->content; if ($content =~ /
VERSION\:\s*([\w.\-]+)<\/p>/) {
@@ -352,8 +400,11 @@ sub get_remote_globals {
}
sub remote_devalidate_cache {
- my ($lonhost,$name,$id) = @_;
- my $response = &reply('devalidatecache:'.&escape($name).':'.&escape($id),$lonhost);
+ my ($lonhost,$cachekeys) = @_;
+ my $items;
+ return unless (ref($cachekeys) eq 'ARRAY');
+ my $cachestr = join('&',@{$cachekeys});
+ my $response = &reply('devalidatecache:'.&escape($cachestr),$lonhost);
return $response;
}
@@ -368,7 +419,7 @@ sub subreply {
my $lockfile=$peerfile.".lock";
while (-e $lockfile) { # Need to wait for the lockfile to disappear.
- sleep(1);
+ sleep(0.1);
}
# At this point, either a loncnew parent is listening or an old lonc
# or loncnew child is listening so we can connect or everything's dead.
@@ -386,7 +437,7 @@ sub subreply {
} else {
&create_connection(&hostname($server),$server);
}
- sleep(1); # Try again later if failed connection.
+ sleep(0.1); # Try again later if failed connection.
}
my $answer;
if ($client) {
@@ -415,8 +466,8 @@ sub reply {
sub reconlonc {
my ($lonid) = @_;
- my $hostname = &hostname($lonid);
if ($lonid) {
+ my $hostname = &hostname($lonid);
my $peerfile="$perlvar{'lonSockDir'}/$hostname";
if ($hostname && -e $peerfile) {
&logthis("Trying to reconnect lonc for $lonid ($hostname)");
@@ -434,14 +485,14 @@ sub reconlonc {
&logthis("Trying to reconnect lonc");
my $loncfile="$perlvar{'lonDaemons'}/logs/lonc.pid";
- if (open(my $fh,"<$loncfile")) {
+ if (open(my $fh,"<",$loncfile)) {
my $loncpid=<$fh>;
chomp($loncpid);
if (kill 0 => $loncpid) {
&logthis("lonc at pid $loncpid responding, sending USR1");
kill USR1 => $loncpid;
sleep 1;
- } else {
+ } else {
&logthis(
"WARNING:".
" lonc at pid $loncpid not responding, giving up");
@@ -462,7 +513,7 @@ sub critical {
}
my $answer=reply($cmd,$server);
if ($answer eq 'con_lost') {
- &reconlonc("$perlvar{'lonSockDir'}/$server");
+ &reconlonc($server);
my $answer=reply($cmd,$server);
if ($answer eq 'con_lost') {
my $now=time;
@@ -474,16 +525,16 @@ sub critical {
$dumpcount++;
{
my $dfh;
- if (open($dfh,">$dfilename")) {
+ if (open($dfh,">",$dfilename)) {
print $dfh "$cmd\n";
close($dfh);
}
}
- sleep 2;
+ sleep 1;
my $wcmd='';
{
my $dfh;
- if (open($dfh,"<$dfilename")) {
+ if (open($dfh,"<",$dfilename)) {
$wcmd=<$dfh>;
close($dfh);
}
@@ -599,12 +650,25 @@ sub transfer_profile_to_env {
# ---------------------------------------------------- Check for valid session
sub check_for_valid_session {
- my ($r,$name) = @_;
+ my ($r,$name,$userhashref,$domref) = @_;
my %cookies=CGI::Cookie->parse($r->header_in('Cookie'));
+ my ($linkname,$pubname);
if ($name eq '') {
$name = 'lonID';
+ $linkname = 'lonLinkID';
+ $pubname = 'lonPubID';
}
my $lonid=$cookies{$name};
+ if (!$lonid) {
+ if (($name eq 'lonID') && ($ENV{'SERVER_PORT'} != 443) && ($linkname)) {
+ $lonid=$cookies{$linkname};
+ }
+ if (!$lonid) {
+ if (($name eq 'lonID') && ($pubname)) {
+ $lonid=$cookies{$pubname};
+ }
+ }
+ }
return undef if (!$lonid);
my $handle=&LONCAPA::clean_handle($lonid->value);
@@ -614,7 +678,16 @@ sub check_for_valid_session {
} else {
$lonidsdir=$r->dir_config('lonIDsDir');
}
- return undef if (!-e "$lonidsdir/$handle.id");
+ if (!-e "$lonidsdir/$handle.id") {
+ if ((ref($domref)) && ($name eq 'lonID') &&
+ ($handle =~ /^($match_username)\_\d+\_($match_domain)\_(.+)$/)) {
+ my ($possuname,$possudom,$possuhome) = ($1,$2,$3);
+ if ((&domain($possudom) ne '') && (&homeserver($possuname,$possudom) eq $possuhome)) {
+ $$domref = $possudom;
+ }
+ }
+ return undef;
+ }
my $opened = open(my $idf,'+<',"$lonidsdir/$handle.id");
return undef if (!$opened);
@@ -630,6 +703,12 @@ sub check_for_valid_session {
|| !defined($disk_env{'user.domain'})) {
return undef;
}
+
+ if (ref($userhashref) eq 'HASH') {
+ $userhashref->{'name'} = $disk_env{'user.name'};
+ $userhashref->{'domain'} = $disk_env{'user.domain'};
+ }
+
return $handle;
}
@@ -663,7 +742,7 @@ sub appenv {
if (($key =~ /^user\.role/) || ($key =~ /^user\.priv/)) {
$refused = 1;
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})) {
$refused = 0;
}
@@ -836,10 +915,8 @@ sub spareserver {
if (ref($spareshash) eq 'HASH') {
if (ref($spareshash->{'primary'}) eq 'ARRAY') {
foreach my $try_server (@{ $spareshash->{'primary'} }) {
- if ($uint_dom) {
- next unless (&spare_can_host($udom,$uint_dom,$remotesessions,
- $try_server));
- }
+ next unless (&spare_can_host($udom,$uint_dom,$remotesessions,
+ $try_server));
($spare_server, $lowest_load) =
&compare_server_load($try_server, $spare_server, $lowest_load);
}
@@ -850,10 +927,8 @@ sub spareserver {
if (!$found_server) {
if (ref($spareshash->{'default'}) eq 'ARRAY') {
foreach my $try_server (@{ $spareshash->{'default'} }) {
- if ($uint_dom) {
- next unless (&spare_can_host($udom,$uint_dom,
- $remotesessions,$try_server));
- }
+ next unless (&spare_can_host($udom,$uint_dom,
+ $remotesessions,$try_server));
($spare_server, $lowest_load) =
&compare_server_load($try_server, $spare_server, $lowest_load);
}
@@ -877,7 +952,17 @@ sub spareserver {
}
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 $userloadans = &reply('userload',$try_server);
@@ -938,26 +1023,43 @@ sub has_user_session {
# --------- determine least loaded server in a user's domain which allows login
sub choose_server {
- my ($udom,$checkloginvia) = @_;
+ my ($udom,$checkloginvia,$required,$skiploadbal) = @_;
my %domconfhash = &Apache::loncommon::get_domainconf($udom);
my %servers = &get_servers($udom);
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)) {
+ if ($skiploadbal) {
+ if (ref($balancers) eq 'HASH') {
+ next if (exists($balancers->{$lonhost}));
+ }
+ }
my $loginvia;
if ($checkloginvia) {
$loginvia = $domconfhash{$udom.'.login.loginvia_'.$lonhost};
if ($loginvia) {
my ($server,$path) = split(/:/,$loginvia);
($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) {
$portal_path = $path;
$isredirect = 1;
}
} else {
($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) {
$portal_path = '';
$isredirect = '';
@@ -965,13 +1067,13 @@ sub choose_server {
}
} else {
($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 '') {
$hostname = &hostname($login_host);
}
- return ($login_host,$hostname,$portal_path,$isredirect);
+ return ($login_host,$hostname,$portal_path,$isredirect,$lowest_load);
}
# --------------------------------------------- Try to change a user's password
@@ -1138,19 +1240,27 @@ sub can_host_session {
sub spare_can_host {
my ($udom,$uint_dom,$remotesessions,$try_server)=@_;
my $canhost=1;
- my @intdoms;
- my $internet_names = &Apache::lonnet::get_internet_names($try_server);
- if (ref($internet_names) eq 'ARRAY') {
- @intdoms = @{$internet_names};
- }
- unless (grep(/^\Q$uint_dom\E$/,@intdoms)) {
- my $serverhomeID = &Apache::lonnet::get_server_homeID($try_server);
- 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);
- $canhost = &can_host_session($udom,$try_server,$remoterev,
- $remotesessions,
- $defdomdefaults{'hostedsessions'});
+ my $try_server_hostname = &hostname($try_server);
+ my $serverhomeID = &get_server_homeID($try_server_hostname);
+ my $serverhomedom = &host_domain($serverhomeID);
+ my %defdomdefaults = &get_domain_defaults($serverhomedom);
+ if (ref($defdomdefaults{'offloadnow'}) eq 'HASH') {
+ if ($defdomdefaults{'offloadnow'}{$try_server}) {
+ $canhost = 0;
+ }
+ }
+ if (($canhost) && ($uint_dom)) {
+ my @intdoms;
+ my $internet_names = &get_internet_names($try_server);
+ 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;
}
@@ -1235,15 +1345,16 @@ sub get_lonbalancer_config {
}
sub check_loadbalancing {
- my ($uname,$udom) = @_;
- my ($is_balancer,$dom_in_use,$homeintdom,$rule_in_effect,
- $offloadto,$otherserver);
+ my ($uname,$udom,$caller) = @_;
+ my ($is_balancer,$currtargets,$currrules,$dom_in_use,$homeintdom,
+ $rule_in_effect,$offloadto,$otherserver);
my $lonhost = $perlvar{'lonHostID'};
+ my @hosts = ¤t_machine_ids();
my $uprimary_id = &Apache::lonnet::domain($udom,'primary');
my $uintdom = &Apache::lonnet::internet_dom($uprimary_id);
my $intdom = &Apache::lonnet::internet_dom($lonhost);
my $serverhomedom = &host_domain($lonhost);
-
+ my $domneedscache;
my $cachetime = 60*60*24;
if (($uintdom ne '') && ($uintdom eq $intdom)) {
@@ -1258,18 +1369,13 @@ sub check_loadbalancing {
&Apache::lonnet::get_dom('configuration',['loadbalancing'],$dom_in_use);
if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
$result = &do_cache_new('loadbalancing',$dom_in_use,$domconfig{'loadbalancing'},$cachetime);
+ } else {
+ $domneedscache = $dom_in_use;
}
}
if (ref($result) eq 'HASH') {
- my $currbalancer = $result->{'lonhost'};
- my $currtargets = $result->{'targets'};
- my $currrules = $result->{'rules'};
- if ($currbalancer ne '') {
- my @hosts = ¤t_machine_ids();
- if (grep(/^\Q$currbalancer\E$/,@hosts)) {
- $is_balancer = 1;
- }
- }
+ ($is_balancer,$currtargets,$currrules) =
+ &check_balancer_result($result,@hosts);
if ($is_balancer) {
if (ref($currrules) eq 'HASH') {
if ($homeintdom) {
@@ -1318,21 +1424,20 @@ sub check_loadbalancing {
}
}
} elsif (($homeintdom) && ($udom ne $serverhomedom)) {
- my ($result,$cached)=&is_cached_new('loadbalancing',$serverhomedom);
+ ($result,$cached)=&is_cached_new('loadbalancing',$serverhomedom);
unless (defined($cached)) {
my %domconfig =
&Apache::lonnet::get_dom('configuration',['loadbalancing'],$serverhomedom);
if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
- $result = &do_cache_new('loadbalancing',$dom_in_use,$domconfig{'loadbalancing'},$cachetime);
+ $result = &do_cache_new('loadbalancing',$serverhomedom,$domconfig{'loadbalancing'},$cachetime);
+ } else {
+ $domneedscache = $serverhomedom;
}
}
if (ref($result) eq 'HASH') {
- my $currbalancer = $result->{'lonhost'};
- my $currtargets = $result->{'targets'};
- my $currrules = $result->{'rules'};
-
- if ($currbalancer eq $lonhost) {
- $is_balancer = 1;
+ ($is_balancer,$currtargets,$currrules) =
+ &check_balancer_result($result,@hosts);
+ if ($is_balancer) {
if (ref($currrules) eq 'HASH') {
if ($currrules->{'_LC_internetdom'} ne '') {
$rule_in_effect = $currrules->{'_LC_internetdom'};
@@ -1346,48 +1451,99 @@ sub check_loadbalancing {
$is_balancer = 1;
$offloadto = &this_host_spares($dom_in_use);
}
+ unless (defined($cached)) {
+ $domneedscache = $serverhomedom;
+ }
}
} else {
if ($perlvar{'lonBalancer'} eq 'yes') {
$is_balancer = 1;
$offloadto = &this_host_spares($dom_in_use);
}
+ unless (defined($cached)) {
+ $domneedscache = $serverhomedom;
+ }
}
- my $lowest_load = 30000;
- if (ref($offloadto) eq 'HASH') {
- if (ref($offloadto->{'primary'}) eq 'ARRAY') {
- foreach my $try_server (@{$offloadto->{'primary'}}) {
- ($otherserver,$lowest_load) =
- &compare_server_load($try_server,$otherserver,$lowest_load);
+ if ($domneedscache) {
+ &do_cache_new('loadbalancing',$domneedscache,$is_balancer,$cachetime);
+ }
+ if ($is_balancer) {
+ my $lowest_load = 30000;
+ if (ref($offloadto) eq 'HASH') {
+ if (ref($offloadto->{'primary'}) eq 'ARRAY') {
+ foreach my $try_server (@{$offloadto->{'primary'}}) {
+ ($otherserver,$lowest_load) =
+ &compare_server_load($try_server,$otherserver,$lowest_load);
+ }
}
- }
- my $found_server = ($otherserver ne '' && $lowest_load < 100);
+ my $found_server = ($otherserver ne '' && $lowest_load < 100);
- if (!$found_server) {
- if (ref($offloadto->{'default'}) eq 'ARRAY') {
- foreach my $try_server (@{$offloadto->{'default'}}) {
+ if (!$found_server) {
+ if (ref($offloadto->{'default'}) eq 'ARRAY') {
+ foreach my $try_server (@{$offloadto->{'default'}}) {
+ ($otherserver,$lowest_load) =
+ &compare_server_load($try_server,$otherserver,$lowest_load);
+ }
+ }
+ }
+ } elsif (ref($offloadto) eq 'ARRAY') {
+ if (@{$offloadto} == 1) {
+ $otherserver = $offloadto->[0];
+ } elsif (@{$offloadto} > 1) {
+ foreach my $try_server (@{$offloadto}) {
($otherserver,$lowest_load) =
&compare_server_load($try_server,$otherserver,$lowest_load);
}
}
}
- } elsif (ref($offloadto) eq 'ARRAY') {
- if (@{$offloadto} == 1) {
- $otherserver = $offloadto->[0];
- } elsif (@{$offloadto} > 1) {
- foreach my $try_server (@{$offloadto}) {
- ($otherserver,$lowest_load) =
- &compare_server_load($try_server,$otherserver,$lowest_load);
+ unless ($caller eq 'login') {
+ if (($otherserver ne '') && (grep(/^\Q$otherserver\E$/,@hosts))) {
+ $is_balancer = 0;
+ if ($uname ne '' && $udom ne '') {
+ if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
+
+ &appenv({'user.loadbalexempt' => $lonhost,
+ 'user.loadbalcheck.time' => time});
+ }
+ }
}
}
}
return ($is_balancer,$otherserver);
}
+sub check_balancer_result {
+ my ($result,@hosts) = @_;
+ my ($is_balancer,$currtargets,$currrules);
+ if (ref($result) eq 'HASH') {
+ if ($result->{'lonhost'} ne '') {
+ my $currbalancer = $result->{'lonhost'};
+ if (grep(/^\Q$currbalancer\E$/,@hosts)) {
+ $is_balancer = 1;
+ $currtargets = $result->{'targets'};
+ $currrules = $result->{'rules'};
+ }
+ } else {
+ foreach my $key (keys(%{$result})) {
+ if (($key ne '') && (grep(/^\Q$key\E$/,@hosts)) &&
+ (ref($result->{$key}) eq 'HASH')) {
+ $is_balancer = 1;
+ $currrules = $result->{$key}{'rules'};
+ $currtargets = $result->{$key}{'targets'};
+ last;
+ }
+ }
+ }
+ }
+ return ($is_balancer,$currtargets,$currrules);
+}
+
sub get_loadbalancer_targets {
my ($rule_in_effect,$currtargets,$uname,$udom) = @_;
my $offloadto;
- if ($rule_in_effect eq '') {
+ if ($rule_in_effect eq 'none') {
+ return [$perlvar{'lonHostID'}];
+ } elsif ($rule_in_effect eq '') {
$offloadto = $currtargets;
} else {
if ($rule_in_effect eq 'homeserver') {
@@ -1405,7 +1561,7 @@ sub get_loadbalancer_targets {
}
}
} else {
- my %servers = &dom_servers($udom);
+ my %servers = &internet_dom_servers($udom);
my ($remotebalancer,$remotetargets) = &get_lonbalancer_config(\%servers);
if (&hostname($remotebalancer) ne '') {
$offloadto = [$remotebalancer];
@@ -1451,6 +1607,100 @@ sub internet_dom_servers {
return %uniqservers;
}
+sub trusted_domains {
+ my ($cmdtype,$calldom) = @_;
+ my ($trusted,$untrusted);
+ if (&domain($calldom) eq '') {
+ return ($trusted,$untrusted);
+ }
+ unless ($cmdtype =~ /^(content|shared|enroll|coaurem|domroles|catalog|reqcrs|msg)$/) {
+ return ($trusted,$untrusted);
+ }
+ my $callprimary = &domain($calldom,'primary');
+ my $intcalldom = &Apache::lonnet::internet_dom($callprimary);
+ if ($intcalldom eq '') {
+ return ($trusted,$untrusted);
+ }
+
+ my ($trustconfig,$cached)=&Apache::lonnet::is_cached_new('trust',$calldom);
+ unless (defined($cached)) {
+ my %domconfig = &Apache::lonnet::get_dom('configuration',['trust'],$calldom);
+ &Apache::lonnet::do_cache_new('trust',$calldom,$domconfig{'trust'},3600);
+ $trustconfig = $domconfig{'trust'};
+ }
+ if (ref($trustconfig)) {
+ my (%possexc,%possinc,@allexc,@allinc);
+ if (ref($trustconfig->{$cmdtype}) eq 'HASH') {
+ if (ref($trustconfig->{$cmdtype}->{'exc'}) eq 'ARRAY') {
+ map { $possexc{$_} = 1; } @{$trustconfig->{$cmdtype}->{'exc'}};
+ }
+ if (ref($trustconfig->{$cmdtype}->{'inc'}) eq 'ARRAY') {
+ map { $possinc{$_} = 1; } @{$trustconfig->{$cmdtype}->{'inc'}};
+ }
+ }
+ if (keys(%possexc)) {
+ if (keys(%possinc)) {
+ foreach my $key (sort(keys(%possexc))) {
+ next if ($key eq $intcalldom);
+ unless ($possinc{$key}) {
+ push(@allexc,$key);
+ }
+ }
+ } else {
+ @allexc = sort(keys(%possexc));
+ }
+ }
+ if (keys(%possinc)) {
+ $possinc{$intcalldom} = 1;
+ @allinc = sort(keys(%possinc));
+ }
+ if ((@allexc > 0) || (@allinc > 0)) {
+ my %doms_by_intdom;
+ my %allintdoms = &all_host_intdom();
+ my %alldoms = &all_host_domain();
+ foreach my $key (%allintdoms) {
+ if (ref($doms_by_intdom{$allintdoms{$key}}) eq 'ARRAY') {
+ unless (grep(/^\Q$alldoms{$key}\E$/,@{$doms_by_intdom{$allintdoms{$key}}})) {
+ push(@{$doms_by_intdom{$allintdoms{$key}}},$alldoms{$key});
+ }
+ } else {
+ $doms_by_intdom{$allintdoms{$key}} = [$alldoms{$key}];
+ }
+ }
+ foreach my $exc (@allexc) {
+ if (ref($doms_by_intdom{$exc}) eq 'ARRAY') {
+ $untrusted = $doms_by_intdom{$exc};
+ }
+ }
+ foreach my $inc (@allinc) {
+ if (ref($doms_by_intdom{$inc}) eq 'ARRAY') {
+ $trusted = $doms_by_intdom{$inc};
+ }
+ }
+ }
+ }
+ return ($trusted,$untrusted);
+}
+
+sub will_trust {
+ my ($cmdtype,$domain,$possdom) = @_;
+ return 1 if ($domain eq $possdom);
+ my ($trustedref,$untrustedref) = &trusted_domains($cmdtype,$possdom);
+ my $willtrust;
+ if ((ref($trustedref) eq 'ARRAY') && (@{$trustedref} > 0)) {
+ if (grep(/^\Q$domain\E$/,@{$trustedref})) {
+ $willtrust = 1;
+ }
+ } elsif ((ref($untrustedref) eq 'ARRAY') && (@{$untrustedref} > 0)) {
+ unless (grep(/^\Q$domain\E$/,@{$untrustedref})) {
+ $willtrust = 1;
+ }
+ } else {
+ $willtrust = 1;
+ }
+ return $willtrust;
+}
+
# ---------------------- Find the homebase for a user from domain's lib servers
my %homecache;
@@ -1476,17 +1726,33 @@ sub homeserver {
return 'no_host';
}
-# ------------------------------------- Find the usernames behind a list of IDs
+# ----- Find the usernames behind a list of student/employee IDs or clicker IDs
sub idget {
- my ($udom,@ids)=@_;
+ my ($udom,$idsref,$namespace)=@_;
my %returnhash=();
+ my @ids=();
+ if (ref($idsref) eq 'ARRAY') {
+ @ids = @{$idsref};
+ } else {
+ return %returnhash;
+ }
+ if ($namespace eq '') {
+ $namespace = 'ids';
+ }
my %servers = &get_servers($udom,'library');
foreach my $tryserver (keys(%servers)) {
- my $idlist=join('&',@ids);
- $idlist=~tr/A-Z/a-z/;
- my $reply=&reply("idget:$udom:".$idlist,$tryserver);
+ my $idlist=join('&', map { &escape($_); } @ids);
+ if ($namespace eq 'ids') {
+ $idlist=~tr/A-Z/a-z/;
+ }
+ my $reply;
+ if ($namespace eq 'ids') {
+ $reply=&reply("idget:$udom:".$idlist,$tryserver);
+ } else {
+ $reply=&reply("getdom:$udom:$namespace:$idlist",$tryserver);
+ }
my @answer=();
if (($reply ne 'con_lost') && ($reply!~/^error\:/)) {
@answer=split(/\&/,$reply);
@@ -1494,10 +1760,10 @@ sub idget {
my $i;
for ($i=0;$i<=$#ids;$i++) {
if ($answer[$i]) {
- $returnhash{$ids[$i]}=$answer[$i];
- }
+ $returnhash{$ids[$i]}=&unescape($answer[$i]);
+ }
}
- }
+ }
return %returnhash;
}
@@ -1512,27 +1778,138 @@ sub idrget {
return %returnhash;
}
-# ------------------------------- Store away a list of names and associated IDs
+# Store away a list of names and associated student/employee IDs or clicker IDs
sub idput {
- my ($udom,%ids)=@_;
+ my ($udom,$idsref,$uhom,$namespace)=@_;
my %servers=();
+ my %ids=();
+ my %byid = ();
+ if (ref($idsref) eq 'HASH') {
+ %ids=%{$idsref};
+ }
+ if ($namespace eq '') {
+ $namespace = 'ids';
+ }
foreach my $uname (keys(%ids)) {
&cput('environment',{'id'=>$ids{$uname}},$udom,$uname);
- my $uhom=&homeserver($uname,$udom);
+ if ($uhom eq '') {
+ $uhom=&homeserver($uname,$udom);
+ }
if ($uhom ne 'no_host') {
- my $id=&escape($ids{$uname});
- $id=~tr/A-Z/a-z/;
my $esc_unam=&escape($uname);
- if ($servers{$uhom}) {
- $servers{$uhom}.='&'.$id.'='.$esc_unam;
+ if ($namespace eq 'ids') {
+ my $id=&escape($ids{$uname});
+ $id=~tr/A-Z/a-z/;
+ my $esc_unam=&escape($uname);
+ $servers{$uhom}.=$id.'='.$esc_unam.'&';
} else {
- $servers{$uhom}=$id.'='.$esc_unam;
+ my @currids = split(/,/,$ids{$uname});
+ foreach my $id (@currids) {
+ $byid{$uhom}{$id} .= $uname.',';
+ }
+ }
+ }
+ }
+ if ($namespace eq 'clickers') {
+ foreach my $server (keys(%byid)) {
+ if (ref($byid{$server}) eq 'HASH') {
+ foreach my $id (keys(%{$byid{$server}})) {
+ $byid{$server} =~ s/,$//;
+ $servers{$uhom}.=&escape($id).'='.&escape($byid{$server}).'&';
+ }
}
}
}
foreach my $server (keys(%servers)) {
- &critical('idput:'.$udom.':'.$servers{$server},$server);
+ $servers{$server} =~ s/\&$//;
+ if ($namespace eq 'ids') {
+ &critical('idput:'.$udom.':'.$servers{$server},$server);
+ } else {
+ &critical('updateclickers:'.$udom.':add:'.$servers{$server},$server);
+ }
+ }
+}
+
+# ------------- Delete unwanted student/employee IDs or clicker IDs from domain
+
+sub iddel {
+ my ($udom,$idshashref,$uhome,$namespace)=@_;
+ my %result=();
+ my %ids=();
+ my %byid = ();
+ if (ref($idshashref) eq 'HASH') {
+ %ids=%{$idshashref};
+ } else {
+ return %result;
+ }
+ if ($namespace eq '') {
+ $namespace = 'ids';
+ }
+ my %servers=();
+ while (my ($id,$unamestr) = each(%ids)) {
+ if ($namespace eq 'ids') {
+ my $uhom = $uhome;
+ if ($uhom eq '') {
+ $uhom=&homeserver($unamestr,$udom);
+ }
+ if ($uhom ne 'no_host') {
+ $servers{$uhom}.='&'.&escape($id);
+ }
+ } else {
+ my @curritems = split(/,/,$ids{$id});
+ foreach my $uname (@curritems) {
+ my $uhom = $uhome;
+ if ($uhom eq '') {
+ $uhom=&homeserver($uname,$udom);
+ }
+ if ($uhom ne 'no_host') {
+ $byid{$uhom}{$id} .= $uname.',';
+ }
+ }
+ }
+ }
+ if ($namespace eq 'clickers') {
+ foreach my $server (keys(%byid)) {
+ if (ref($byid{$server}) eq 'HASH') {
+ foreach my $id (keys(%{$byid{$server}})) {
+ $byid{$server}{$id} =~ s/,$//;
+ $servers{$server}.=&escape($id).'='.&escape($byid{$server}{$id}).'&';
+ }
+ }
+ }
+ }
+ foreach my $server (keys(%servers)) {
+ $servers{$server} =~ s/\&$//;
+ if ($namespace eq 'ids') {
+ $result{$server} = &critical('iddel:'.$udom.':'.$servers{$server},$uhome);
+ } elsif ($namespace eq 'clickers') {
+ $result{$server} = &critical('updateclickers:'.$udom.':del:'.$servers{$server},$server);
+ }
+ }
+ return %result;
+}
+
+# ----- Update clicker ID-to-username look-ups in clickers.db on library server
+
+sub updateclickers {
+ my ($udom,$action,$idshashref,$uhome,$critical) = @_;
+ my %clickers;
+ if (ref($idshashref) eq 'HASH') {
+ %clickers=%{$idshashref};
+ } else {
+ return;
+ }
+ my $items='';
+ foreach my $item (keys(%clickers)) {
+ $items.=&escape($item).'='.&escape($clickers{$item}).'&';
+ }
+ $items=~s/\&$//;
+ my $request = "updateclickers:$udom:$action:$items";
+ if ($critical) {
+ return &critical($request,$uhome);
+ } else {
+ return &reply($request,$uhome);
}
}
@@ -1551,6 +1928,7 @@ sub dump_dom {
sub get_dom {
my ($namespace,$storearr,$udom,$uhome)=@_;
+ return if ($udom eq 'public');
my $items='';
foreach my $item (@$storearr) {
$items.=&escape($item).'&';
@@ -1558,6 +1936,7 @@ sub get_dom {
$items=~s/\&$//;
if (!$udom) {
$udom=$env{'user.domain'};
+ return if ($udom eq 'public');
if (defined(&domain($udom,'primary'))) {
$uhome=&domain($udom,'primary');
} else {
@@ -1571,7 +1950,12 @@ sub get_dom {
}
}
if ($udom && $uhome && ($uhome ne 'no_host')) {
- my $rep=&reply("getdom:$udom:$namespace:$items",$uhome);
+ my $rep;
+ if ($namespace =~ /^enc/) {
+ $rep=&reply("encrypt:egetdom:$udom:$namespace:$items",$uhome);
+ } else {
+ $rep=&reply("getdom:$udom:$namespace:$items",$uhome);
+ }
my %returnhash;
if ($rep eq '' || $rep =~ /^error: 2 /) {
return %returnhash;
@@ -1615,7 +1999,11 @@ sub put_dom {
$items.=&escape($item).'='.&freeze_escape($$storehash{$item}).'&';
}
$items=~s/\&$//;
- return &reply("putdom:$udom:$namespace:$items",$uhome);
+ if ($namespace =~ /^enc/) {
+ return &reply("encrypt:putdom:$udom:$namespace:$items",$uhome);
+ } else {
+ return &reply("putdom:$udom:$namespace:$items",$uhome);
+ }
} else {
&logthis("put_dom failed - no homeserver and/or domain");
}
@@ -1661,14 +2049,13 @@ sub retrieve_inst_usertypes {
my %domdefs = &Apache::lonnet::get_domain_defaults($udom);
if ((ref($domdefs{'inststatustypes'}) eq 'HASH') &&
(ref($domdefs{'inststatusorder'}) eq 'ARRAY')) {
- %returnhash = %{$domdefs{'inststatustypes'}};
- @order = @{$domdefs{'inststatusorder'}};
+ return ($domdefs{'inststatustypes'},$domdefs{'inststatusorder'});
} else {
if (defined(&domain($udom,'primary'))) {
my $uhome=&domain($udom,'primary');
my $rep=&reply("inst_usertypes:$udom",$uhome);
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);
}
my ($hashitems,$orderitems) = split(/:/,$rep);
@@ -1684,15 +2071,15 @@ sub retrieve_inst_usertypes {
push(@order,&unescape($item));
}
} 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 {
my ($url) = @_;
- if ($url=~m-^/+res/+($match_domain)/+\1\-domainconfig/+(img|logo|domlogo)/+-) {
+ if ($url=~m-^/+res/+($match_domain)/+\1\-domainconfig/+(img|logo|domlogo)/+[^/]-) {
if (&domain($1) ne '') {
return '1';
}
@@ -1707,13 +2094,23 @@ sub inst_directory_query {
my $homeserver = &domain($udom,'primary');
my $outcome;
if ($homeserver ne '') {
+ unless ($homeserver eq $perlvar{'lonHostID'}) {
+ if ($srch->{'srchby'} eq 'email') {
+ my $lcrev = &get_server_loncaparev(undef,$homeserver);
+ my ($major,$minor) = ($lcrev =~ /^\'?(\d+)\.(\d+)\.[\w.\-]+\'?$/);
+ if (($major eq '' && $minor eq '') || ($major < 2) ||
+ (($major == 2) && ($minor < 12))) {
+ return;
+ }
+ }
+ }
my $queryid=&reply("querysend:instdirsearch:".
&escape($srch->{'srchby'}).':'.
&escape($srch->{'srchterm'}).':'.
&escape($srch->{'srchtype'}),$homeserver);
my $host=&hostname($homeserver);
if ($queryid !~/^\Q$host\E\_/) {
- &logthis('instituional directory search invalid queryid: '.$queryid.' for host: '.$homeserver.'in domain '.$udom);
+ &logthis('institutional directory search invalid queryid: '.$queryid.' for host: '.$homeserver.' in domain '.$udom);
return;
}
my $response = &get_query_reply($queryid);
@@ -1748,6 +2145,14 @@ sub usersearch {
my $query = 'usersearch';
foreach my $tryserver (keys(%libserv)) {
if (&host_domain($tryserver) eq $dom) {
+ unless ($tryserver eq $perlvar{'lonHostID'}) {
+ if ($srch->{'srchby'} eq 'email') {
+ my $lcrev = &get_server_loncaparev(undef,$tryserver);
+ my ($major,$minor) = ($lcrev =~ /^\'?(\d+)\.(\d+)\.[\w.\-]+\'?$/);
+ next if (($major eq '' && $minor eq '') || ($major < 2) ||
+ (($major == 2) && ($minor < 12)));
+ }
+ }
my $host=&hostname($tryserver);
my $queryid=
&reply("querysend:".&escape($query).':'.
@@ -1833,6 +2238,63 @@ sub get_instuser {
return ($outcome,%userinfo);
}
+sub get_multiple_instusers {
+ my ($udom,$users,$caller) = @_;
+ my ($outcome,$results);
+ if (ref($users) eq 'HASH') {
+ my $count = keys(%{$users});
+ my $requested = &freeze_escape($users);
+ my $homeserver = &domain($udom,'primary');
+ if ($homeserver ne '') {
+ my $queryid=&reply('querysend:getmultinstusers:::'.$caller.'='.$requested,$homeserver);
+ my $host=&hostname($homeserver);
+ if ($queryid !~/^\Q$host\E\_/) {
+ &logthis('get_multiple_instusers invalid queryid: '.$queryid.
+ ' for host: '.$homeserver.'in domain '.$udom);
+ return ($outcome,$results);
+ }
+ my $response = &get_query_reply($queryid);
+ my $maxtries = 5;
+ if ($count > 100) {
+ $maxtries = 1+int($count/20);
+ }
+ my $tries = 1;
+ while (($response=~/^timeout/) && ($tries <= $maxtries)) {
+ $response = &get_query_reply($queryid);
+ $tries ++;
+ }
+ if ($response eq '') {
+ $results = {};
+ foreach my $key (keys(%{$users})) {
+ my ($uname,$id);
+ if ($caller eq 'id') {
+ $id = $key;
+ } else {
+ $uname = $key;
+ }
+ my ($resp,%info) = &get_instuser($udom,$uname,$id);
+ $outcome = $resp;
+ if ($resp eq 'ok') {
+ %{$results} = (%{$results}, %info);
+ } else {
+ last;
+ }
+ }
+ } elsif(!&error($response) && ($response ne 'refused')) {
+ if (($response eq 'unavailable') || ($response eq 'invalid') || ($response eq 'timeout')) {
+ $outcome = $response;
+ } else {
+ ($outcome,my $userdata) = split(/=/,$response,2);
+ if ($outcome eq 'ok') {
+ $results = &thaw_unescape($userdata);
+ }
+ }
+ }
+ }
+ }
+ return ($outcome,$results);
+}
+
sub inst_rulecheck {
my ($udom,$uname,$id,$item,$rules) = @_;
my %returnhash;
@@ -1912,19 +2374,26 @@ sub inst_userrules {
# ------------- Get Authentication, Language and User Tools Defaults for Domain
sub get_domain_defaults {
- my ($domain) = @_;
+ my ($domain,$ignore_cache) = @_;
+ return if (($domain eq '') || ($domain eq 'public'));
my $cachetime = 60*60*24;
- my ($result,$cached)=&is_cached_new('domdefaults',$domain);
- if (defined($cached)) {
- if (ref($result) eq 'HASH') {
- return %{$result};
+ unless ($ignore_cache) {
+ my ($result,$cached)=&is_cached_new('domdefaults',$domain);
+ if (defined($cached)) {
+ if (ref($result) eq 'HASH') {
+ return %{$result};
+ }
}
}
my %domdefaults;
my %domconfig =
&Apache::lonnet::get_dom('configuration',['defaults','quotas',
'requestcourses','inststatus',
- 'coursedefaults','usersessions'],$domain);
+ 'coursedefaults','usersessions',
+ 'requestauthor','selfenrollment',
+ 'coursecategories','ssl','autoenroll',
+ 'trust','helpsettings'],$domain);
+ my @coursetypes = ('official','unofficial','community','textbook','placement');
if (ref($domconfig{'defaults'}) eq 'HASH') {
$domdefaults{'lang_def'} = $domconfig{'defaults'}{'lang_def'};
$domdefaults{'auth_def'} = $domconfig{'defaults'}{'auth_def'};
@@ -1932,6 +2401,9 @@ sub get_domain_defaults {
$domdefaults{'timezone_def'} = $domconfig{'defaults'}{'timezone_def'};
$domdefaults{'datelocale_def'} = $domconfig{'defaults'}{'datelocale_def'};
$domdefaults{'portal_def'} = $domconfig{'defaults'}{'portal_def'};
+ $domdefaults{'intauth_cost'} = $domconfig{'defaults'}{'intauth_cost'};
+ $domdefaults{'intauth_switch'} = $domconfig{'defaults'}{'intauth_switch'};
+ $domdefaults{'intauth_check'} = $domconfig{'defaults'}{'intauth_check'};
} else {
$domdefaults{'lang_def'} = &domain($domain,'lang_def');
$domdefaults{'auth_def'} = &domain($domain,'auth_def');
@@ -1942,28 +2414,66 @@ sub get_domain_defaults {
$domdefaults{'defaultquota'} = $domconfig{'quotas'}{'defaultquota'};
} else {
$domdefaults{'defaultquota'} = $domconfig{'quotas'};
- }
- my @usertools = ('aboutme','blog','portfolio');
+ }
+ my @usertools = ('aboutme','blog','webdav','portfolio');
foreach my $item (@usertools) {
if (ref($domconfig{'quotas'}{$item}) eq 'HASH') {
$domdefaults{$item} = $domconfig{'quotas'}{$item};
}
}
+ if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') {
+ $domdefaults{'authorquota'} = $domconfig{'quotas'}{'authorquota'};
+ }
}
if (ref($domconfig{'requestcourses'}) eq 'HASH') {
- foreach my $item ('official','unofficial','community') {
+ foreach my $item ('official','unofficial','community','textbook','placement') {
$domdefaults{$item} = $domconfig{'requestcourses'}{$item};
}
}
+ if (ref($domconfig{'requestauthor'}) eq 'HASH') {
+ $domdefaults{'requestauthor'} = $domconfig{'requestauthor'};
+ }
if (ref($domconfig{'inststatus'}) eq 'HASH') {
- foreach my $item ('inststatustypes','inststatusorder') {
+ foreach my $item ('inststatustypes','inststatusorder','inststatusguest') {
$domdefaults{$item} = $domconfig{'inststatus'}{$item};
}
}
if (ref($domconfig{'coursedefaults'}) eq 'HASH') {
- foreach my $item ('canuse_pdfforms') {
- $domdefaults{$item} = $domconfig{'coursedefaults'}{$item};
+ $domdefaults{'canuse_pdfforms'} = $domconfig{'coursedefaults'}{'canuse_pdfforms'};
+ $domdefaults{'usejsme'} = $domconfig{'coursedefaults'}{'usejsme'};
+ $domdefaults{'uselcmath'} = $domconfig{'coursedefaults'}{'uselcmath'};
+ 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 ($domconfig{'coursedefaults'}{'texengine'}) {
+ $domdefaults{'texengine'} = $domconfig{'coursedefaults'}{'texengine'};
+ }
}
if (ref($domconfig{'usersessions'}) eq 'HASH') {
if (ref($domconfig{'usersessions'}{'remote'}) eq 'HASH') {
@@ -1972,12 +2482,96 @@ sub get_domain_defaults {
if (ref($domconfig{'usersessions'}{'hosted'}) eq 'HASH') {
$domdefaults{'hostedsessions'} = $domconfig{'usersessions'}{'hosted'};
}
+ if (ref($domconfig{'usersessions'}{'offloadnow'}) eq 'HASH') {
+ $domdefaults{'offloadnow'} = $domconfig{'usersessions'}{'offloadnow'};
+ }
}
- &Apache::lonnet::do_cache_new('domdefaults',$domain,\%domdefaults,
- $cachetime);
+ 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'};
+ }
+ }
+ if (ref($domconfig{'ssl'}) eq 'HASH') {
+ if (ref($domconfig{'ssl'}{'replication'}) eq 'HASH') {
+ $domdefaults{'replication'} = $domconfig{'ssl'}{'replication'};
+ }
+ if (ref($domconfig{'ssl'}{'connto'}) eq 'HASH') {
+ $domdefaults{'connect'} = $domconfig{'ssl'}{'connto'};
+ }
+ if (ref($domconfig{'ssl'}{'connfrom'}) eq 'HASH') {
+ $domdefaults{'connect'} = $domconfig{'ssl'}{'connfrom'};
+ }
+ }
+ if (ref($domconfig{'trust'}) eq 'HASH') {
+ my @prefixes = qw(content shared enroll othcoau coaurem domroles catalog reqcrs msg);
+ foreach my $prefix (@prefixes) {
+ if (ref($domconfig{'trust'}{$prefix}) eq 'HASH') {
+ $domdefaults{'trust'.$prefix} = $domconfig{'trust'}{$prefix};
+ }
+ }
+ }
+ if (ref($domconfig{'autoenroll'}) eq 'HASH') {
+ $domdefaults{'autofailsafe'} = $domconfig{'autoenroll'}{'autofailsafe'};
+ }
+ if (ref($domconfig{'helpsettings'}) eq 'HASH') {
+ $domdefaults{'submitbugs'} = $domconfig{'helpsettings'}{'submitbugs'};
+ if (ref($domconfig{'helpsettings'}{'adhoc'}) eq 'HASH') {
+ $domdefaults{'adhocroles'} = $domconfig{'helpsettings'}{'adhoc'};
+ }
+ }
+ &do_cache_new('domdefaults',$domain,\%domdefaults,$cachetime);
return %domdefaults;
}
+sub course_portal_url {
+ my ($cnum,$cdom) = @_;
+ my $chome = &homeserver($cnum,$cdom);
+ my $hostname = &hostname($chome);
+ my $protocol = $protocol{$chome};
+ $protocol = 'http' if ($protocol ne 'https');
+ my %domdefaults = &get_domain_defaults($cdom);
+ my $firsturl;
+ if ($domdefaults{'portal_def'}) {
+ $firsturl = $domdefaults{'portal_def'};
+ } else {
+ $firsturl = $protocol.'://'.$hostname;
+ }
+ return $firsturl;
+}
+
# --------------------------------------------------- Assign a key to a student
sub assign_access_key {
@@ -2214,21 +2808,23 @@ sub make_key {
sub devalidate_cache_new {
my ($name,$id,$debug) = @_;
if ($debug) { &Apache::lonnet::logthis("deleting $name:$id"); }
+ my $remembered_id=$name.':'.$id;
$id=&make_key($name,$id);
$memcache->delete($id);
- delete($remembered{$id});
- delete($accessed{$id});
+ delete($remembered{$remembered_id});
+ delete($accessed{$remembered_id});
}
sub is_cached_new {
my ($name,$id,$debug) = @_;
- $id=&make_key($name,$id);
- if (exists($remembered{$id})) {
- if ($debug) { &Apache::lonnet::logthis("Early return $id of $remembered{$id} "); }
- $accessed{$id}=[&gettimeofday()];
+ my $remembered_id=$name.':'.$id; # this is to avoid make_key (which is slow) whenever possible
+ if (exists($remembered{$remembered_id})) {
+ if ($debug) { &Apache::lonnet::logthis("Early return $remembered_id of $remembered{$remembered_id} "); }
+ $accessed{$remembered_id}=[&gettimeofday()];
$hits++;
- return ($remembered{$id},1);
+ return ($remembered{$remembered_id},1);
}
+ $id=&make_key($name,$id);
my $value = $memcache->get($id);
if (!(defined($value))) {
if ($debug) { &Apache::lonnet::logthis("getting $id is not defined"); }
@@ -2238,13 +2834,14 @@ sub is_cached_new {
if ($debug) { &Apache::lonnet::logthis("getting $id is __undef__"); }
$value=undef;
}
- &make_room($id,$value,$debug);
+ &make_room($remembered_id,$value,$debug);
if ($debug) { &Apache::lonnet::logthis("getting $id is $value"); }
return ($value,1);
}
sub do_cache_new {
my ($name,$id,$value,$time,$debug) = @_;
+ my $remembered_id=$name.':'.$id;
$id=&make_key($name,$id);
my $setvalue=$value;
if (!defined($setvalue)) {
@@ -2260,17 +2857,17 @@ sub do_cache_new {
$memcache->disconnect_all();
}
# need to make a copy of $value
- &make_room($id,$value,$debug);
+ &make_room($remembered_id,$value,$debug);
return $value;
}
sub make_room {
- my ($id,$value,$debug)=@_;
+ my ($remembered_id,$value,$debug)=@_;
- $remembered{$id}= (ref($value)) ? &Storable::dclone($value)
+ $remembered{$remembered_id}= (ref($value)) ? &Storable::dclone($value)
: $value;
if ($to_remember<0) { return; }
- $accessed{$id}=[&gettimeofday()];
+ $accessed{$remembered_id}=[&gettimeofday()];
if (scalar(keys(%remembered)) <= $to_remember) { return; }
my $to_kick;
my $max_time=0;
@@ -2384,7 +2981,7 @@ sub chatsend {
sub getversion {
my $fname=&clutter(shift);
- unless ($fname=~/^\/res\//) { return -1; }
+ unless ($fname=~m{^(/adm/wrapper|)/res/}) { return -1; }
return ¤tversion(&filelocation('',$fname));
}
@@ -2482,9 +3079,13 @@ sub repcopy {
mkdir($path,0777);
}
}
- my $ua=new LWP::UserAgent;
my $request=new HTTP::Request('GET',"$remoteurl");
- my $response=$ua->request($request,$transname);
+ my $response;
+ if ($remoteurl =~ m{/raw/}) {
+ $response=&LONCAPA::LWPReq::makerequest($home,$request,$transname,\%perlvar,'',0,1);
+ } else {
+ $response=&LONCAPA::LWPReq::makerequest($home,$request,$transname,\%perlvar,'',1);
+ }
if ($response->is_error()) {
unlink($transname);
my $message=$response->status_line;
@@ -2494,7 +3095,12 @@ sub repcopy {
} else {
if ($remoteurl!~/\.meta$/) {
my $mrequest=new HTTP::Request('GET',$remoteurl.'.meta');
- my $mresponse=$ua->request($mrequest,$filename.'.meta');
+ my $mresponse;
+ if ($remoteurl =~ m{/raw/}) {
+ $mresponse = &LONCAPA::LWPReq::makerequest($home,$mrequest,$filename.'.meta',\%perlvar,'',0,1);
+ } else {
+ $mresponse = &LONCAPA::LWPReq::makerequest($home,$mrequest,$filename.'.meta',\%perlvar,'',1);
+ }
if ($mresponse->is_error()) {
unlink($filename.'.meta');
&logthis(
@@ -2557,33 +3163,37 @@ sub absolute_url {
sub ssi {
my ($fn,%form)=@_;
- my $ua=new LWP::UserAgent;
my $request;
$form{'no_update_last_known'}=1;
&Apache::lonenc::check_encrypt(\$fn);
if (%form) {
$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 {
$request=new HTTP::Request('GET',&absolute_url().$fn);
}
$request->header(Cookie => $ENV{'HTTP_COOKIE'});
- my $response= $ua->request($request);
- my $content = Encode::decode_utf8($response->content);
+ my $lonhost = $perlvar{'lonHostID'};
+ my $response= &LONCAPA::LWPReq::makerequest($lonhost,$request,'',\%perlvar);
+
if (wantarray) {
- return ($content, $response);
+ return ($response->content, $response);
} else {
- return $content;
+ return $response->content;
}
}
sub externalssi {
my ($url)=@_;
- my $ua=new LWP::UserAgent;
my $request=new HTTP::Request('GET',$url);
- my $response=$ua->request($request);
+ my $response = &LONCAPA::LWPReq::makerequest('',$request,'',\%perlvar);
if (wantarray) {
return ($response->content, $response);
} else {
@@ -2591,6 +3201,71 @@ sub externalssi {
}
}
+
+# If the local copy of a replicated resource is outdated, trigger a
+# connection from the homeserver to flush the delayed queue. If no update
+# happens, remove local copies of outdated resource (and corresponding
+# metadata file).
+
+sub remove_stale_resfile {
+ my ($url) = @_;
+ my $removed;
+ if ($url=~m{^/res/($match_domain)/($match_username)/}) {
+ my $audom = $1;
+ my $auname = $2;
+ unless (($url =~ /\.\d+\.\w+$/) || ($url =~ m{^/res/lib/templates/})) {
+ my $homeserver = &homeserver($auname,$audom);
+ unless (($homeserver eq 'no_host') ||
+ (grep { $_ eq $homeserver } ¤t_machine_ids())) {
+ my $fname = &filelocation('',$url);
+ if (-e $fname) {
+ my $protocol = $protocol{$homeserver};
+ $protocol = 'http' if ($protocol ne 'https');
+ my $hostname = &hostname($homeserver);
+ if ($hostname) {
+ my $uri = &declutter($url);
+ my $request=new HTTP::Request('HEAD',$protocol.'://'.$hostname.'/raw/'.$uri);
+ my $response = &LONCAPA::LWPReq::makerequest($homeserver,$request,'',\%perlvar,5,0,1);
+ if ($response->is_success()) {
+ my $remmodtime = &HTTP::Date::str2time( $response->header('Last-modified') );
+ my $locmodtime = (stat($fname))[9];
+ if ($locmodtime < $remmodtime) {
+ my $stale;
+ my $answer = &reply('pong',$homeserver);
+ if ($answer eq $homeserver.':'.$perlvar{'lonHostID'}) {
+ sleep(0.2);
+ $locmodtime = (stat($fname))[9];
+ if ($locmodtime < $remmodtime) {
+ my $posstransfer = $fname.'.in.transfer';
+ if ((-e $posstransfer) && ($remmodtime < (stat($posstransfer))[9])) {
+ $removed = 1;
+ } else {
+ $stale = 1;
+ }
+ } else {
+ $removed = 1;
+ }
+ } else {
+ $stale = 1;
+ }
+ if ($stale) {
+ unlink($fname);
+ if ($uri!~/\.meta$/) {
+ unlink($fname.'.meta');
+ }
+ &reply("unsub:$fname",$homeserver);
+ $removed = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return $removed;
+}
+
# -------------------------------- Allow a /uploaded/ URI to be vouched for
sub allowuploaded {
@@ -2604,6 +3279,285 @@ sub allowuploaded {
&Apache::lonnet::appenv(\%httpref);
}
+#
+# Determine if the current user should be able to edit a particular resource,
+# when viewing in course context.
+# (a) When viewing resource used to determine if "Edit" item is included in
+# Functions.
+# (b) When displaying folder contents in course editor, used to determine if
+# "Edit" link will be displayed alongside resource.
+#
+# input: six args -- filename (decluttered), course number, course domain,
+# url, symb (if registered) and group (if this is a group
+# item -- e.g., bulletin board, group page etc.).
+# output: array of five scalars --
+# $cfile -- url for file editing if editable on current server
+# $home -- homeserver of resource (i.e., for author if published,
+# or course if uploaded.).
+# $switchserver -- 1 if server switch will be needed.
+# $forceedit -- 1 if icon/link should be to go to edit mode
+# $forceview -- 1 if icon/link should be to go to view mode
+#
+
+sub can_edit_resource {
+ my ($file,$cnum,$cdom,$resurl,$symb,$group) = @_;
+ my ($cfile,$home,$switchserver,$forceedit,$forceview,$uploaded,$incourse);
+#
+# For aboutme pages user can only edit his/her own.
+#
+ if ($resurl =~ m{^/?adm/($match_domain)/($match_username)/aboutme$}) {
+ my ($sdom,$sname) = ($1,$2);
+ if (($sdom eq $env{'user.domain'}) && ($sname eq $env{'user.name'})) {
+ $home = $env{'user.home'};
+ $cfile = $resurl;
+ if ($env{'form.forceedit'}) {
+ $forceview = 1;
+ } else {
+ $forceedit = 1;
+ }
+ return ($cfile,$home,$switchserver,$forceedit,$forceview);
+ } else {
+ return;
+ }
+ }
+
+ if ($env{'request.course.id'}) {
+ my $crsedit = &Apache::lonnet::allowed('mdc',$env{'request.course.id'});
+ if ($group ne '') {
+# if this is a group homepage or group bulletin board, check group privs
+ my $allowed = 0;
+ if ($resurl =~ m{^/?adm/$cdom/$cnum/$group/smppg$}) {
+ if ((&allowed('mdg',$env{'request.course.id'}.
+ ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) ||
+ (&allowed('mgh',$env{'request.course.id'}.'/'.$group)) || $crsedit) {
+ $allowed = 1;
+ }
+ } elsif ($resurl =~ m{^/?adm/$cdom/$cnum/\d+/bulletinboard$}) {
+ if ((&allowed('mdg',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) ||
+ (&allowed('cgb',$env{'request.course.id'}.'/'.$group)) || $crsedit) {
+ $allowed = 1;
+ }
+ }
+ if ($allowed) {
+ $home=&homeserver($cnum,$cdom);
+ if ($env{'form.forceedit'}) {
+ $forceview = 1;
+ } else {
+ $forceedit = 1;
+ }
+ $cfile = $resurl;
+ } else {
+ return;
+ }
+ } else {
+ if ($resurl =~ m{^/?adm/viewclasslist$}) {
+ unless (&Apache::lonnet::allowed('opa',$env{'request.course.id'})) {
+ return;
+ }
+ } elsif (!$crsedit) {
+#
+# No edit allowed where CC has switched to student role.
+#
+ return;
+ }
+ }
+ }
+
+ if ($file ne '') {
+ if (($cnum =~ /$match_courseid/) && ($cdom =~ /$match_domain/)) {
+ if (&is_course_upload($file,$cnum,$cdom)) {
+ $uploaded = 1;
+ $incourse = 1;
+ if ($file =~/\.(htm|html|css|js|txt)$/) {
+ $cfile = &hreflocation('',$file);
+ if ($env{'form.forceedit'}) {
+ $forceview = 1;
+ } else {
+ $forceedit = 1;
+ }
+ }
+ } elsif ($resurl =~ m{^/public/$cdom/$cnum/syllabus}) {
+ $incourse = 1;
+ if ($env{'form.forceedit'}) {
+ $forceview = 1;
+ } else {
+ $forceedit = 1;
+ }
+ $cfile = $resurl;
+ } elsif (($resurl ne '') && (&is_on_map($resurl))) {
+ if ($resurl =~ m{^/adm/$match_domain/$match_username/\d+/smppg|bulletinboard$}) {
+ $incourse = 1;
+ if ($env{'form.forceedit'}) {
+ $forceview = 1;
+ } else {
+ $forceedit = 1;
+ }
+ $cfile = $resurl;
+ } elsif ($resurl eq '/res/lib/templates/simpleproblem.problem') {
+ $incourse = 1;
+ $cfile = $resurl.'/smpedit';
+ } elsif ($resurl =~ m{^/adm/wrapper/ext/}) {
+ $incourse = 1;
+ if ($env{'form.forceedit'}) {
+ $forceview = 1;
+ } else {
+ $forceedit = 1;
+ }
+ $cfile = $resurl;
+ } elsif ($resurl =~ m{^/adm/wrapper/adm/$cdom/$cnum/\d+/ext\.tool$}) {
+ $incourse = 1;
+ if ($env{'form.forceedit'}) {
+ $forceview = 1;
+ } else {
+ $forceedit = 1;
+ }
+ $cfile = $resurl;
+ } elsif ($resurl =~ m{^/?adm/viewclasslist$}) {
+ $incourse = 1;
+ if ($env{'form.forceedit'}) {
+ $forceview = 1;
+ } else {
+ $forceedit = 1;
+ }
+ $cfile = ($resurl =~ m{^/} ? $resurl : "/$resurl");
+ }
+ } elsif ($resurl eq '/res/lib/templates/simpleproblem.problem/smpedit') {
+ my $template = '/res/lib/templates/simpleproblem.problem';
+ if (&is_on_map($template)) {
+ $incourse = 1;
+ $forceview = 1;
+ $cfile = $template;
+ }
+ } elsif (($resurl =~ m{^/adm/wrapper/ext/}) && ($env{'form.folderpath'} =~ /^supplemental/)) {
+ $incourse = 1;
+ if ($env{'form.forceedit'}) {
+ $forceview = 1;
+ } else {
+ $forceedit = 1;
+ }
+ $cfile = $resurl;
+ } elsif (($resurl =~ m{^/adm/wrapper/adm/$cdom/$cnum/\d+/ext\.tool$}) && ($env{'form.folderpath'} =~ /^supplemental/)) {
+ $incourse = 1;
+ if ($env{'form.forceedit'}) {
+ $forceview = 1;
+ } else {
+ $forceedit = 1;
+ }
+ $cfile = $resurl;
+ } elsif (($resurl eq '/adm/extresedit') && ($symb || $env{'form.folderpath'})) {
+ $incourse = 1;
+ $forceview = 1;
+ if ($symb) {
+ my ($map,$id,$res)=&decode_symb($symb);
+ $env{'request.symb'} = $symb;
+ $cfile = &clutter($res);
+ } else {
+ $cfile = $env{'form.suppurl'};
+ my $escfile = &unescape($cfile);
+ if ($escfile =~ m{^/adm/$cdom/$cnum/\d+/ext\.tool$}) {
+ $cfile = '/adm/wrapper'.$escfile;
+ } else {
+ $escfile =~ s{^http://}{};
+ $cfile = &escape("/adm/wrapper/ext/$escfile");
+ }
+ }
+ } elsif ($resurl =~ m{^/?adm/viewclasslist$}) {
+ if ($env{'form.forceedit'}) {
+ $forceview = 1;
+ } else {
+ $forceedit = 1;
+ }
+ $cfile = ($resurl =~ m{^/} ? $resurl : "/$resurl");
+ }
+ }
+ if ($uploaded || $incourse) {
+ $home=&homeserver($cnum,$cdom);
+ } elsif ($file !~ m{/$}) {
+ $file=~s{^(priv/$match_domain/$match_username)}{/$1};
+ $file=~s{^($match_domain/$match_username)}{/priv/$1};
+ # Check that the user has permission to edit this resource
+ my $setpriv = 1;
+ my ($cfuname,$cfudom)=&constructaccess($file,$setpriv);
+ if (defined($cfudom)) {
+ $home=&homeserver($cfuname,$cfudom);
+ $cfile=$file;
+ }
+ }
+ if (($cfile ne '') && (!$incourse || $uploaded) &&
+ (($home ne '') && ($home ne 'no_host'))) {
+ my @ids=¤t_machine_ids();
+ unless (grep(/^\Q$home\E$/,@ids)) {
+ $switchserver=1;
+ }
+ }
+ }
+ return ($cfile,$home,$switchserver,$forceedit,$forceview);
+}
+
+sub is_course_upload {
+ my ($file,$cnum,$cdom) = @_;
+ my $uploadpath = &LONCAPA::propath($cdom,$cnum);
+ $uploadpath =~ s{^\/}{};
+ if (($file =~ m{^\Q$uploadpath\E/userfiles/(docs|supplemental)/}) ||
+ ($file =~ m{^userfiles/\Q$cdom\E/\Q$cnum\E/(docs|supplemental)/})) {
+ return 1;
+ }
+ return;
+}
+
+sub in_course {
+ my ($udom,$uname,$cdom,$cnum,$type,$hideprivileged) = @_;
+ if ($hideprivileged) {
+ my $skipuser;
+ my %coursehash = &coursedescription($cdom.'_'.$cnum);
+ my @possdoms = ($cdom);
+ if ($coursehash{'checkforpriv'}) {
+ push(@possdoms,split(/,/,$coursehash{'checkforpriv'}));
+ }
+ if (&privileged($uname,$udom,\@possdoms)) {
+ $skipuser = 1;
+ if ($coursehash{'nothideprivileged'}) {
+ foreach my $item (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) {
+ my $user;
+ if ($item =~ /:/) {
+ $user = $item;
+ } else {
+ $user = join(':',split(/[\@]/,$item));
+ }
+ if ($user eq $uname.':'.$udom) {
+ undef($skipuser);
+ last;
+ }
+ }
+ }
+ if ($skipuser) {
+ return 0;
+ }
+ }
+ }
+ $type ||= 'any';
+ if (!defined($cdom) || !defined($cnum)) {
+ my $cid = $env{'request.course.id'};
+ $cdom = $env{'course.'.$cid.'.domain'};
+ $cnum = $env{'course.'.$cid.'.num'};
+ }
+ my $typesref;
+ if (($type eq 'any') || ($type eq 'all')) {
+ $typesref = ['active','previous','future'];
+ } elsif ($type eq 'previous' || $type eq 'future') {
+ $typesref = [$type];
+ }
+ my %roles = &get_my_roles($uname,$udom,'userroles',
+ $typesref,undef,[$cdom]);
+ my ($tmp) = keys(%roles);
+ return 0 if ($tmp =~ /^(con_lost|error|no_such_host)/i);
+ my @course_roles = grep(/^\Q$cnum\E:\Q$cdom\E:/, keys(%roles));
+ if (@course_roles > 0) {
+ return 1;
+ }
+ return 0;
+}
+
# --------- File operations in /home/httpd/html/userfiles/$domain/1/2/3/$course
# input: action, courseID, current domain, intended
# path to file, source of file, instruction to parse file for objects,
@@ -2661,7 +3615,7 @@ sub process_coursefile {
$home);
}
} elsif ($action eq 'uploaddoc') {
- open(my $fh,'>'.$filepath.'/'.$fname);
+ open(my $fh,'>',$filepath.'/'.$fname);
print $fh $env{'form.'.$source};
close($fh);
if ($parser eq 'parse') {
@@ -2719,7 +3673,7 @@ sub store_edited_file {
($fpath,$fname) = ($file =~ m|^(.*)/([^/]+)$|);
$fpath=$docudom.'/'.$docuname.'/'.$fpath;
my $filepath = &build_filepath($fpath);
- open(my $fh,'>'.$filepath.'/'.$fname);
+ open(my $fh,'>',$filepath.'/'.$fname);
print $fh $content;
close($fh);
my $home=&homeserver($docuname,$docudom);
@@ -2835,12 +3789,12 @@ sub userfileupload {
'_'.$env{'user.domain'}.'/pending';
} elsif (($context eq 'existingfile') || ($context eq 'canceloverwrite')) {
my ($docuname,$docudom);
- if ($destudom) {
+ if ($destudom =~ /^$match_domain$/) {
$docudom = $destudom;
} else {
$docudom = $env{'user.domain'};
}
- if ($destuname) {
+ if ($destuname =~ /^$match_username$/) {
$docuname = $destuname;
} else {
$docuname = $env{'user.name'};
@@ -2870,7 +3824,7 @@ sub userfileupload {
mkdir($fullpath,0777);
}
}
- open(my $fh,'>'.$fullpath.'/'.$fname);
+ open(my $fh,'>',$fullpath.'/'.$fname);
print $fh $env{'form.'.$formname};
close($fh);
if ($context eq 'existingfile') {
@@ -2894,7 +3848,9 @@ sub userfileupload {
$codebase,$thumbwidth,$thumbheight,
$resizewidth,$resizeheight,$context,$mimetype);
} else {
- $fname=$env{'form.folder'}.'/'.$fname;
+ if ($env{'form.folder'}) {
+ $fname=$env{'form.folder'}.'/'.$fname;
+ }
return &process_coursefile('uploaddoc',$docuname,$docudom,
$fname,$formname,$parser,
$allfiles,$codebase,$mimetype);
@@ -2909,7 +3865,7 @@ sub userfileupload {
} else {
my $docuname=$env{'user.name'};
my $docudom=$env{'user.domain'};
- if (exists($env{'form.group'})) {
+ if ((exists($env{'form.group'})) || ($context eq 'syllabus')) {
$docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
$docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
}
@@ -2943,7 +3899,7 @@ sub finishuserfileupload {
# Save the file
{
- if (!open(FH,'>'.$filepath.'/'.$file)) {
+ if (!open(FH,'>',$filepath.'/'.$file)) {
&logthis('Failed to create '.$filepath.'/'.$file);
print STDERR ('Failed to create '.$filepath.'/'.$file."\n");
return '/adm/notfound.html';
@@ -3001,7 +3957,8 @@ sub finishuserfileupload {
my $input = $filepath.'/'.$file;
my $output = $filepath.'/'.'tn-'.$file;
my $thumbsize = $thumbwidth.'x'.$thumbheight;
- system("convert -sample $thumbsize $input $output");
+ my @args = ('convert','-sample',$thumbsize,$input,$output);
+ system({$args[0]} @args);
if (-e $filepath.'/'.'tn-'.$file) {
$fetchthumb = 1;
}
@@ -3059,7 +4016,9 @@ sub extract_embedded_items {
&add_filetype($allfiles,$attr->{'src'},'src');
}
if (lc($tagname) eq 'a') {
- &add_filetype($allfiles,$attr->{'href'},'href');
+ unless (($attr->{'href'} =~ /^#/) || ($attr->{'href'} eq '')) {
+ &add_filetype($allfiles,$attr->{'href'},'href');
+ }
}
if (lc($tagname) eq 'script') {
my $src;
@@ -3147,8 +4106,26 @@ 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{/>$}) {
- pop(@state);
+ pop(@state);
}
} elsif ($t->[0] eq 'E') {
my ($tagname) = ($t->[1]);
@@ -3365,7 +4342,7 @@ sub flushcourselogs {
}
}
#
-# Reverse lookup of domain roles (dc, ad, li, sc, au)
+# Reverse lookup of domain roles (dc, ad, li, sc, dh, da, au)
#
my %domrolebuffer = ();
foreach my $entry (keys(%domainrolehash)) {
@@ -3380,10 +4357,19 @@ sub flushcourselogs {
delete $domainrolehash{$entry};
}
foreach my $dom (keys(%domrolebuffer)) {
- my %servers = &get_servers($dom,'library');
+ my %servers;
+ if (defined(&domain($dom,'primary'))) {
+ my $primary=&domain($dom,'primary');
+ my $hostname=&hostname($primary);
+ $servers{$primary} = $hostname;
+ } else {
+ %servers = &get_servers($dom,'library');
+ }
foreach my $tryserver (keys(%servers)) {
- unless (&reply('domroleput:'.$dom.':'.
- $domrolebuffer{$dom},$tryserver) eq 'ok') {
+ if (&reply('domroleput:'.$dom.':'.
+ $domrolebuffer{$dom},$tryserver) eq 'ok') {
+ last;
+ } else {
&logthis('Put of domain roles failed for '.$dom.' and '.$tryserver);
}
}
@@ -3503,7 +4489,7 @@ sub userrolelog {
{$trole.':'.$username.':'.$domain.':'.$env{'user.name'}.':'.$env{'user.domain'}.':'}
=$tend.':'.$tstart;
}
- if ($trole =~ /^(dc|ad|li|au|dg|sc)/ ) {
+ if ($trole =~ /^(dc|ad|li|au|dg|sc|dh|da)/ ) {
my (undef,$rudom,$runame,$rsec)=split(/\//,$area);
$domainrolehash
{$trole.':'.$username.':'.$domain.':'.$runame.':'.$rudom.':'.$rsec}
@@ -3513,38 +4499,70 @@ sub userrolelog {
sub courserolelog {
my ($trole,$username,$domain,$area,$tstart,$tend,$delflag,$selfenroll,$context)=@_;
- if (($trole eq 'cc') || ($trole eq 'in') ||
- ($trole eq 'ep') || ($trole eq 'ad') ||
- ($trole eq 'ta') || ($trole eq 'st') ||
- ($trole=~/^cr/) || ($trole eq 'gr') ||
- ($trole eq 'co')) {
- if ($area =~ m-^/($match_domain)/($match_courseid)/?([^/]*)-) {
- my $cdom = $1;
- my $cnum = $2;
- my $sec = $3;
- my $namespace = 'rolelog';
- my %storehash = (
- role => $trole,
- start => $tstart,
- end => $tend,
- selfenroll => $selfenroll,
- context => $context,
- );
- if ($trole eq 'gr') {
- $namespace = 'groupslog';
- $storehash{'group'} = $sec;
- } else {
- $storehash{'section'} = $sec;
- }
- &instructor_log($namespace,\%storehash,$delflag,$username,$domain,$cnum,$cdom);
- if (($trole ne 'st') || ($sec ne '')) {
- &devalidate_cache_new('getcourseroles',$cdom.'_'.$cnum);
- }
+ if ($area =~ m-^/($match_domain)/($match_courseid)/?([^/]*)-) {
+ my $cdom = $1;
+ my $cnum = $2;
+ my $sec = $3;
+ my $namespace = 'rolelog';
+ my %storehash = (
+ role => $trole,
+ start => $tstart,
+ end => $tend,
+ selfenroll => $selfenroll,
+ context => $context,
+ );
+ if ($trole eq 'gr') {
+ $namespace = 'groupslog';
+ $storehash{'group'} = $sec;
+ } else {
+ $storehash{'section'} = $sec;
+ }
+ &write_log('course',$namespace,\%storehash,$delflag,$username,
+ $domain,$cnum,$cdom);
+ if (($trole ne 'st') || ($sec ne '')) {
+ &devalidate_cache_new('getcourseroles',$cdom.'_'.$cnum);
}
}
return;
}
+sub domainrolelog {
+ my ($trole,$username,$domain,$area,$tstart,$tend,$delflag,$context)=@_;
+ if ($area =~ m{^/($match_domain)/$}) {
+ my $cdom = $1;
+ my $domconfiguser = &Apache::lonnet::get_domainconfiguser($cdom);
+ my $namespace = 'rolelog';
+ my %storehash = (
+ role => $trole,
+ start => $tstart,
+ end => $tend,
+ context => $context,
+ );
+ &write_log('domain',$namespace,\%storehash,$delflag,$username,
+ $domain,$domconfiguser,$cdom);
+ }
+ return;
+
+}
+
+sub coauthorrolelog {
+ my ($trole,$username,$domain,$area,$tstart,$tend,$delflag,$context)=@_;
+ if ($area =~ m{^/($match_domain)/($match_username)$}) {
+ my $audom = $1;
+ my $auname = $2;
+ my $namespace = 'rolelog';
+ my %storehash = (
+ role => $trole,
+ start => $tstart,
+ end => $tend,
+ context => $context,
+ );
+ &write_log('author',$namespace,\%storehash,$delflag,$username,
+ $domain,$auname,$audom);
+ }
+ return;
+}
+
sub get_course_adv_roles {
my ($cid,$codes) = @_;
$cid=$env{'request.course.id'} unless (defined($cid));
@@ -3558,6 +4576,10 @@ sub get_course_adv_roles {
$nothide{$user}=1;
}
}
+ my @possdoms = ($coursehash{'domain'});
+ if ($coursehash{'checkforpriv'}) {
+ push(@possdoms,split(/,/,$coursehash{'checkforpriv'}));
+ }
my %returnhash=();
my %dumphash=
&dump('nohist_userroles',$coursehash{'domain'},$coursehash{'num'});
@@ -3570,20 +4592,7 @@ sub get_course_adv_roles {
if (($tstart) && ($now<$tstart)) { next; }
my ($role,$username,$domain,$section)=split(/\:/,$entry);
if ($username eq '' || $domain eq '') { next; }
- unless (ref($privileged{$domain}) eq 'HASH') {
- my %dompersonnel =
- &Apache::lonnet::get_domain_roles($domain,['dc'],$now,$now);
- $privileged{$domain} = {};
- foreach my $server (keys(%dompersonnel)) {
- if (ref($dompersonnel{$server}) eq 'HASH') {
- foreach my $user (keys(%{$dompersonnel{$server}})) {
- my ($trole,$uname,$udom) = split(/:/,$user);
- $privileged{$udom}{$uname} = 1;
- }
- }
- }
- }
- if ((exists($privileged{$domain}{$username})) &&
+ if ((&privileged($username,$domain,\@possdoms)) &&
(!$nothide{$username.':'.$domain})) { next; }
if ($role eq 'cr') { next; }
if ($codes) {
@@ -3614,8 +4623,7 @@ sub get_my_roles {
if ($context eq 'userroles') {
%dumphash = &dump('roles',$udom,$uname);
} else {
- %dumphash=
- &dump('nohist_userroles',$udom,$uname);
+ %dumphash = &dump('nohist_userroles',$udom,$uname);
if ($hidepriv) {
my %coursehash=&coursedescription($udom.'_'.$uname);
foreach my $user (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) {
@@ -3657,7 +4665,7 @@ sub get_my_roles {
}
my ($rolecode,$username,$domain,$section,$area);
if ($context eq 'userroles') {
- ($area,$rolecode) = split(/_/,$entry);
+ ($area,$rolecode) = ($entry =~ /^(.+)_([^_]+)$/);
(undef,$domain,$username,$section) = split(/\//,$area);
} else {
($role,$username,$domain,$section) = split(/\:/,$entry);
@@ -3683,28 +4691,15 @@ sub get_my_roles {
}
}
if ($hidepriv) {
+ my @privroles = ('dc','su');
if ($context eq 'userroles') {
- if ((&privileged($username,$domain)) &&
- (!$nothide{$username.':'.$domain})) {
- next;
- }
+ next if (grep(/^\Q$role\E$/,@privroles));
} else {
- unless (ref($privileged{$domain}) eq 'HASH') {
- my %dompersonnel =
- &Apache::lonnet::get_domain_roles($domain,['dc'],$now,$now);
- $privileged{$domain} = {};
- if (keys(%dompersonnel)) {
- foreach my $server (keys(%dompersonnel)) {
- if (ref($dompersonnel{$server}) eq 'HASH') {
- foreach my $user (keys(%{$dompersonnel{$server}})) {
- my ($trole,$uname,$udom) = split(/:/,$user);
- $privileged{$udom}{$uname} = $trole;
- }
- }
- }
- }
+ my $possdoms = [$domain];
+ if (ref($roledoms) eq 'ARRAY') {
+ push(@{$possdoms},@{$roledoms});
}
- if (exists($privileged{$domain}{$username})) {
+ if (&privileged($username,$domain,$possdoms,\@privroles)) {
if (!$nothide{$username.':'.$domain}) {
next;
}
@@ -3721,6 +4716,195 @@ sub get_my_roles {
return %returnhash;
}
+sub get_all_adhocroles {
+ my ($dom) = @_;
+ my @roles_by_num = ();
+ my %domdefaults = &get_domain_defaults($dom);
+ my (%description,%access_in_dom,%access_info);
+ if (ref($domdefaults{'adhocroles'}) eq 'HASH') {
+ my $count = 0;
+ my %domcurrent = %{$domdefaults{'adhocroles'}};
+ my %ordered;
+ foreach my $role (sort(keys(%domcurrent))) {
+ my ($order,$desc,$access_in_dom);
+ if (ref($domcurrent{$role}) eq 'HASH') {
+ $order = $domcurrent{$role}{'order'};
+ $desc = $domcurrent{$role}{'desc'};
+ $access_in_dom{$role} = $domcurrent{$role}{'access'};
+ $access_info{$role} = $domcurrent{$role}{$access_in_dom{$role}};
+ }
+ if ($order eq '') {
+ $order = $count;
+ }
+ $ordered{$order} = $role;
+ if ($desc ne '') {
+ $description{$role} = $desc;
+ } else {
+ $description{$role}= $role;
+ }
+ $count++;
+ }
+ foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
+ push(@roles_by_num,$ordered{$item});
+ }
+ }
+ return (\@roles_by_num,\%description,\%access_in_dom,\%access_info);
+}
+
+sub get_my_adhocroles {
+ my ($cid,$checkreg) = @_;
+ my ($cdom,$cnum,%info,@possroles,$description,$roles_by_num);
+ if ($env{'request.course.id'} eq $cid) {
+ $cdom = $env{'course.'.$cid.'.domain'};
+ $cnum = $env{'course.'.$cid.'.num'};
+ $info{'internal.coursecode'} = $env{'course.'.$cid.'.internal.coursecode'};
+ } elsif ($cid =~ /^($match_domain)_($match_courseid)$/) {
+ $cdom = $1;
+ $cnum = $2;
+ %info = &Apache::lonnet::get('environment',['internal.coursecode'],
+ $cdom,$cnum);
+ }
+ if (($info{'internal.coursecode'} ne '') && ($checkreg)) {
+ my $user = $env{'user.name'}.':'.$env{'user.domain'};
+ my %rosterhash = &get('classlist',[$user],$cdom,$cnum);
+ if ($rosterhash{$user} ne '') {
+ my $type = (split(/:/,$rosterhash{$user}))[5];
+ return ([],{}) if ($type eq 'auto');
+ }
+ }
+ if (($cdom ne '') && ($cnum ne '')) {
+ if (($env{"user.role.dh./$cdom/"}) || ($env{"user.role.da./$cdom/"})) {
+ my $then=$env{'user.login.time'};
+ my $update=$env{'user.update.time'};
+ if (!$update) {
+ $update = $then;
+ }
+ my @liveroles;
+ foreach my $role ('dh','da') {
+ if ($env{"user.role.$role./$cdom/"}) {
+ my ($tstart,$tend)=split(/\./,$env{"user.role.$role./$cdom/"});
+ my $limit = $update;
+ if ($env{'request.role'} eq "$role./$cdom/") {
+ $limit = $then;
+ }
+ my $activerole = 1;
+ if ($tstart && $tstart>$limit) { $activerole = 0; }
+ if ($tend && $tend <$limit) { $activerole = 0; }
+ if ($activerole) {
+ push(@liveroles,$role);
+ }
+ }
+ }
+ if (@liveroles) {
+ if (&homeserver($cnum,$cdom) ne 'no_host') {
+ my ($accessref,$accessinfo,%access_in_dom);
+ ($roles_by_num,$description,$accessref,$accessinfo) = &get_all_adhocroles($cdom);
+ if (ref($roles_by_num) eq 'ARRAY') {
+ if (@{$roles_by_num}) {
+ my %settings;
+ if ($env{'request.course.id'} eq $cid) {
+ foreach my $envkey (keys(%env)) {
+ if ($envkey =~ /^\Qcourse.$cid.\E(internal\.adhoc.+)$/) {
+ $settings{$1} = $env{$envkey};
+ }
+ }
+ } else {
+ %settings = &dump('environment',$cdom,$cnum,'internal\.adhoc');
+ }
+ my %setincrs;
+ if ($settings{'internal.adhocaccess'}) {
+ map { $setincrs{$_} = 1; } split(/,/,$settings{'internal.adhocaccess'});
+ }
+ my @statuses;
+ if ($env{'environment.inststatus'}) {
+ @statuses = split(/,/,$env{'environment.inststatus'});
+ }
+ my $user = $env{'user.name'}.':'.$env{'user.domain'};
+ if (ref($accessref) eq 'HASH') {
+ %access_in_dom = %{$accessref};
+ }
+ foreach my $role (@{$roles_by_num}) {
+ my ($curraccess,@okstatus,@personnel);
+ if ($setincrs{$role}) {
+ ($curraccess,my $rest) = split(/=/,$settings{'internal.adhoc.'.$role});
+ if ($curraccess eq 'status') {
+ @okstatus = split(/\&/,$rest);
+ } elsif (($curraccess eq 'exc') || ($curraccess eq 'inc')) {
+ @personnel = split(/\&/,$rest);
+ }
+ } else {
+ $curraccess = $access_in_dom{$role};
+ if (ref($accessinfo) eq 'HASH') {
+ if ($curraccess eq 'status') {
+ if (ref($accessinfo->{$role}) eq 'ARRAY') {
+ @okstatus = @{$accessinfo->{$role}};
+ }
+ } elsif (($curraccess eq 'exc') || ($curraccess eq 'inc')) {
+ if (ref($accessinfo->{$role}) eq 'ARRAY') {
+ @personnel = @{$accessinfo->{$role}};
+ }
+ }
+ }
+ }
+ if ($curraccess eq 'none') {
+ next;
+ } elsif ($curraccess eq 'all') {
+ push(@possroles,$role);
+ } elsif ($curraccess eq 'dh') {
+ if (grep(/^dh$/,@liveroles)) {
+ push(@possroles,$role);
+ } else {
+ next;
+ }
+ } elsif ($curraccess eq 'da') {
+ if (grep(/^da$/,@liveroles)) {
+ push(@possroles,$role);
+ } else {
+ next;
+ }
+ } elsif ($curraccess eq 'status') {
+ if (@okstatus) {
+ if (!@statuses) {
+ if (grep(/^default$/,@okstatus)) {
+ push(@possroles,$role);
+ }
+ } else {
+ foreach my $status (@okstatus) {
+ if (grep(/^\Q$status\E$/,@statuses)) {
+ push(@possroles,$role);
+ last;
+ }
+ }
+ }
+ }
+ } elsif (($curraccess eq 'exc') || ($curraccess eq 'inc')) {
+ if (grep(/^\Q$user\E$/,@personnel)) {
+ if ($curraccess eq 'exc') {
+ push(@possroles,$role);
+ }
+ } elsif ($curraccess eq 'inc') {
+ push(@possroles,$role);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ unless (ref($description) eq 'HASH') {
+ if (ref($roles_by_num) eq 'ARRAY') {
+ my %desc;
+ map { $desc{$_} = $_; } (@{$roles_by_num});
+ $description = \%desc;
+ } else {
+ $description = {};
+ }
+ }
+ return (\@possroles,$description);
+}
+
# ----------------------------------------------------- Frontpage Announcements
#
#
@@ -3734,7 +4918,7 @@ sub postannounce {
sub getannounce {
- if (open(my $fh,$perlvar{'lonDocRoot'}.'/announcement.txt')) {
+ if (open(my $fh,"<",$perlvar{'lonDocRoot'}.'/announcement.txt')) {
my $announcement='';
while (my $line = <$fh>) { $announcement .= $line; }
close($fh);
@@ -3796,7 +4980,8 @@ sub courseiddump {
my ($domfilter,$descfilter,$sincefilter,$instcodefilter,$ownerfilter,
$coursefilter,$hostidflag,$hostidref,$typefilter,$regexp_ok,
$selfenrollonly,$catfilter,$showhidden,$caller,$cloner,$cc_clone,
- $cloneonly,$createdbefore,$createdafter,$creationcontext,$domcloner)=@_;
+ $cloneonly,$createdbefore,$createdafter,$creationcontext,$domcloner,
+ $hasuniquecode,$reqcrsdom,$reqinstcode)=@_;
my $as_hash = 1;
my %returnhash;
if (!$domfilter) { $domfilter=''; }
@@ -3808,18 +4993,33 @@ sub courseiddump {
if (($domfilter eq '') ||
(&host_domain($tryserver) eq $domfilter)) {
- my $rep =
- &reply('courseiddump:'.&host_domain($tryserver).':'.
- $sincefilter.':'.&escape($descfilter).':'.
- &escape($instcodefilter).':'.&escape($ownerfilter).
- ':'.&escape($coursefilter).':'.&escape($typefilter).
- ':'.&escape($regexp_ok).':'.$as_hash.':'.
- &escape($selfenrollonly).':'.&escape($catfilter).':'.
- $showhidden.':'.$caller.':'.&escape($cloner).':'.
- &escape($cc_clone).':'.$cloneonly.':'.
- &escape($createdbefore).':'.&escape($createdafter).':'.
- &escape($creationcontext).':'.$domcloner,
- $tryserver);
+ my $rep;
+ if (grep { $_ eq $tryserver } current_machine_ids()) {
+ $rep = LONCAPA::Lond::dump_course_id_handler(
+ join(":", (&host_domain($tryserver), $sincefilter,
+ &escape($descfilter), &escape($instcodefilter),
+ &escape($ownerfilter), &escape($coursefilter),
+ &escape($typefilter), &escape($regexp_ok),
+ $as_hash, &escape($selfenrollonly),
+ &escape($catfilter), $showhidden, $caller,
+ &escape($cloner), &escape($cc_clone), $cloneonly,
+ &escape($createdbefore), &escape($createdafter),
+ &escape($creationcontext),$domcloner,$hasuniquecode,
+ $reqcrsdom,&escape($reqinstcode))));
+ } else {
+ $rep = &reply('courseiddump:'.&host_domain($tryserver).':'.
+ $sincefilter.':'.&escape($descfilter).':'.
+ &escape($instcodefilter).':'.&escape($ownerfilter).
+ ':'.&escape($coursefilter).':'.&escape($typefilter).
+ ':'.&escape($regexp_ok).':'.$as_hash.':'.
+ &escape($selfenrollonly).':'.&escape($catfilter).':'.
+ $showhidden.':'.$caller.':'.&escape($cloner).':'.
+ &escape($cc_clone).':'.$cloneonly.':'.
+ &escape($createdbefore).':'.&escape($createdafter).':'.
+ &escape($creationcontext).':'.$domcloner.':'.$hasuniquecode.
+ ':'.$reqcrsdom.':'.&escape($reqinstcode),$tryserver);
+ }
+
my @pairs=split(/\&/,$rep);
foreach my $item (@pairs) {
my ($key,$value)=split(/\=/,$item,2);
@@ -3925,7 +5125,7 @@ sub get_domain_roles {
}
my $rolelist;
if (ref($roles) eq 'ARRAY') {
- $rolelist = join(':',@{$roles});
+ $rolelist = join('&',@{$roles});
}
my %personnel = ();
@@ -3945,6 +5145,21 @@ sub get_domain_roles {
return %personnel;
}
+sub get_active_domroles {
+ my ($dom,$roles) = @_;
+ return () unless (ref($roles) eq 'ARRAY');
+ my $now = time;
+ my %dompersonnel = &get_domain_roles($dom,$roles,$now,$now);
+ my %domroles;
+ foreach my $server (keys(%dompersonnel)) {
+ foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {
+ my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user);
+ $domroles{$uname.':'.$udom} = $dompersonnel{$server}{$user};
+ }
+ }
+ return %domroles;
+}
+
# ----------------------------------------------------------- Interval timing
{
@@ -3956,12 +5171,13 @@ my $cachedkey='';
# The cached times for this user
my %cachedtimes=();
# When this was last done
-my $cachedtime=();
+my $cachedtime='';
sub load_all_first_access {
- my ($uname,$udom)=@_;
+ my ($uname,$udom,$ignorecache)=@_;
if (($cachedkey eq $uname.':'.$udom) &&
- (abs($cachedtime-time)<5) && (!$env{'form.markaccess'})) {
+ (abs($cachedtime-time)<5) && (!$env{'form.markaccess'}) &&
+ (!$ignorecache)) {
return;
}
$cachedtime=time;
@@ -3970,7 +5186,7 @@ sub load_all_first_access {
}
sub get_first_access {
- my ($type,$argsymb,$argmap)=@_;
+ my ($type,$argsymb,$argmap,$ignorecache)=@_;
my ($symb,$courseid,$udom,$uname)=&whichuser();
if ($argsymb) { $symb=$argsymb; }
my ($map,$id,$res)=&decode_symb($symb);
@@ -3982,7 +5198,7 @@ sub get_first_access {
} else {
$res=$symb;
}
- &load_all_first_access($uname,$udom);
+ &load_all_first_access($uname,$udom,$ignorecache);
return $cachedtimes{"$courseid\0$res"};
}
@@ -4018,6 +5234,7 @@ sub set_first_access {
return 'already_set';
}
}
+
# --------------------------------------------- Set Expire Date for Spreadsheet
sub expirespread {
@@ -4388,7 +5605,7 @@ sub tmprestore {
# ----------------------------------------------------------------------- Store
sub store {
- my ($storehash,$symb,$namespace,$domain,$stuname) = @_;
+ my ($storehash,$symb,$namespace,$domain,$stuname,$laststore) = @_;
my $home='';
if ($stuname) { $home=&homeserver($stuname,$domain); }
@@ -4418,13 +5635,13 @@ sub store {
}
$namevalue=~s/\&$//;
&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
sub cstore {
- my ($storehash,$symb,$namespace,$domain,$stuname) = @_;
+ my ($storehash,$symb,$namespace,$domain,$stuname,$laststore) = @_;
my $home='';
if ($stuname) { $home=&homeserver($stuname,$domain); }
@@ -4455,7 +5672,7 @@ sub cstore {
$namevalue=~s/\&$//;
&courselog($symb.':'.$stuname.':'.$domain.':CSTORE:'.$namevalue);
return critical
- ("store:$domain:$stuname:$namespace:$symb:$namevalue","$home");
+ ("store:$domain:$stuname:$namespace:$symb:$namevalue:$laststore","$home");
}
# --------------------------------------------------------------------- Restore
@@ -4467,9 +5684,12 @@ sub restore {
if ($stuname) { $home=&homeserver($stuname,$domain); }
if (!$symb) {
- unless ($symb=escape(&symbread())) { return ''; }
+ return if ($namespace eq 'courserequests');
+ unless ($symb=escape(&symbread())) { return ''; }
} else {
- $symb=&escape(&symbclean($symb));
+ unless ($namespace eq 'courserequests') {
+ $symb=&escape(&symbclean($symb));
+ }
}
if (!$namespace) {
unless ($namespace=$env{'request.course.id'}) {
@@ -4604,22 +5824,95 @@ sub update_released_required {
# -------------------------------------------------See if a user is privileged
sub privileged {
- my ($username,$domain)=@_;
-
- my %rolesdump = &dump("roles", $domain, $username) or return 0;
+ my ($username,$domain,$possdomains,$possroles)=@_;
my $now = time;
+ my $roles;
+ if (ref($possroles) eq 'ARRAY') {
+ $roles = $possroles;
+ } else {
+ $roles = ['dc','su'];
+ }
+ if (ref($possdomains) eq 'ARRAY') {
+ my %privileged = &privileged_by_domain($possdomains,$roles);
+ foreach my $dom (@{$possdomains}) {
+ if (($username =~ /^$match_username$/) && ($domain =~ /^$match_domain$/) &&
+ (ref($privileged{$dom}) eq 'HASH')) {
+ foreach my $role (@{$roles}) {
+ if (ref($privileged{$dom}{$role}) eq 'HASH') {
+ if (exists($privileged{$dom}{$role}{$username.':'.$domain})) {
+ my ($end,$start) = split(/:/,$privileged{$dom}{$role}{$username.':'.$domain});
+ return 1 unless (($end && $end < $now) ||
+ ($start && $start > $now));
+ }
+ }
+ }
+ }
+ }
+ } else {
+ my %rolesdump = &dump("roles", $domain, $username) or return 0;
+ 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);
- if (($trole eq 'dc') || ($trole eq 'su')) {
+ if (grep(/^\Q$trole\E$/,@{$roles})) {
return 1 unless ($tend && $tend < $now)
- or ($tstart && $tstart > $now);
+ or ($tstart && $tstart > $now);
}
- }
-
+ }
+ }
return 0;
}
+sub privileged_by_domain {
+ my ($domains,$roles) = @_;
+ my %privileged = ();
+ my $cachetime = 60*60*24;
+ my $now = time;
+ unless ((ref($domains) eq 'ARRAY') && (ref($roles) eq 'ARRAY')) {
+ return %privileged;
+ }
+ foreach my $dom (@{$domains}) {
+ next if (ref($privileged{$dom}) eq 'HASH');
+ my $needroles;
+ foreach my $role (@{$roles}) {
+ my ($result,$cached)=&is_cached_new('priv_'.$role,$dom);
+ if (defined($cached)) {
+ if (ref($result) eq 'HASH') {
+ $privileged{$dom}{$role} = $result;
+ }
+ } else {
+ $needroles = 1;
+ }
+ }
+ if ($needroles) {
+ my %dompersonnel = &get_domain_roles($dom,$roles);
+ $privileged{$dom} = {};
+ foreach my $server (keys(%dompersonnel)) {
+ if (ref($dompersonnel{$server}) eq 'HASH') {
+ foreach my $item (keys(%{$dompersonnel{$server}})) {
+ my ($trole,$uname,$udom,$rest) = split(/:/,$item,4);
+ my ($end,$start) = split(/:/,$dompersonnel{$server}{$item});
+ next if ($end && $end < $now);
+ $privileged{$dom}{$trole}{$uname.':'.$udom} =
+ $dompersonnel{$server}{$item};
+ }
+ }
+ }
+ if (ref($privileged{$dom}) eq 'HASH') {
+ foreach my $role (@{$roles}) {
+ if (ref($privileged{$dom}{$role}) eq 'HASH') {
+ &do_cache_new('priv_'.$role,$dom,$privileged{$dom}{$role},$cachetime);
+ } else {
+ my %hash = ();
+ &do_cache_new('priv_'.$role,$dom,\%hash,$cachetime);
+ }
+ }
+ }
+ }
+ }
+ return %privileged;
+}
+
# -------------------------------------------------------- Get user privileges
sub rolesinit {
@@ -4648,7 +5941,7 @@ sub rolesinit {
my %allroles=();
my %allgroups=();
- for my $area (grep { ! /^rolesdef_/ } keys %rolesdump) {
+ for my $area (grep { ! /^rolesdef_/ } keys(%rolesdump)) {
my $role = $rolesdump{$area};
$area =~ s/\_\w\w$//;
@@ -4721,24 +6014,27 @@ sub rolesinit {
}
}
- @userroles{'user.author', 'user.adv'} = &set_userprivs(\%userroles,
- \%allroles, \%allgroups);
+ @userroles{'user.author','user.adv','user.rar'} = &set_userprivs(\%userroles,
+ \%allroles, \%allgroups);
$env{'user.adv'} = $userroles{'user.adv'};
+ $env{'user.rar'} = $userroles{'user.rar'};
return (\%userroles,\%firstaccenv,\%timerintenv);
}
sub set_arearole {
- my ($trole,$area,$tstart,$tend,$domain,$username) = @_;
+ my ($trole,$area,$tstart,$tend,$domain,$username,$nolog) = @_;
+ unless ($nolog) {
# log the associated role with the area
- &userrolelog($trole,$username,$domain,$area,$tstart,$tend);
+ &userrolelog($trole,$username,$domain,$area,$tstart,$tend);
+ }
return ('user.role.'.$trole.'.'.$area => $tstart.'.'.$tend);
}
sub custom_roleprivs {
my ($allroles,$trole,$tdomain,$trest,$spec,$area) = @_;
my ($rdummy,$rdomain,$rauthor,$rrole)=split(/\//,$trole);
- my $homsvr=homeserver($rauthor,$rdomain);
+ my $homsvr = &homeserver($rauthor,$rdomain);
if (&hostname($homsvr) ne '') {
my ($rdummy,$roledef)=
&get('roles',["rolesdef_$rrole"],$rdomain,$rauthor);
@@ -4757,6 +6053,10 @@ sub custom_roleprivs {
$$allroles{$spec.'./'.$tdomain.'/'}.=':'.$dompriv;
}
if (($trest ne '') && (defined($coursepriv))) {
+ if ($trole =~ m{^cr/$tdomain/$tdomain\Q-domainconfig\E/([^/]+)$}) {
+ my $rolename = $1;
+ $coursepriv = &course_adhocrole_privs($rolename,$tdomain,$trest,$coursepriv);
+ }
$$allroles{'cm.'.$area}.=':'.$coursepriv;
$$allroles{$spec.'.'.$area}.=':'.$coursepriv;
}
@@ -4765,6 +6065,48 @@ sub custom_roleprivs {
}
}
+sub course_adhocrole_privs {
+ my ($rolename,$cdom,$cnum,$coursepriv) = @_;
+ my %overrides = &get('environment',["internal.adhocpriv.$rolename"],$cdom,$cnum);
+ if ($overrides{"internal.adhocpriv.$rolename"}) {
+ my (%currprivs,%storeprivs);
+ foreach my $item (split(/:/,$coursepriv)) {
+ my ($priv,$restrict) = split(/\&/,$item);
+ $currprivs{$priv} = $restrict;
+ }
+ my (%possadd,%possremove,%full);
+ foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:c'})) {
+ my ($priv,$restrict)=split(/\&/,$item);
+ $full{$priv} = $restrict;
+ }
+ foreach my $item (split(/,/,$overrides{"internal.adhocpriv.$rolename"})) {
+ next if ($item eq '');
+ my ($rule,$rest) = split(/=/,$item);
+ next unless (($rule eq 'off') || ($rule eq 'on'));
+ foreach my $priv (split(/:/,$rest)) {
+ if ($priv ne '') {
+ if ($rule eq 'off') {
+ $possremove{$priv} = 1;
+ } else {
+ $possadd{$priv} = 1;
+ }
+ }
+ }
+ }
+ foreach my $priv (sort(keys(%full))) {
+ if (exists($currprivs{$priv})) {
+ unless (exists($possremove{$priv})) {
+ $storeprivs{$priv} = $currprivs{$priv};
+ }
+ } elsif (exists($possadd{$priv})) {
+ $storeprivs{$priv} = $full{$priv};
+ }
+ }
+ $coursepriv = ':'.join(':',map { $_.'&'.$storeprivs{$_}; } sort(keys(%storeprivs)));
+ }
+ return $coursepriv;
+}
+
sub group_roleprivs {
my ($allgroups,$area,$group_privs,$tend,$tstart) = @_;
my $access = 1;
@@ -4799,6 +6141,7 @@ sub set_userprivs {
my ($userroles,$allroles,$allgroups,$groups_roles) = @_;
my $author=0;
my $adv=0;
+ my $rar=0;
my %grouproles = ();
if (keys(%{$allgroups}) > 0) {
my @groupkeys;
@@ -4846,6 +6189,7 @@ sub set_userprivs {
$thesepriv{$privilege}.=$restrictions;
}
if ($thesepriv{'adv'} eq 'F') { $adv=1; }
+ if ($thesepriv{'rar'} eq 'F') { $rar=1; }
}
}
my $thesestr='';
@@ -4854,16 +6198,16 @@ sub set_userprivs {
}
$userroles->{'user.priv.'.$role} = $thesestr;
}
- return ($author,$adv);
+ return ($author,$adv,$rar);
}
sub role_status {
my ($rolekey,$update,$refresh,$now,$role,$where,$trolecode,$tstatus,$tstart,$tend) = @_;
- my @pwhere = ();
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 '') {
- $$where=join('.',@pwhere);
+ $$where = '/'.$two;
$$trolecode=$$role.'.'.$$where;
($$tstart,$$tend)=split(/\./,$env{$rolekey});
$$tstatus='is';
@@ -4899,9 +6243,10 @@ sub role_status {
push(@rolecodes,$$role);
&standard_roleprivs(\%allroles,$$role,$tdomain,$spec,$trest,$$where);
}
- my ($author,$adv)= &set_userprivs(\%userroles,\%allroles,\%allgroups,\%groups_roles);
+ my ($author,$adv,$rar)= &set_userprivs(\%userroles,\%allroles,\%allgroups,
+ \%groups_roles);
&appenv(\%userroles,\@rolecodes);
- &log($env{'user.domain'},$env{'user.name'},$env{'user.home'},"Role ".$role);
+ &log($env{'user.domain'},$env{'user.name'},$env{'user.home'},"Role ".$spec);
}
}
$$tstatus = 'is';
@@ -4977,35 +6322,56 @@ sub delete_env_groupprivs {
}
sub check_adhoc_privs {
- my ($cdom,$cnum,$update,$refresh,$now,$checkrole,$caller) = @_;
+ my ($cdom,$cnum,$update,$refresh,$now,$checkrole,$caller,$sec) = @_;
my $cckey = 'user.role.'.$checkrole.'./'.$cdom.'/'.$cnum;
+ if ($sec) {
+ $cckey .= '/'.$sec;
+ }
+ my $setprivs;
if ($env{$cckey}) {
my ($role,$where,$trolecode,$tstart,$tend,$tremark,$tstatus,$tpstart,$tpend);
&role_status($cckey,$update,$refresh,$now,\$role,\$where,\$trolecode,\$tstatus,\$tstart,\$tend);
unless (($tstatus eq 'is') || ($tstatus eq 'will_not')) {
- &set_adhoc_privileges($cdom,$cnum,$checkrole,$caller);
+ &set_adhoc_privileges($cdom,$cnum,$checkrole,$caller,$sec);
+ $setprivs = 1;
}
} else {
- &set_adhoc_privileges($cdom,$cnum,$checkrole,$caller);
+ &set_adhoc_privileges($cdom,$cnum,$checkrole,$caller,$sec);
+ $setprivs = 1;
}
+ return $setprivs;
}
sub set_adhoc_privileges {
-# role can be cc or ca
- my ($dcdom,$pickedcourse,$role,$caller) = @_;
+# role can be cc, ca, or cr/
'.$space.' - '.$qualifier.' - '.$spacequalifierrest;
# ----------------------------------------------------- Cascading lookup scheme
my $symbp=$symbparm;
- my $mapp=&deversion((&decode_symb($symbp))[0]);
-
+ $mapp=&deversion((&decode_symb($symbp))[0]);
my $symbparm=$symbp.'.'.$spacequalifierrest;
+ my $recurseparm=$mapp.'___(rec).'.$spacequalifierrest;
my $mapparm=$mapp.'___(all).'.$spacequalifierrest;
-
if (($env{'user.name'} eq $uname) &&
($env{'user.domain'} eq $udom)) {
$section=$env{'request.course.sec'};
@@ -9137,17 +11423,21 @@ sub EXT {
my $seclevel=$courseid.'.['.$section.'].'.$spacequalifierrest;
my $seclevelr=$courseid.'.['.$section.'].'.$symbparm;
+ my $secleveli=$courseid.'.['.$section.'].'.$recurseparm;
my $seclevelm=$courseid.'.['.$section.'].'.$mapparm;
$courselevel=$courseid.'.'.$spacequalifierrest;
my $courselevelr=$courseid.'.'.$symbparm;
+ $courseleveli=$courseid.'.'.$recurseparm;
$courselevelm=$courseid.'.'.$mapparm;
# ----------------------------------------------------------- first, check user
- my $userreply=&resdata($uname,$udom,'user',
+ my $userreply=&resdata($uname,$udom,'user',$mapp,\$recursed,
+ \@recurseup,$courseid,'.',$spacequalifierrest,
([$courselevelr,'resource'],
[$courselevelm,'map' ],
+ [$courseleveli,'map' ],
[$courselevel, 'course' ]));
if (defined($userreply)) { return &get_reply($userreply); }
@@ -9155,15 +11445,18 @@ sub EXT {
my $coursereply;
if (@groups > 0) {
$coursereply = &check_group_parms($courseid,\@groups,$symbparm,
- $mapparm,$spacequalifierrest);
- if (defined($coursereply)) { return &get_reply($coursereply); }
+ $recurseparm,$mapparm,$spacequalifierrest,
+ $mapp,\$recursed,\@recurseup);
+ if (defined($coursereply)) { return &get_reply($coursereply); }
}
$coursereply=&resdata($env{'course.'.$courseid.'.num'},
$env{'course.'.$courseid.'.domain'},
- 'course',
+ 'course',$mapp,\$recursed,\@recurseup,
+ $courseid,'.['.$section.'].',$spacequalifierrest,
([$seclevelr, 'resource'],
[$seclevelm, 'map' ],
+ [$secleveli, 'map' ],
[$seclevel, 'course' ],
[$courselevelr,'resource']));
if (defined($coursereply)) { return &get_reply($coursereply); }
@@ -9180,8 +11473,9 @@ sub EXT {
if ($thisparm) { return &get_reply([$thisparm,'resource']); }
}
# ------------------------------------------ fourth, look in resource metadata
-
- $spacequalifierrest=~s/\./\_/;
+
+ my $what = $spacequalifierrest;
+ $what=~s/\./\_/;
my $filename;
if (!$symbparm) { $symbparm=&symbread(); }
if ($symbparm) {
@@ -9189,18 +11483,20 @@ sub EXT {
} else {
$filename=$env{'request.filename'};
}
- my $metadata=&metadata($filename,$spacequalifierrest);
+ my $metadata=&metadata($filename,$what);
if (defined($metadata)) { return &get_reply([$metadata,'resource']); }
- $metadata=&metadata($filename,'parameter_'.$spacequalifierrest);
+ $metadata=&metadata($filename,'parameter_'.$what);
if (defined($metadata)) { return &get_reply([$metadata,'resource']); }
-# ---------------------------------------------- fourth, look in rest of course
+# ----------------------------------------------- fifth, look in rest of course
if ($symbparm && defined($courseid) &&
$courseid eq $env{'request.course.id'}) {
my $coursereply=&resdata($env{'course.'.$courseid.'.num'},
$env{'course.'.$courseid.'.domain'},
- 'course',
+ 'course',$mapp,\$recursed,\@recurseup,
+ $courseid,'.',$spacequalifierrest,
([$courselevelm,'map' ],
+ [$courseleveli,'map' ],
[$courselevel, 'course']));
if (defined($coursereply)) { return &get_reply($coursereply); }
}
@@ -9257,22 +11553,51 @@ sub get_reply {
}
sub check_group_parms {
- my ($courseid,$groups,$symbparm,$mapparm,$what) = @_;
- my @groupitems = ();
- my $resultitem;
- my @levels = ([$symbparm,'resource'],[$mapparm,'map'],[$what,'course']);
+ my ($courseid,$groups,$symbparm,$recurseparm,$mapparm,$what,$mapp,
+ $recursed,$recurseupref) = @_;
+ my @levels = ([$symbparm,'resource'],[$mapparm,'map'],[$recurseparm,'map'],
+ [$what,'course']);
+ my $coursereply;
foreach my $group (@{$groups}) {
+ my @groupitems = ();
foreach my $level (@levels) {
my $item = $courseid.'.['.$group.'].'.$level->[0];
push(@groupitems,[$item,$level->[1]]);
}
+ my $coursereply = &resdata($env{'course.'.$courseid.'.num'},
+ $env{'course.'.$courseid.'.domain'},
+ 'course',$mapp,$recursed,$recurseupref,
+ $courseid,'.['.$group.'].',$what,
+ @groupitems);
+ last if (defined($coursereply));
}
- my $coursereply = &resdata($env{'course.'.$courseid.'.num'},
- $env{'course.'.$courseid.'.domain'},
- 'course',@groupitems);
return $coursereply;
}
+sub get_map_hierarchy {
+ my ($mapname,$courseid) = @_;
+ my @recurseup = ();
+ if ($mapname) {
+ if (($cachedmapkey eq $courseid) &&
+ (abs($cachedmaptime-time)<5)) {
+ if (ref($cachedmaps{$mapname}) eq 'ARRAY') {
+ return @{$cachedmaps{$mapname}};
+ }
+ }
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (ref($navmap)) {
+ @recurseup = $navmap->recurseup_maps($mapname);
+ undef($navmap);
+ $cachedmaps{$mapname} = \@recurseup;
+ $cachedmaptime=time;
+ $cachedmapkey=$courseid;
+ }
+ }
+ return @recurseup;
+}
+
+}
+
sub sort_course_groups { # Sort groups based on defined rankings. Default is sort().
my ($courseid,@groups) = @_;
@groups = sort(@groups);
@@ -9357,11 +11682,11 @@ sub metadata {
# if it is a non metadata possible uri return quickly
if (($uri eq '') ||
(($uri =~ m|^/*adm/|) &&
- ($uri !~ m|^adm/includes|) && ($uri !~ m|/bulletinboard$|)) ||
+ ($uri !~ m|^adm/includes|) && ($uri !~ m{/(smppg|bulletinboard|ext\.tool)$})) ||
($uri =~ m|/$|) || ($uri =~ m|/.meta$|) || ($uri =~ m{^/*uploaded/.+\.sequence$})) {
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)$/) {
return undef;
}
@@ -9622,7 +11947,7 @@ sub metadata {
$metaentry{':keys'} = join(',',keys(%metathesekeys));
&metadata_generate_part0(\%metathesekeys,\%metaentry,$uri);
- $metaentry{':allpossiblekeys'}=join(',',keys %metathesekeys);
+ $metaentry{':allpossiblekeys'}=join(',',keys(%metathesekeys));
&do_cache_new('meta',$uri,\%metaentry,$cachetime);
# this is the end of "was not already recently cached
}
@@ -9788,7 +12113,7 @@ sub get_course_slots {
my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum);
my ($tmp) = keys(%slots);
if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
- &Apache::lonnet::do_cache_new('allslots',$hashid,\%slots,600);
+ &do_cache_new('allslots',$hashid,\%slots,600);
return %slots;
}
}
@@ -9801,6 +12126,41 @@ sub devalidate_slots_cache {
&devalidate_cache_new('allslots',$hashid);
}
+sub get_coursechange {
+ my ($cdom,$cnum) = @_;
+ if ($cdom eq '' || $cnum eq '') {
+ return unless ($env{'request.course.id'});
+ $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ }
+ my $hashid=$cdom.'_'.$cnum;
+ my ($change,$cached)=&is_cached_new('crschange',$hashid);
+ if ((defined($cached)) && ($change ne '')) {
+ return $change;
+ } else {
+ my %crshash;
+ %crshash = &get('environment',['internal.contentchange'],$cdom,$cnum);
+ if ($crshash{'internal.contentchange'} eq '') {
+ $change = $env{'course.'.$cdom.'_'.$cnum.'.internal.created'};
+ if ($change eq '') {
+ %crshash = &get('environment',['internal.created'],$cdom,$cnum);
+ $change = $crshash{'internal.created'};
+ }
+ } else {
+ $change = $crshash{'internal.contentchange'};
+ }
+ my $cachetime = 600;
+ &do_cache_new('crschange',$hashid,$change,$cachetime);
+ }
+ return $change;
+}
+
+sub devalidate_coursechange_cache {
+ my ($cnum,$cdom)=@_;
+ my $hashid=$cnum.':'.$cdom;
+ &devalidate_cache_new('crschange',$hashid);
+}
+
# ------------------------------------------------- Update symbolic store links
sub symblist {
@@ -9828,7 +12188,7 @@ sub symblist {
# --------------------------------------------------------------- Verify a symb
sub symbverify {
- my ($symb,$thisurl)=@_;
+ my ($symb,$thisurl,$encstate)=@_;
my $thisfn=$thisurl;
$thisfn=&declutter($thisfn);
# direct jump to resource in page or to a sequence - will construct own symbs
@@ -9847,28 +12207,43 @@ sub symbverify {
if (tie(%bighash,'GDBM_File',$env{'request.course.fn'}.'.db',
&GDBM_READER(),0640)) {
+ my $noclutter;
if (($thisurl =~ m{^/adm/wrapper/ext/}) || ($thisurl =~ m{^ext/})) {
$thisurl =~ s/\?.+$//;
+ if ($map =~ m{^uploaded/.+\.page$}) {
+ $thisurl =~ s{^(/adm/wrapper|)/ext/}{http://};
+ $thisurl =~ s{^\Qhttp://https://\E}{https://};
+ $noclutter = 1;
+ }
+ }
+ my $ids;
+ if ($noclutter) {
+ $ids=$bighash{'ids_'.$thisurl};
+ } else {
+ $ids=$bighash{'ids_'.&clutter($thisurl)};
}
- my $ids=$bighash{'ids_'.&clutter($thisurl)};
unless ($ids) {
my $idkey = 'ids_'.($thisurl =~ m{^/}? '' : '/').$thisurl;
$ids=$bighash{$idkey};
}
if ($ids) {
# ------------------------------------------------------------------- Has ID(s)
+ if ($thisfn =~ m{^/adm/wrapper/ext/}) {
+ $symb =~ s/\?.+$//;
+ }
foreach my $id (split(/\,/,$ids)) {
my ($mapid,$resid)=split(/\./,$id);
- if ($thisfn =~ m{^/adm/wrapper/ext/}) {
- $symb =~ s/\?.+$//;
- }
if (
&symbclean(&declutter($bighash{'map_id_'.$mapid}).'___'.$resid.'___'.$thisfn)
- eq $symb) {
+ eq $symb) {
+ if (ref($encstate)) {
+ $$encstate = $bighash{'encrypted_'.$id};
+ }
if (($env{'request.role.adv'}) ||
($bighash{'encrypted_'.$id} eq $env{'request.enc'}) ||
($thisurl eq '/adm/navmaps')) {
- $okay=1;
+ $okay=1;
+ last;
}
}
}
@@ -9943,9 +12318,15 @@ sub deversion {
# ------------------------------------------------------ Return symb list entry
sub symbread {
- my ($thisfn,$donotrecurse)=@_;
+ my ($thisfn,$donotrecurse,$ignorecachednull,$checkforblock,$possibles)=@_;
my $cache_str='request.symbread.cached.'.$thisfn;
- if (defined($env{$cache_str})) { return $env{$cache_str}; }
+ if (defined($env{$cache_str})) {
+ if ($ignorecachednull) {
+ return $env{$cache_str} unless ($env{$cache_str} eq '');
+ } else {
+ return $env{$cache_str};
+ }
+ }
# no filename provided? try from environment
unless ($thisfn) {
if ($env{'request.symb'}) {
@@ -10007,18 +12388,46 @@ sub symbread {
my ($mapid,$resid)=split(/\./,$ids);
$syval=&encode_symb($bighash{'map_id_'.$mapid},
$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
my $realpossible=0;
foreach my $id (@possibilities) {
my $file=$bighash{'src_'.$id};
- if (&allowed('bre',$file)) {
- my ($mapid,$resid)=split(/\./,$id);
- if ($bighash{'map_type_'.$mapid} ne 'page') {
- $realpossible++;
- $syval=&encode_symb($bighash{'map_id_'.$mapid},
- $resid,$thisfn);
- }
+ my $canaccess;
+ if (($donotrecurse) || ($checkforblock) || (ref($possibles) eq 'HASH')) {
+ $canaccess = 1;
+ } else {
+ $canaccess = &allowed('bre',$file);
+ }
+ 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=''; }
@@ -10026,7 +12435,7 @@ sub symbread {
$syval='';
}
}
- untie(%bighash)
+ untie(%bighash);
}
}
if ($syval) {
@@ -10365,8 +12774,12 @@ sub rndseed_CODE_64bit5 {
sub setup_random_from_rndseed {
my ($rndseed)=@_;
if ($rndseed =~/([,:])/) {
- my ($num1,$num2)=split(/[,:]/,$rndseed);
- &Math::Random::random_set_seed(abs($num1),abs($num2));
+ my ($num1,$num2) = map { abs($_); } (split(/[,:]/,$rndseed));
+ if ((!$num1) || (!$num2) || ($num1 > 2147483562) || ($num2 > 2147483398)) {
+ &Math::Random::random_set_seed_from_phrase($rndseed);
+ } else {
+ &Math::Random::random_set_seed($num1,$num2);
+ }
} else {
&Math::Random::random_set_seed_from_phrase($rndseed);
}
@@ -10545,7 +12958,6 @@ sub repcopy_userfile {
}
# now the path exists for sure
# get a user agent
- my $ua=new LWP::UserAgent;
my $transferfile=$file.'.in.transfer';
# FIXME: this should flock
if (-e $transferfile) { return 'ok'; }
@@ -10555,7 +12967,7 @@ sub repcopy_userfile {
my $protocol = $protocol{$homeserver};
$protocol = 'http' if ($protocol ne 'https');
$request=new HTTP::Request('GET',$protocol.'://'.&hostname($homeserver).'/raw/'.$uri);
- my $response=$ua->request($request,$transferfile);
+ my $response = &LONCAPA::LWPReq::makerequest($homeserver,$request,$transferfile,\%perlvar,'',0,1);
# did it work?
if ($response->is_error()) {
unlink($transferfile);
@@ -10599,9 +13011,8 @@ sub getuploaded {
my $protocol = $protocol{$homeserver};
$protocol = 'http' if ($protocol ne 'https');
$uri = $protocol.'://'.&hostname($homeserver).'/raw/'.$uri;
- my $ua=new LWP::UserAgent;
my $request=new HTTP::Request($reqtype,$uri);
- my $response=$ua->request($request);
+ my $response=&LONCAPA::LWPReq::makerequest($homeserver,$request,'',\%perlvar,'',0,1);
$$rtncode = $response->code;
if (! $response->is_success()) {
return 'failed';
@@ -10618,7 +13029,7 @@ sub readfile {
my $file = shift;
if ( (! -e $file ) || ($file eq '') ) { return -1; };
my $fh;
- open($fh,"<$file");
+ open($fh,"<",$file);
my $a='';
while (my $line = <$fh>) { $a .= $line; }
return $a;
@@ -10731,7 +13142,7 @@ sub machine_ids {
sub additional_machine_domains {
my @domains;
- open(my $fh,"<$perlvar{'lonTabDir'}/expected_domains.tab");
+ open(my $fh,"<","$perlvar{'lonTabDir'}/expected_domains.tab");
while( my $line = <$fh>) {
$line =~ s/\s//g;
push(@domains,$line);
@@ -10757,7 +13168,9 @@ sub default_login_domain {
sub declutter {
my $thisfn=shift;
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|^adm/wrapper/||;
$thisfn=~s|^adm/coursedocs/showdoc/||;
@@ -10800,6 +13213,8 @@ sub clutter {
# &logthis("Got a blank emb style");
}
}
+ } elsif ($thisfn =~ m{^/adm/$match_domain/$match_courseid/\d+/ext\.tool$}) {
+ $thisfn='/adm/wrapper'.$thisfn;
}
return $thisfn;
}
@@ -10862,18 +13277,18 @@ sub goodbye {
}
sub get_dns {
- my ($url,$func,$ignore_cache) = @_;
+ my ($url,$func,$ignore_cache,$nocache,$hashref) = @_;
if (!$ignore_cache) {
my ($content,$cached)=
&Apache::lonnet::is_cached_new('dns',$url);
if ($cached) {
- &$func($content);
+ &$func($content,$hashref);
return;
}
}
my %alldns;
- open(my $config,"<$perlvar{'lonTabDir'}/hosts.tab");
+ open(my $config,"<","$perlvar{'lonTabDir'}/hosts.tab");
foreach my $dns (<$config>) {
next if ($dns !~ /^\^(\S*)/x);
my $line = $1;
@@ -10884,26 +13299,83 @@ sub get_dns {
$alldns{$host} = $protocol;
}
while (%alldns) {
- my ($dns) = keys(%alldns);
- my $ua=new LWP::UserAgent;
- $ua->timeout(30);
+ my ($dns) = sort { $b cmp $a } keys(%alldns);
my $request=new HTTP::Request('GET',"$alldns{$dns}://$dns$url");
- my $response=$ua->request($request);
+ my $response = &LONCAPA::LWPReq::makerequest('',$request,'',\%perlvar,30,0);
delete($alldns{$dns});
next if ($response->is_error());
my @content = split("\n",$response->content);
- &Apache::lonnet::do_cache_new('dns',$url,\@content,30*24*60*60);
- &$func(\@content);
+ unless ($nocache) {
+ &do_cache_new('dns',$url,\@content,30*24*60*60);
+ }
+ &$func(\@content,$hashref);
return;
}
close($config);
my $which = (split('/',$url))[3];
&logthis("unable to contact DNS defaulting to on disk file dns_$which.tab\n");
- open($config,"<$perlvar{'lonTabDir'}/dns_$which.tab");
+ open($config,"<","$perlvar{'lonTabDir'}/dns_$which.tab");
my @content = <$config>;
- &$func(\@content);
+ &$func(\@content,$hashref);
return;
}
+
+# ------------------------------------------------------Get DNS checksums file
+sub parse_dns_checksums_tab {
+ my ($lines,$hashref) = @_;
+ my $lonhost = $perlvar{'lonHostID'};
+ my $machine_dom = &Apache::lonnet::host_domain($lonhost);
+ 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 (%chksum,%revnum);
+ if (ref($lines) eq 'ARRAY') {
+ chomp(@{$lines});
+ my $version = shift(@{$lines});
+ if ($version eq $release) {
+ foreach my $line (@{$lines}) {
+ my ($file,$version,$shasum) = split(/,/,$line);
+ if ($file =~ m{^/etc/httpd/conf}) {
+ if ($webconfdir eq '/etc/apache2') {
+ $file =~ s{^\Q/etc/httpd/conf/\E}{$webconfdir/};
+ }
+ }
+ $chksum{$file} = $shasum;
+ $revnum{$file} = $version;
+ }
+ if (ref($hashref) eq 'HASH') {
+ %{$hashref} = (
+ sums => \%chksum,
+ versions => \%revnum,
+ );
+ }
+ }
+ }
+ return;
+}
+
+sub fetch_dns_checksums {
+ my %checksums;
+ 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);
+ return \%checksums;
+}
+
# ------------------------------------------------------------ Read domain file
{
my $loaded;
@@ -10932,10 +13404,10 @@ sub get_dns {
}
sub load_domain_tab {
- my ($ignore_cache) = @_;
- &get_dns('/adm/dns/domain',\&parse_domain_tab,$ignore_cache);
+ my ($ignore_cache,$nocache) = @_;
+ &get_dns('/adm/dns/domain',\&parse_domain_tab,$ignore_cache,$nocache);
my $fh;
- if (open($fh,"<".$perlvar{'lonTabDir'}.'/domain.tab')) {
+ if (open($fh,"<",$perlvar{'lonTabDir'}.'/domain.tab')) {
my @lines = <$fh>;
&parse_domain_tab(\@lines);
}
@@ -10987,8 +13459,23 @@ sub get_dns {
my ($id,$domain,$role,$name,$protocol,$intdom)=split(/:/,$configline);
$name=~s/\s//g;
if ($id && $domain && $role && $name) {
+ if ((exists($hostname{$id})) && ($hostname{$id} ne '')) {
+ my $curr = $hostname{$id};
+ my $skip;
+ if (ref($name_to_host{$curr}) eq 'ARRAY') {
+ if (($curr eq $name) && (@{$name_to_host{$curr}} == 1)) {
+ $skip = 1;
+ } else {
+ @{$name_to_host{$curr}} = grep { $_ ne $id } @{$name_to_host{$curr}};
+ }
+ }
+ unless ($skip) {
+ push(@{$name_to_host{$name}},$id);
+ }
+ } else {
+ push(@{$name_to_host{$name}},$id);
+ }
$hostname{$id}=$name;
- push(@{$name_to_host{$name}}, $id);
$hostdom{$id}=$domain;
if ($role eq 'library') { $libserv{$id}=$name; }
if (defined($protocol)) {
@@ -11011,6 +13498,7 @@ sub get_dns {
&purge_remembered();
&reset_domain_info();
&reset_hosts_ip_info();
+ undef(%internetdom);
undef(%name_to_host);
undef(%hostname);
undef(%hostdom);
@@ -11019,9 +13507,9 @@ sub get_dns {
}
sub load_hosts_tab {
- my ($ignore_cache) = @_;
- &get_dns('/adm/dns/hosts',\&parse_hosts_tab,$ignore_cache);
- open(my $config,"<$perlvar{'lonTabDir'}/hosts.tab");
+ my ($ignore_cache,$nocache) = @_;
+ &get_dns('/adm/dns/hosts',\&parse_hosts_tab,$ignore_cache,$nocache);
+ open(my $config,"<","$perlvar{'lonTabDir'}/hosts.tab");
my @config = <$config>;
&parse_hosts_tab(\@config);
close($config);
@@ -11042,7 +13530,8 @@ sub get_dns {
}
sub all_names {
- &load_hosts_tab() if (!$loaded);
+ my ($ignore_cache,$nocache) = @_;
+ &load_hosts_tab($ignore_cache,$nocache) if (!$loaded);
return %name_to_host;
}
@@ -11052,6 +13541,11 @@ sub get_dns {
return %hostdom;
}
+ sub all_host_intdom {
+ &load_hosts_tab() if (!$loaded);
+ return %internetdom;
+ }
+
sub is_library {
&load_hosts_tab() if (!$loaded);
@@ -11164,7 +13658,7 @@ sub get_dns {
}
sub get_iphost {
- my ($ignore_cache) = @_;
+ my ($ignore_cache,$nocache) = @_;
if (!$ignore_cache) {
if (%iphost) {
@@ -11188,7 +13682,7 @@ sub get_dns {
%old_name_to_ip = %{$ip_info->[1]};
}
- my %name_to_host = &all_names();
+ my %name_to_host = &all_names($ignore_cache,$nocache);
foreach my $name (keys(%name_to_host)) {
my $ip;
if (!exists($name_to_ip{$name})) {
@@ -11213,9 +13707,11 @@ sub get_dns {
}
push(@{$iphost{$ip}},@{$name_to_host{$name}});
}
- &Apache::lonnet::do_cache_new('iphost','iphost',
- [\%iphost,\%name_to_ip,\%lonid_to_ip],
- 48*60*60);
+ unless ($nocache) {
+ &do_cache_new('iphost','iphost',
+ [\%iphost,\%name_to_ip,\%lonid_to_ip],
+ 48*60*60);
+ }
return %iphost;
}
@@ -11271,15 +13767,48 @@ sub get_dns {
}
$seen{$prim_ip} = 1;
}
- return &Apache::lonnet::do_cache_new('internetnames',$lonid,\@idns,12*60*60);
+ return &do_cache_new('internetnames',$lonid,\@idns,12*60*60);
}
}
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
+{
+ sub load_loncaparevs {
+ if (-e "$perlvar{'lonTabDir'}/loncaparevs.tab") {
+ if (open(my $config,"<","$perlvar{'lonTabDir'}/loncaparevs.tab")) {
+ while (my $configline=<$config>) {
+ chomp($configline);
+ my ($hostid,$loncaparev)=split(/:/,$configline);
+ $loncaparevs{$hostid}=$loncaparev;
+ }
+ close($config);
+ }
+ }
+ }
+}
+
+# ---------------------------------------------------------- Read serverhostID table
+{
+ sub load_serverhomeIDs {
+ if (-e "$perlvar{'lonTabDir'}/serverhomeIDs.tab") {
+ if (open(my $config,"<","$perlvar{'lonTabDir'}/serverhomeIDs.tab")) {
+ while (my $configline=<$config>) {
+ chomp($configline);
+ my ($name,$id)=split(/:/,$configline);
+ $serverhomeIDs{$name}=$id;
+ }
+ close($config);
+ }
+ }
+ }
}
+
BEGIN {
# ----------------------------------- Read loncapa.conf and loncapa_apache.conf
@@ -11292,7 +13821,7 @@ BEGIN {
# ------------------------------------------------------ Read spare server file
{
- open(my $config,"<$perlvar{'lonTabDir'}/spare.tab");
+ open(my $config,"<","$perlvar{'lonTabDir'}/spare.tab");
while (my $configline=<$config>) {
chomp($configline);
@@ -11306,7 +13835,7 @@ BEGIN {
}
# ------------------------------------------------------------ Read permissions
{
- open(my $config,"<$perlvar{'lonTabDir'}/roles.tab");
+ open(my $config,"<","$perlvar{'lonTabDir'}/roles.tab");
while (my $configline=<$config>) {
chomp($configline);
@@ -11320,7 +13849,7 @@ BEGIN {
# -------------------------------------------- Read plain texts for permissions
{
- open(my $config,"<$perlvar{'lonTabDir'}/rolesplain.tab");
+ open(my $config,"<","$perlvar{'lonTabDir'}/rolesplain.tab");
while (my $configline=<$config>) {
chomp($configline);
@@ -11340,7 +13869,7 @@ BEGIN {
# ---------------------------------------------------------- Read package table
{
- open(my $config,"<$perlvar{'lonTabDir'}/packages.tab");
+ open(my $config,"<","$perlvar{'lonTabDir'}/packages.tab");
while (my $configline=<$config>) {
if ($configline !~ /\S/ || $configline=~/^#/) { next; }
@@ -11356,33 +13885,14 @@ BEGIN {
}
# ---------------------------------------------------------- Read loncaparev table
-{
- if (-e "$perlvar{'lonTabDir'}/loncaparevs.tab") {
- if (open(my $config,"<$perlvar{'lonTabDir'}/loncaparevs.tab")) {
- while (my $configline=<$config>) {
- chomp($configline);
- my ($hostid,$loncaparev)=split(/:/,$configline);
- $loncaparevs{$hostid}=$loncaparev;
- }
- close($config);
- }
- }
-}
+
+&load_loncaparevs();
# ---------------------------------------------------------- Read serverhostID table
-{
- if (-e "$perlvar{'lonTabDir'}/serverhomeIDs.tab") {
- if (open(my $config,"<$perlvar{'lonTabDir'}/serverhomeIDs.tab")) {
- while (my $configline=<$config>) {
- chomp($configline);
- my ($name,$id)=split(/:/,$configline);
- $serverhomeIDs{$name}=$id;
- }
- close($config);
- }
- }
-}
+&load_serverhomeIDs();
+
+# ---------------------------------------------------------- Read releaseslist XML
{
my $file = $Apache::lonnet::perlvar{'lonTabDir'}.'/releaseslist.xml';
if (-e $file) {
@@ -11392,7 +13902,15 @@ BEGIN {
my $item = $token->[1];
my $name = $token->[2]{'name'};
my $value = $token->[2]{'value'};
- if ($item ne '' && $name ne '' && $value ne '') {
+ my $valuematch = $token->[2]{'valuematch'};
+ my $namematch = $token->[2]{'namematch'};
+ if ($item eq 'parameter') {
+ if (($namematch ne '') || (($name ne '') && ($value ne '' || $valuematch ne ''))) {
+ my $release = $parser->get_text();
+ $release =~ s/(^\s*|\s*$ )//gx;
+ $needsrelease{$item.':'.$name.':'.$value.':'.$valuematch.':'.$namematch} = $release;
+ }
+ } elsif ($item ne '' && $name ne '') {
my $release = $parser->get_text();
$release =~ s/(^\s*|\s*$ )//gx;
$needsrelease{$item.':'.$name.':'.$value} = $release;
@@ -11405,7 +13923,7 @@ BEGIN {
# ---------------------------------------------------------- Read managers table
{
if (-e "$perlvar{'lonTabDir'}/managers.tab") {
- if (open(my $config,"<$perlvar{'lonTabDir'}/managers.tab")) {
+ if (open(my $config,"<","$perlvar{'lonTabDir'}/managers.tab")) {
while (my $configline=<$config>) {
chomp($configline);
next if ($configline =~ /^\#/);
@@ -11581,8 +14099,8 @@ were new keys. I.E. 1:foo will become 1:
Calling convention:
- my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$uname,$home);
- &Apache::lonnet::cstore(\%newrecord,$symb,$courseid,$domain,$uname,$home);
+ my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$uname);
+ &Apache::lonnet::cstore(\%newrecord,$symb,$courseid,$domain,$uname,$laststore);
For more detailed information, see lonnet specific documentation.
@@ -11665,10 +14183,12 @@ the answer, and also caches if there is
=item *
X