--- loncom/lonnet/perl/lonnet.pm 2023/09/06 13:33:33 1.1172.2.146.2.15 +++ loncom/lonnet/perl/lonnet.pm 2016/07/25 19:50:44 1.1315 @@ -1,7 +1,7 @@ # The LearningOnline Network # TCP networking package # -# $Id: lonnet.pm,v 1.1172.2.146.2.15 2023/09/06 13:33:33 raeburn Exp $ +# $Id: lonnet.pm,v 1.1315 2016/07/25 19:50:44 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -74,11 +74,13 @@ use strict; use LWP::UserAgent(); use HTTP::Date; use Image::Magick; -use CGI::Cookie; -use vars qw(%perlvar %spareid %pr %prp $memcache %packagetab $tmpdir $deftex + +use Encode; + +use vars qw(%perlvar %spareid %pr %prp $memcache %packagetab $tmpdir $_64bit %env %protocol %loncaparevs %serverhomeIDs %needsrelease - %managerstab $passwdmin); + %managerstab); my (%badServerCache, $memcache, %courselogs, %accesshash, %domainrolehash, %userrolehash, $processmarker, $dumpcount, %coursedombuf, @@ -95,13 +97,10 @@ use Cache::Memcached; use Digest::MD5; use Math::Random; use File::MMagic; -use Net::CIDR; -use Sys::Hostname::FQDN(); use LONCAPA qw(:DEFAULT :match); use LONCAPA::Configuration; use LONCAPA::lonmetadata; use LONCAPA::Lond; -use LONCAPA::transliterate; use File::Copy; @@ -113,6 +112,7 @@ require Exporter; our @ISA = qw (Exporter); our @EXPORT = qw(%env); + # ------------------------------------ Logging (parameters, docs, slots, roles) { my $logid; @@ -127,27 +127,26 @@ our @EXPORT = qw(%env); $logid ++; my $now = time(); my $id=$now.'00000'.$$.'00000'.$logid; - my $ip = &get_requestor_ip(); - my $logentry = { - $id => { - 'exe_uname' => $env{'user.name'}, - 'exe_udom' => $env{'user.domain'}, - 'exe_time' => $now, - 'exe_ip' => $ip, - 'delflag' => $delflag, - 'logentry' => $storehash, - 'uname' => $uname, - 'udom' => $udom, - } + 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); + 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]; @@ -159,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); @@ -172,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); } @@ -230,6 +229,46 @@ 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 =~ /^(?:centos|redhat|scientific)(\d+)$/) { + if ($1 < 6) { + $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)) { @@ -266,10 +305,9 @@ sub get_server_loncaparev { if ($caller eq 'loncron') { my $ua=new LWP::UserAgent; $ua->timeout(4); - my $hostname = &hostname($lonhost); my $protocol = $protocol{$lonhost}; $protocol = 'http' if ($protocol ne 'https'); - my $url = $protocol.'://'.$hostname.'/adm/about.html'; + my $url = $protocol.'://'.&hostname($lonhost).'/adm/about.html'; my $request=new HTTP::Request('GET',$url); my $response=$ua->request($request); unless ($response->is_error()) { @@ -362,64 +400,8 @@ sub remote_devalidate_cache { my $items; return unless (ref($cachekeys) eq 'ARRAY'); my $cachestr = join('&',@{$cachekeys}); - return &reply('devalidatecache:'.&escape($cachestr),$lonhost); -} - -sub sign_lti { - my ($cdom,$cnum,$crsdef,$type,$context,$url,$ltinum,$keynum,$paramsref,$inforef) = @_; - my $chome; - if (&domain($cdom) ne '') { - if ($crsdef) { - $chome = &homeserver($cnum,$cdom); - } else { - $chome = &domain($cdom,'primary'); - } - } - if ($cdom && $chome && ($chome ne 'no_host')) { - if ((ref($paramsref) eq 'HASH') && - (ref($inforef) eq 'HASH')) { - my $rep; - if (grep { $_ eq $chome } ¤t_machine_ids()) { - # domain information is hosted on this machine - $rep = - &LONCAPA::Lond::sign_lti_payload($cdom,$cnum,$crsdef,$type, - $context,$url,$ltinum,$keynum, - $perlvar{'lonVersion'}, - $paramsref,$inforef); - if (ref($rep) eq 'HASH') { - return ('ok',$rep); - } - } else { - my ($escurl,$params,$info); - $escurl = &escape($url); - if (ref($paramsref) eq 'HASH') { - $params = &freeze_escape($paramsref); - } - if (ref($inforef) eq 'HASH') { - $info = &freeze_escape($inforef); - } - $rep=&reply("encrypt:signlti:$cdom:$cnum:$crsdef:$type:$context:$escurl:$ltinum:$keynum:$params:$info",$chome); - } - if (($rep eq '') || ($rep =~ /^con_lost|error|no_such_host|unknown_cmd/i)) { - return (); - } elsif (($inforef->{'respfmt'} eq 'to_post_body') || - ($inforef->{'respfmt'} eq 'to_authorization_header')) { - return ('ok',$rep); - } else { - my %returnhash; - foreach my $item (split(/\&/,$rep)) { - my ($name,$value)=split(/\=/,$item); - $returnhash{&unescape($name)}=&thaw_unescape($value); - } - return('ok',\%returnhash); - } - } else { - return (); - } - } else { - return (); - &logthis("sign_lti failed - no homeserver and/or domain ($cdom) ($chome)"); - } + my $response = &reply('devalidatecache:'.&escape($cachestr),$lonhost); + return $response; } # -------------------------------------------------- Non-critical communication @@ -451,7 +433,7 @@ sub subreply { } else { &create_connection(&hostname($server),$server); } - sleep(0.1); # Try again later if failed connection. + sleep(0.1); # Try again later if failed connection. } my $answer; if ($client) { @@ -470,27 +452,8 @@ sub reply { unless (defined(&hostname($server))) { return 'no_such_host'; } my $answer=subreply($cmd,$server); if (($answer=~/^refused/) || ($answer=~/^rejected/)) { - my $logged = $cmd; - if ($cmd =~ /^encrypt:([^:]+):/) { - my $subcmd = $1; - if (($subcmd eq 'auth') || ($subcmd eq 'passwd') || - ($subcmd eq 'changeuserauth') || ($subcmd eq 'makeuser') || - ($subcmd eq 'putdom') || ($subcmd eq 'autoexportgrades') || - ($subcmd eq 'put')) { - (undef,undef,my @rest) = split(/:/,$cmd); - if (($subcmd eq 'auth') || ($subcmd eq 'putdom')) { - splice(@rest,2,1,'Hidden'); - } elsif ($subcmd eq 'passwd') { - splice(@rest,2,2,('Hidden','Hidden')); - } elsif (($subcmd eq 'changeuserauth') || ($subcmd eq 'makeuser') || - ($subcmd eq 'autoexportgrades') || ($subcmd eq 'put')) { - splice(@rest,3,1,'Hidden'); - } - $logged = join(':',('encrypt:'.$subcmd,@rest)); - } - } - &logthis("WARNING:". - " $logged to $server returned $answer"); + &logthis("WARNING:". + " $cmd to $server returned $answer"); } return $answer; } @@ -518,14 +481,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"); @@ -558,7 +521,7 @@ sub critical { $dumpcount++; { my $dfh; - if (open($dfh,">",$dfilename)) { + if (open($dfh,">$dfilename")) { print $dfh "$cmd\n"; close($dfh); } @@ -567,7 +530,7 @@ sub critical { my $wcmd=''; { my $dfh; - if (open($dfh,"<",$dfilename)) { + if (open($dfh,"<$dfilename")) { $wcmd=<$dfh>; close($dfh); } @@ -683,52 +646,22 @@ sub transfer_profile_to_env { # ---------------------------------------------------- Check for valid session sub check_for_valid_session { - my ($r,$name,$userhashref,$domref) = @_; + my ($r,$name,$userhashref) = @_; my %cookies=CGI::Cookie->parse($r->header_in('Cookie')); - my ($lonidsdir,$linkname,$pubname,$secure,$lonid); - if ($name eq 'lonDAV') { - $lonidsdir=$r->dir_config('lonDAVsessDir'); - } else { - $lonidsdir=$r->dir_config('lonIDsDir'); - if ($name eq '') { - $name = 'lonID'; - } - } - if ($name eq 'lonID') { - $secure = 'lonSID'; - $linkname = 'lonLinkID'; - $pubname = 'lonPubID'; - if (exists($cookies{$secure})) { - $lonid=$cookies{$secure}; - } elsif (exists($cookies{$name})) { - $lonid=$cookies{$name}; - } elsif ((exists($cookies{$linkname})) && ($ENV{'SERVER_PORT'} != 443)) { - $lonid=$cookies{$linkname}; - } elsif (exists($cookies{$pubname})) { - $lonid=$cookies{$pubname}; - } - } else { - $lonid=$cookies{$name}; + if ($name eq '') { + $name = 'lonID'; } + my $lonid=$cookies{$name}; return undef if (!$lonid); my $handle=&LONCAPA::clean_handle($lonid->value); - if (-l "$lonidsdir/$handle.id") { - my $link = readlink("$lonidsdir/$handle.id"); - if ((-e $link) && ($link =~ m{^\Q$lonidsdir\E/(.+)\.id$})) { - $handle = $1; - } - } - 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 $lonidsdir; + if ($name eq 'lonDAV') { + $lonidsdir=$r->dir_config('lonDAVsessDir'); + } else { + $lonidsdir=$r->dir_config('lonIDsDir'); } + return undef if (!-e "$lonidsdir/$handle.id"); my $opened = open(my $idf,'+<',"$lonidsdir/$handle.id"); return undef if (!$opened); @@ -742,23 +675,13 @@ sub check_for_valid_session { if (!defined($disk_env{'user.name'}) || !defined($disk_env{'user.domain'})) { - untie(%disk_env); return undef; } if (ref($userhashref) eq 'HASH') { $userhashref->{'name'} = $disk_env{'user.name'}; $userhashref->{'domain'} = $disk_env{'user.domain'}; - if ($disk_env{'request.role'}) { - $userhashref->{'role'} = $disk_env{'request.role'}; - } - $userhashref->{'lti'} = $disk_env{'request.lti.login'}; - if ($userhashref->{'lti'}) { - $userhashref->{'ltitarget'} = $disk_env{'request.lti.target'}; - $userhashref->{'ltiuri'} = $disk_env{'request.lti.uri'}; - } } - untie(%disk_env); return $handle; } @@ -783,37 +706,6 @@ sub timed_flock { } } -sub get_sessionfile_vars { - my ($handle,$lonidsdir,$storearr) = @_; - my %returnhash; - unless (ref($storearr) eq 'ARRAY') { - return %returnhash; - } - if (-l "$lonidsdir/$handle.id") { - my $link = readlink("$lonidsdir/$handle.id"); - if ((-e $link) && ($link =~ m{^\Q$lonidsdir\E/(.+)\.id$})) { - $handle = $1; - } - } - if ((-e "$lonidsdir/$handle.id") && - ($handle =~ /^($match_username)\_\d+\_($match_domain)\_(.+)$/)) { - my ($possuname,$possudom,$possuhome) = ($1,$2,$3); - if ((&domain($possudom) ne '') && (&homeserver($possuname,$possudom) eq $possuhome)) { - if (open(my $idf,'+<',"$lonidsdir/$handle.id")) { - flock($idf,LOCK_SH); - if (tie(my %disk_env,'GDBM_File',"$lonidsdir/$handle.id", - &GDBM_READER(),0640)) { - foreach my $item (@{$storearr}) { - $returnhash{$item} = $disk_env{$item}; - } - untie(%disk_env); - } - } - } - } - return %returnhash; -} - # ---------------------------------------------------------- Append Environment sub appenv { @@ -839,19 +731,16 @@ sub appenv { $env{$key}=$newenv->{$key}; } } - my $lonids = $perlvar{'lonIDsDir'}; - if ($env{'user.environment'} =~ m{^\Q$lonids/\E$match_username\_\d+\_$match_domain\_[\w\-.]+\.id$}) { - my $opened = open(my $env_file,'+<',$env{'user.environment'}); - if ($opened - && &timed_flock($env_file,LOCK_EX) - && - tie(my %disk_env,'GDBM_File',$env{'user.environment'}, - (&GDBM_WRITER()|&GDBM_NOLOCK()),0640)) { - while (my ($key,$value) = each(%{$newenv})) { - $disk_env{$key} = $value; - } - untie(%disk_env); - } + my $opened = open(my $env_file,'+<',$env{'user.environment'}); + if ($opened + && &timed_flock($env_file,LOCK_EX) + && + tie(my %disk_env,'GDBM_File',$env{'user.environment'}, + (&GDBM_WRITER()|&GDBM_NOLOCK()),0640)) { + while (my ($key,$value) = each(%{$newenv})) { + $disk_env{$key} = $value; + } + untie(%disk_env); } } return 'ok'; @@ -967,7 +856,6 @@ sub userload { while ($filename=readdir(LONIDS)) { next if ($filename eq '.' || $filename eq '..'); next if ($filename =~ /publicuser_\d+\.id/); - next if ($filename =~ /^[a-f0-9]+_linked\.id$/); my ($mtime)=(stat($perlvar{'lonIDsDir'}.'/'.$filename))[9]; if ($curtime-$mtime < 1800) { $numusers++; } } @@ -985,7 +873,7 @@ sub userload { # ------------------------------ Find server with least workload from spare.tab sub spareserver { - my ($r,$loadpercent,$userloadpercent,$want_server_name,$udom) = @_; + my ($loadpercent,$userloadpercent,$want_server_name,$udom) = @_; my $spare_server; if ($userloadpercent !~ /\d/) { $userloadpercent=0; } my $lowest_load=($loadpercent > $userloadpercent) ? $loadpercent @@ -1023,15 +911,13 @@ sub spareserver { } if (!$want_server_name) { + my $protocol = 'http'; + if ($protocol{$spare_server} eq 'https') { + $protocol = $protocol{$spare_server}; + } if (defined($spare_server)) { my $hostname = &hostname($spare_server); if (defined($hostname)) { - my $protocol = 'http'; - if ($protocol{$spare_server} eq 'https') { - $protocol = $protocol{$spare_server}; - } - my $alias = &Apache::lonnet::use_proxy_alias($r,$spare_server); - $hostname = $alias if ($alias ne ''); $spare_server = $protocol.'://'.$hostname; } } @@ -1098,104 +984,6 @@ sub find_existing_session { return; } -sub delusersession { - my ($lonid,$udom,$uname) = @_; - my $uprimary_id = &domain($udom,'primary'); - my $uintdom = &internet_dom($uprimary_id); - my $intdom = &internet_dom($lonid); - my $serverhomedom = &host_domain($lonid); - if (($uintdom ne '') && ($uintdom eq $intdom)) { - return &reply(join(':','delusersession', - map {&escape($_)} ($udom,$uname)),$lonid); - } - return; -} - - -# check if user's browser sent load balancer cookie and server still has session -# and is not overloaded. -sub check_for_balancer_cookie { - my ($r,$update_mtime) = @_; - my ($otherserver,$cookie); - my %cookies=CGI::Cookie->parse($r->header_in('Cookie')); - if (exists($cookies{'balanceID'})) { - my $balid = $cookies{'balanceID'}; - $cookie=&LONCAPA::clean_handle($balid->value); - my $balancedir=$r->dir_config('lonBalanceDir'); - if ((-d $balancedir) && (-e "$balancedir/$cookie.id")) { - if ($cookie =~ /^($match_domain)_($match_username)_[a-f0-9]+$/) { - my ($possudom,$possuname) = ($1,$2); - my $has_session = 0; - if ((&domain($possudom) ne '') && - (&homeserver($possuname,$possudom) ne 'no_host')) { - my $try_server; - my $opened = open(my $idf,'+<',"$balancedir/$cookie.id"); - if ($opened) { - flock($idf,LOCK_SH); - while (my $line = <$idf>) { - chomp($line); - if (&hostname($line) ne '') { - $try_server = $line; - last; - } - } - close($idf); - if (($try_server) && - (&has_user_session($try_server,$possudom,$possuname))) { - my $lowest_load = 30000; - ($otherserver,$lowest_load) = - &compare_server_load($try_server,undef,$lowest_load); - if ($otherserver ne '' && $lowest_load < 100) { - $has_session = 1; - } else { - undef($otherserver); - } - } - } - } - if ($has_session) { - if ($update_mtime) { - my $atime = my $mtime = time; - utime($atime,$mtime,"$balancedir/$cookie.id"); - } - } else { - unlink("$balancedir/$cookie.id"); - } - } - } - } - return ($otherserver,$cookie); -} - -sub updatebalcookie { - my ($cookie,$balancer,$lastentry)=@_; - if ($cookie =~ /^($match_domain)\_($match_username)\_[a-f0-9]{32}$/) { - my ($udom,$uname) = ($1,$2); - my $uprimary_id = &domain($udom,'primary'); - my $uintdom = &internet_dom($uprimary_id); - my $intdom = &internet_dom($balancer); - my $serverhomedom = &host_domain($balancer); - if (($uintdom ne '') && ($uintdom eq $intdom)) { - return &reply('updatebalcookie:'.&escape($cookie).':'.&escape($lastentry),$balancer); - } - } - return; -} - -sub delbalcookie { - my ($cookie,$balancer) =@_; - if ($cookie =~ /^($match_domain)\_($match_username)\_[a-f0-9]{32}$/) { - my ($udom,$uname) = ($1,$2); - my $uprimary_id = &domain($udom,'primary'); - my $uintdom = &internet_dom($uprimary_id); - my $intdom = &internet_dom($balancer); - my $serverhomedom = &host_domain($balancer); - if (($uintdom ne '') && ($uintdom eq $intdom)) { - return &reply('delbalcookie:'.&escape($cookie),$balancer); - } - } -} - # -------------------------------- ask if server already has a session for user sub has_user_session { my ($lonid,$udom,$uname) = @_; @@ -1227,12 +1015,12 @@ sub choose_server { } } foreach my $lonhost (keys(%servers)) { - my $loginvia; if ($skiploadbal) { if (ref($balancers) eq 'HASH') { next if (exists($balancers->{$lonhost})); } - } + } + my $loginvia; if ($checkloginvia) { $loginvia = $domconfhash{$udom.'.login.loginvia_'.$lonhost}; if ($loginvia) { @@ -1259,29 +1047,7 @@ sub choose_server { if ($login_host ne '') { $hostname = &hostname($login_host); } - return ($login_host,$hostname,$portal_path,$isredirect,$lowest_load); -} - -sub get_course_sessions { - my ($cnum,$cdom,$lastactivity) = @_; - my %servers = &internet_dom_servers($cdom); - my %returnhash; - foreach my $server (sort(keys(%servers))) { - my $rep = &reply("coursesessions:$cdom:$cnum:$lastactivity",$server); - my @pairs=split(/\&/,$rep); - unless (($rep eq 'unknown_cmd') || ($rep =~ /^error/)) { - foreach my $item (@pairs) { - my ($key,$value)=split(/=/,$item,2); - $key = &unescape($key); - next if ($key =~ /^error: 2 /); - if (exists($returnhash{$key})) { - next if ($value < $returnhash{$key}); - } - $returnhash{$key}=$value; - } - } - } - return %returnhash; + return ($login_host,$hostname,$portal_path,$isredirect); } # --------------------------------------------- Try to change a user's password @@ -1319,9 +1085,6 @@ sub changepass { } elsif ($answer =~ "invalid_client") { &logthis("$server refused to change $uname in $udom password because ". "it was a reset by e-mail originating from an invalid server."); - } elsif ($answer =~ "^prioruse") { - &logthis("$server refused to change $uname in $udom password because ". - "the password had been used before"); } return $answer; } @@ -1331,7 +1094,7 @@ sub changepass { sub queryauthenticate { my ($uname,$udom)=@_; my $uhome=&homeserver($uname,$udom); - if ((!$uhome) || ($uhome eq 'no_host')) { + if (!$uhome) { &logthis("User $uname at $udom is unknown when looking for authentication mechanism"); return 'no_host'; } @@ -1380,35 +1143,12 @@ sub authenticate { } if ($answer eq 'non_authorized') { &logthis("User $uname at $udom rejected by $uhome"); - return 'no_host'; + return 'no_host'; } &logthis("User $uname at $udom threw error $answer when checking authentication mechanism"); return 'no_host'; } -sub can_switchserver { - my ($udom,$home) = @_; - my ($canswitch,@intdoms); - my $internet_names = &get_internet_names($home); - if (ref($internet_names) eq 'ARRAY') { - @intdoms = @{$internet_names}; - } - my $uint_dom = &internet_dom(&domain($udom,'primary')); - if ($uint_dom ne '' && grep(/^\Q$uint_dom\E$/,@intdoms)) { - $canswitch = 1; - } else { - my $serverhomeID = &get_server_homeID(&hostname($home)); - my $serverhomedom = &host_domain($serverhomeID); - my %defdomdefaults = &get_domain_defaults($serverhomedom); - my %udomdefaults = &get_domain_defaults($udom); - my $remoterev = &get_server_loncaparev('',$home); - $canswitch = &can_host_session($udom,$home,$remoterev, - $udomdefaults{'remotesessions'}, - $defdomdefaults{'hostedsessions'}); - } - return $canswitch; -} - sub can_host_session { my ($udom,$lonhost,$remoterev,$remotesessions,$hostedsessions) = @_; my $canhost = 1; @@ -1483,15 +1223,6 @@ sub spare_can_host { $canhost = 0; } } - if ($canhost) { - if (ref($defdomdefaults{'offloadoth'}) eq 'HASH') { - if ($defdomdefaults{'offloadoth'}{$try_server}) { - unless (&shared_institution($udom,$try_server)) { - $canhost = 0; - } - } - } - } if (($canhost) && ($uint_dom)) { my @intdoms; my $internet_names = &get_internet_names($try_server); @@ -1588,16 +1319,16 @@ sub get_lonbalancer_config { } sub check_loadbalancing { - my ($uname,$udom,$caller) = @_; + my ($uname,$udom) = @_; my ($is_balancer,$currtargets,$currrules,$dom_in_use,$homeintdom, - $rule_in_effect,$offloadto,$otherserver,$setcookie); + $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 $domneedscache; my $cachetime = 60*60*24; if (($uintdom ne '') && ($uintdom eq $intdom)) { @@ -1617,7 +1348,7 @@ sub check_loadbalancing { } } if (ref($result) eq 'HASH') { - ($is_balancer,$currtargets,$currrules,$setcookie) = + ($is_balancer,$currtargets,$currrules) = &check_balancer_result($result,@hosts); if ($is_balancer) { if (ref($currrules) eq 'HASH') { @@ -1678,7 +1409,7 @@ sub check_loadbalancing { } } if (ref($result) eq 'HASH') { - ($is_balancer,$currtargets,$currrules,$setcookie) = + ($is_balancer,$currtargets,$currrules) = &check_balancer_result($result,@hosts); if ($is_balancer) { if (ref($currrules) eq 'HASH') { @@ -1710,7 +1441,7 @@ sub check_loadbalancing { if ($domneedscache) { &do_cache_new('loadbalancing',$domneedscache,$is_balancer,$cachetime); } - if (($is_balancer) && ($caller ne 'switchserver')) { + if ($is_balancer) { my $lowest_load = 30000; if (ref($offloadto) eq 'HASH') { if (ref($offloadto->{'primary'}) eq 'ARRAY') { @@ -1739,27 +1470,23 @@ sub check_loadbalancing { } } } - 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}); - } + 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}); } } } } - if (($is_balancer) && (!$homeintdom)) { - undef($setcookie); - } - return ($is_balancer,$otherserver,$setcookie); + return ($is_balancer,$otherserver); } sub check_balancer_result { my ($result,@hosts) = @_; - my ($is_balancer,$currtargets,$currrules,$setcookie); + my ($is_balancer,$currtargets,$currrules); if (ref($result) eq 'HASH') { if ($result->{'lonhost'} ne '') { my $currbalancer = $result->{'lonhost'}; @@ -1775,13 +1502,12 @@ sub check_balancer_result { $is_balancer = 1; $currrules = $result->{$key}{'rules'}; $currtargets = $result->{$key}{'targets'}; - $setcookie = $result->{$key}{'cookie'}; last; } } } } - return ($is_balancer,$currtargets,$currrules,$setcookie); + return ($is_balancer,$currtargets,$currrules); } sub get_loadbalancer_targets { @@ -1878,17 +1604,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('&', map { &escape($_); } @ids); - $idlist=~tr/A-Z/a-z/; - my $reply=&reply("idget:$udom:".$idlist,$tryserver); + 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); @@ -1897,9 +1639,9 @@ sub idget { for ($i=0;$i<=$#ids;$i++) { if ($answer[$i]) { $returnhash{$ids[$i]}=&unescape($answer[$i]); - } + } } - } + } return %returnhash; } @@ -1914,60 +1656,141 @@ 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 IDs from ids.db file +# ------------- Delete unwanted student/employee IDs or clicker IDs from domain sub iddel { - my ($udom,$idshashref,$uhome)=@_; + my ($udom,$idshashref,$uhome,$namespace)=@_; my %result=(); - unless (ref($idshashref) eq 'HASH') { + my %ids=(); + my %byid = (); + if (ref($idshashref) eq 'HASH') { + %ids=%{$idshashref}; + } else { return %result; } + if ($namespace eq '') { + $namespace = 'ids'; + } my %servers=(); - while (my ($id,$uname) = each(%{$idshashref})) { - my $uhom; - if ($uhome) { - $uhom = $uhome; - } else { - $uhom=&homeserver($uname,$udom); - } - if ($uhom ne 'no_host') { - if ($servers{$uhom}) { + 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 { - $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)) { - $result{$server} = &critical('iddel:'.$udom.':'.$servers{$server},$uhome); + $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); + } +} + # ------------------------------dump from db file owned by domainconfig user sub dump_dom { my ($namespace, $udom, $regexp) = @_; @@ -1982,7 +1805,7 @@ sub dump_dom { # ------------------------------------------ get items from domain db files sub get_dom { - my ($namespace,$storearr,$udom,$uhome,$encrypt)=@_; + my ($namespace,$storearr,$udom,$uhome)=@_; return if ($udom eq 'public'); my $items=''; foreach my $item (@$storearr) { @@ -2005,17 +1828,7 @@ sub get_dom { } } if ($udom && $uhome && ($uhome ne 'no_host')) { - my $rep; - if (grep { $_ eq $uhome } ¤t_machine_ids()) { - # domain information is hosted on this machine - $rep = &LONCAPA::Lond::get_dom("getdom:$udom:$namespace:$items"); - } else { - if ($encrypt) { - $rep=&reply("encrypt:egetdom:$udom:$namespace:$items",$uhome); - } else { - $rep=&reply("getdom:$udom:$namespace:$items",$uhome); - } - } + my $rep=&reply("getdom:$udom:$namespace:$items",$uhome); my %returnhash; if ($rep eq '' || $rep =~ /^error: 2 /) { return %returnhash; @@ -2038,7 +1851,7 @@ sub get_dom { # -------------------------------------------- put items in domain db files sub put_dom { - my ($namespace,$storehash,$udom,$uhome,$encrypt)=@_; + my ($namespace,$storehash,$udom,$uhome)=@_; if (!$udom) { $udom=$env{'user.domain'}; if (defined(&domain($udom,'primary'))) { @@ -2059,11 +1872,7 @@ sub put_dom { $items.=&escape($item).'='.&freeze_escape($$storehash{$item}).'&'; } $items=~s/\&$//; - if ($encrypt) { - return &reply("encrypt:putdom:$udom:$namespace:$items",$uhome); - } else { - return &reply("putdom:$udom:$namespace:$items",$uhome); - } + return &reply("putdom:$udom:$namespace:$items",$uhome); } else { &logthis("put_dom failed - no homeserver and/or domain"); } @@ -2097,57 +1906,6 @@ sub del_dom { } } -sub store_dom { - my ($storehash,$id,$namespace,$dom,$home,$encrypt) = @_; - $$storehash{'ip'}=&get_requestor_ip(); - $$storehash{'host'}=$perlvar{'lonHostID'}; - my $namevalue=''; - foreach my $key (keys(%{$storehash})) { - $namevalue.=&escape($key).'='.&freeze_escape($$storehash{$key}).'&'; - } - $namevalue=~s/\&$//; - if (grep { $_ eq $home } current_machine_ids()) { - return LONCAPA::Lond::store_dom("storedom:$dom:$namespace:$id:$namevalue"); - } else { - if ($namespace eq 'private') { - return 'refused'; - } elsif ($encrypt) { - return reply("encrypt:storedom:$dom:$namespace:$id:$namevalue",$home); - } else { - return reply("storedom:$dom:$namespace:$id:$namevalue",$home); - } - } -} - -sub restore_dom { - my ($id,$namespace,$dom,$home,$encrypt) = @_; - my $answer; - if (grep { $_ eq $home } current_machine_ids()) { - $answer = LONCAPA::Lond::restore_dom("restoredom:$dom:$namespace:$id"); - } elsif ($namespace ne 'private') { - if ($encrypt) { - $answer=&reply("encrypt:restoredom:$dom:$namespace:$id",$home); - } else { - $answer=&reply("restoredom:$dom:$namespace:$id",$home); - } - } - my %returnhash=(); - unless (($answer eq '') || ($answer eq 'con_lost') || ($answer eq 'refused') || - ($answer eq 'unknown_cmd') || ($answer eq 'rejected')) { - foreach my $line (split(/\&/,$answer)) { - my ($name,$value)=split(/\=/,$line); - $returnhash{&unescape($name)}=&thaw_unescape($value); - } - my $version; - for ($version=1;$version<=$returnhash{'version'};$version++) { - foreach my $item (split(/\:/,$returnhash{$version.':keys'})) { - $returnhash{$item}=$returnhash{$version.':'.$item}; - } - } - } - return %returnhash; -} - # ----------------------------------construct domainconfig user for a domain sub get_domainconfiguser { my ($udom) = @_; @@ -2190,7 +1948,7 @@ sub retrieve_inst_usertypes { sub is_domainimage { my ($url) = @_; - if ($url=~m-^/+res/+($match_domain)/+\1\-domainconfig/+(img|logo|domlogo|login)/+[^/]-) { + if ($url=~m-^/+res/+($match_domain)/+\1\-domainconfig/+(img|logo|domlogo)/+[^/]-) { if (&domain($1) ne '') { return '1'; } @@ -2205,24 +1963,13 @@ 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($udom,$homeserver); - my ($major,$minor,$subver) = ($lcrev =~ /^\'?(\d+)\.(\d+)\.(\d+)[\w.\-]+\'?$/); - if (($major eq '' && $minor eq '') || ($major < 2) || - (($major == 2) && ($minor < 11)) || - (($major == 2) && ($minor == 11) && ($subver < 3))) { - 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('institutional directory search invalid queryid: '.$queryid.' for host: '.$homeserver.' in domain '.$udom); + &logthis('instituional directory search invalid queryid: '.$queryid.' for host: '.$homeserver.'in domain '.$udom); return; } my $response = &get_query_reply($queryid); @@ -2257,15 +2004,6 @@ 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($dom,$tryserver); - my ($major,$minor,$subver) = ($lcrev =~ /^\'?(\d+)\.(\d+)\.(\d+)[\w.\-]+\'?$/); - next if (($major eq '' && $minor eq '') || ($major < 2) || - (($major == 2) && ($minor < 11)) || - (($major == 2) && ($minor == 11) && ($subver < 3))); - } - } my $host=&hostname($tryserver); my $queryid= &reply("querysend:".&escape($query).':'. @@ -2355,7 +2093,7 @@ sub get_multiple_instusers { my ($udom,$users,$caller) = @_; my ($outcome,$results); if (ref($users) eq 'HASH') { - my $count = keys(%{$users}); + my $count = keys(%{$users}); my $requested = &freeze_escape($users); my $homeserver = &domain($udom,'primary'); if ($homeserver ne '') { @@ -2399,7 +2137,7 @@ sub get_multiple_instusers { } else { ($outcome,my $userdata) = split(/=/,$response,2); if ($outcome eq 'ok') { - $results = &thaw_unescape($userdata); + $results = &thaw_unescape($userdata); } } } @@ -2426,10 +2164,6 @@ sub inst_rulecheck { $response=&unescape(&reply('instidrulecheck:'.&escape($udom). ':'.&escape($id).':'.$rulestr, $homeserver)); - } elsif ($item eq 'unamemap') { - $response=&unescape(&reply('instunamemapcheck:'. - &escape($udom).':'.&escape($uname). - ':'.$rulestr,$homeserver)); } elsif ($item eq 'selfcreate') { $response=&unescape(&reply('instselfcreatecheck:'. &escape($udom).':'.&escape($uname). @@ -2463,9 +2197,6 @@ sub inst_userrules { } elsif ($check eq 'email') { $response=&reply('instemailrules:'.&escape($udom), $homeserver); - } elsif ($check eq 'unamemap') { - $response=&reply('unamemaprules:'.&escape($udom), - $homeserver); } else { $response=&reply('instuserrules:'.&escape($udom), $homeserver); @@ -2511,11 +2242,8 @@ sub get_domain_defaults { 'requestcourses','inststatus', 'coursedefaults','usersessions', 'requestauthor','selfenrollment', - 'coursecategories','autoenroll', - 'helpsettings','wafproxy','ltisec', - 'toolsec','domexttool','exttool'], - $domain); - my @coursetypes = ('official','unofficial','community','textbook'); + 'coursecategories','ssl','autoenroll'],$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'}; @@ -2523,12 +2251,6 @@ 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{'portal_def_email'} = $domconfig{'defaults'}{'portal_def_email'}; - $domdefaults{'portal_def_web'} = $domconfig{'defaults'}{'portal_def_web'}; - $domdefaults{'intauth_cost'} = $domconfig{'defaults'}{'intauth_cost'}; - $domdefaults{'intauth_switch'} = $domconfig{'defaults'}{'intauth_switch'}; - $domdefaults{'intauth_check'} = $domconfig{'defaults'}{'intauth_check'}; - $domdefaults{'unamemap_rule'} = $domconfig{'defaults'}{'unamemap_rule'}; } else { $domdefaults{'lang_def'} = &domain($domain,'lang_def'); $domdefaults{'auth_def'} = &domain($domain,'auth_def'); @@ -2551,7 +2273,7 @@ sub get_domain_defaults { } } if (ref($domconfig{'requestcourses'}) eq 'HASH') { - foreach my $item ('official','unofficial','community','textbook') { + foreach my $item ('official','unofficial','community','textbook','placement') { $domdefaults{$item} = $domconfig{'requestcourses'}{$item}; } } @@ -2564,8 +2286,8 @@ sub get_domain_defaults { } } if (ref($domconfig{'coursedefaults'}) eq 'HASH') { + $domdefaults{'canuse_pdfforms'} = $domconfig{'coursedefaults'}{'canuse_pdfforms'}; $domdefaults{'usejsme'} = $domconfig{'coursedefaults'}{'usejsme'}; - $domdefaults{'inline_chem'} = $domconfig{'coursedefaults'}{'inline_chem'}; $domdefaults{'uselcmath'} = $domconfig{'coursedefaults'}{'uselcmath'}; if (ref($domconfig{'coursedefaults'}{'postsubmit'}) eq 'HASH') { $domdefaults{'postsubmit'} = $domconfig{'coursedefaults'}{'postsubmit'}{'client'}; @@ -2579,25 +2301,12 @@ sub get_domain_defaults { if (ref($domconfig{'coursedefaults'}{'uploadquota'}) eq 'HASH') { $domdefaults{$type.'quota'} = $domconfig{'coursedefaults'}{'uploadquota'}{$type}; } - if (ref($domconfig{'coursedefaults'}{'coursequota'}) eq 'HASH') { - $domdefaults{$type.'coursequota'} = $domconfig{'coursedefaults'}{'coursequota'}{$type}; - } if ($domdefaults{'postsubmit'} eq 'on') { if (ref($domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') { - $domdefaults{$type.'postsubtimeout'} = - $domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}{$type}; + $domdefaults{$type.'postsubtimeout'} = + $domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}{$type}; } } - if (ref($domconfig{'coursedefaults'}{'domexttool'}) eq 'HASH') { - $domdefaults{$type.'domexttool'} = $domconfig{'coursedefaults'}{'domexttool'}{$type}; - } else { - $domdefaults{$type.'domexttool'} = 1; - } - if (ref($domconfig{'coursedefaults'}{'exttool'}) eq 'HASH') { - $domdefaults{$type.'exttool'} = $domconfig{'coursedefaults'}{'exttool'}{$type}; - } else { - $domdefaults{$type.'exttool'} = 0; - } } if (ref($domconfig{'coursedefaults'}{'canclone'}) eq 'HASH') { if (ref($domconfig{'coursedefaults'}{'canclone'}{'instcode'}) eq 'ARRAY') { @@ -2609,12 +2318,6 @@ sub get_domain_defaults { } elsif ($domconfig{'coursedefaults'}{'canclone'}) { $domdefaults{'canclone'}=$domconfig{'coursedefaults'}{'canclone'}; } - if ($domconfig{'coursedefaults'}{'texengine'}) { - $domdefaults{'texengine'} = $domconfig{'coursedefaults'}{'texengine'}; - } - if (exists($domconfig{'coursedefaults'}{'ltiauth'})) { - $domdefaults{'crsltiauth'} = $domconfig{'coursedefaults'}{'ltiauth'}; - } } if (ref($domconfig{'usersessions'}) eq 'HASH') { if (ref($domconfig{'usersessions'}{'remote'}) eq 'HASH') { @@ -2626,9 +2329,6 @@ sub get_domain_defaults { if (ref($domconfig{'usersessions'}{'offloadnow'}) eq 'HASH') { $domdefaults{'offloadnow'} = $domconfig{'usersessions'}{'offloadnow'}; } - if (ref($domconfig{'usersessions'}{'offloadoth'}) eq 'HASH') { - $domdefaults{'offloadoth'} = $domconfig{'usersessions'}{'offloadoth'}; - } } if (ref($domconfig{'selfenrollment'}) eq 'HASH') { if (ref($domconfig{'selfenrollment'}{'admin'}) eq 'HASH') { @@ -2661,142 +2361,30 @@ sub get_domain_defaults { if (ref($domconfig{'coursecategories'}) eq 'HASH') { $domdefaults{'catauth'} = 'std'; $domdefaults{'catunauth'} = 'std'; - if ($domconfig{'coursecategories'}{'auth'}) { + if ($domconfig{'coursecategories'}{'auth'}) { $domdefaults{'catauth'} = $domconfig{'coursecategories'}{'auth'}; } if ($domconfig{'coursecategories'}{'unauth'}) { $domdefaults{'catunauth'} = $domconfig{'coursecategories'}{'unauth'}; } } - if (ref($domconfig{'autoenroll'}) eq 'HASH') { - $domdefaults{'autofailsafe'} = $domconfig{'autoenroll'}{'autofailsafe'}; - $domdefaults{'failsafe'} = $domconfig{'autoenroll'}{'failsafe'}; - } - if (ref($domconfig{'helpsettings'}) eq 'HASH') { - $domdefaults{'submitbugs'} = $domconfig{'helpsettings'}{'submitbugs'}; - if (ref($domconfig{'helpsettings'}{'adhoc'}) eq 'HASH') { - $domdefaults{'adhocroles'} = $domconfig{'helpsettings'}{'adhoc'}; + if (ref($domconfig{'ssl'}) eq 'HASH') { + if (ref($domconfig{'ssl'}{'replication'}) eq 'HASH') { + $domdefaults{'replication'} = $domconfig{'ssl'}{'replication'}; } - } - if (ref($domconfig{'wafproxy'}) eq 'HASH') { - foreach my $item ('ipheader','trusted','vpnint','vpnext','sslopt') { - if ($domconfig{'wafproxy'}{$item}) { - $domdefaults{'waf_'.$item} = $domconfig{'wafproxy'}{$item}; - } - } - } - if (ref($domconfig{'ltisec'}) eq 'HASH') { - if (ref($domconfig{'ltisec'}{'encrypt'}) eq 'HASH') { - $domdefaults{'linkprotenc_crs'} = $domconfig{'ltisec'}{'encrypt'}{'crs'}; - $domdefaults{'linkprotenc_dom'} = $domconfig{'ltisec'}{'encrypt'}{'dom'}; - $domdefaults{'ltienc_consumers'} = $domconfig{'ltisec'}{'encrypt'}{'consumers'}; - } - if (ref($domconfig{'ltisec'}{'private'}) eq 'HASH') { - if (ref($domconfig{'ltisec'}{'private'}{'keys'}) eq 'ARRAY') { - $domdefaults{'ltiprivhosts'} = $domconfig{'ltisec'}{'private'}{'keys'}; - } + if (ref($domconfig{'ssl'}{'connect'}) eq 'HASH') { + $domdefaults{'connect'} = $domconfig{'ssl'}{'connect'}; } } - if (ref($domconfig{'toolsec'}) eq 'HASH') { - if (ref($domconfig{'toolsec'}{'encrypt'}) eq 'HASH') { - $domdefaults{'toolenc_crs'} = $domconfig{'toolsec'}{'encrypt'}{'crs'}; - $domdefaults{'toolenc_dom'} = $domconfig{'toolsec'}{'encrypt'}{'dom'}; - } - if (ref($domconfig{'toolsec'}{'private'}) eq 'HASH') { - if (ref($domconfig{'toolsec'}{'private'}{'keys'}) eq 'ARRAY') { - $domdefaults{'toolprivhosts'} = $domconfig{'toolsec'}{'private'}{'keys'}; - } - } + if (ref($domconfig{'autoenroll'}) eq 'HASH') { + $domdefaults{'autofailsafe'} = $domconfig{'autoenroll'}{'autofailsafe'}; } &do_cache_new('domdefaults',$domain,\%domdefaults,$cachetime); return %domdefaults; } -sub get_dom_cats { - my ($dom) = @_; - return unless (&domain($dom)); - my ($cats,$cached)=&is_cached_new('cats',$dom); - unless (defined($cached)) { - my %domconfig = &get_dom('configuration',['coursecategories'],$dom); - if (ref($domconfig{'coursecategories'}) eq 'HASH') { - if (ref($domconfig{'coursecategories'}{'cats'}) eq 'HASH') { - %{$cats} = %{$domconfig{'coursecategories'}{'cats'}}; - } else { - $cats = {}; - } - } else { - $cats = {}; - } - &Apache::lonnet::do_cache_new('cats',$dom,$cats,3600); - } - return $cats; -} - -sub get_dom_instcats { - my ($dom) = @_; - return unless (&domain($dom)); - my ($instcats,$cached)=&is_cached_new('instcats',$dom); - unless (defined($cached)) { - my (%coursecodes,%codes,@codetitles,%cat_titles,%cat_order); - my $totcodes = &retrieve_instcodes(\%coursecodes,$dom); - if ($totcodes > 0) { - my $caller = 'global'; - if (&auto_instcode_format($caller,$dom,\%coursecodes,\%codes, - \@codetitles,\%cat_titles,\%cat_order) eq 'ok') { - $instcats = { - totcodes => $totcodes, - codes => \%codes, - codetitles => \@codetitles, - cat_titles => \%cat_titles, - cat_order => \%cat_order, - }; - &do_cache_new('instcats',$dom,$instcats,3600); - } - } - } - return $instcats; -} - -sub retrieve_instcodes { - my ($coursecodes,$dom) = @_; - my $totcodes; - my %courses = &courseiddump($dom,'.',1,'.','.','.',undef,undef,'Course'); - foreach my $course (keys(%courses)) { - if (ref($courses{$course}) eq 'HASH') { - if ($courses{$course}{'inst_code'} ne '') { - $$coursecodes{$course} = $courses{$course}{'inst_code'}; - $totcodes ++; - } - } - } - return $totcodes; -} - -# --------------------------------------------- Get domain config for passwords - -sub get_passwdconf { - my ($dom) = @_; - my (%passwdconf,$gotconf,$lookup); - my ($result,$cached)=&is_cached_new('passwdconf',$dom); - if (defined($cached)) { - if (ref($result) eq 'HASH') { - %passwdconf = %{$result}; - $gotconf = 1; - } - } - unless ($gotconf) { - my %domconfig = &get_dom('configuration',['passwords'],$dom); - if (ref($domconfig{'passwords'}) eq 'HASH') { - %passwdconf = %{$domconfig{'passwords'}}; - } - my $cachetime = 24*60*60; - &do_cache_new('passwdconf',$dom,\%passwdconf,$cachetime); - } - return %passwdconf; -} - sub course_portal_url { - my ($cnum,$cdom,$r) = @_; + my ($cnum,$cdom) = @_; my $chome = &homeserver($cnum,$cdom); my $hostname = &hostname($chome); my $protocol = $protocol{$chome}; @@ -2806,33 +2394,11 @@ sub course_portal_url { if ($domdefaults{'portal_def'}) { $firsturl = $domdefaults{'portal_def'}; } else { - my $alias = &Apache::lonnet::use_proxy_alias($r,$chome); - $hostname = $alias if ($alias ne ''); $firsturl = $protocol.'://'.$hostname; } return $firsturl; } -sub url_prefix { - my ($r,$dom,$home,$context) = @_; - my $prefix; - my %domdefs = &get_domain_defaults($dom); - if ($domdefs{'portal_def'} && $domdefs{'portal_def_'.$context}) { - if ($domdefs{'portal_def'} =~ m{^(https?://[^/]+)}) { - $prefix = $1; - } - } - if ($prefix eq '') { - my $hostname = &hostname($home); - my $protocol = $protocol{$home}; - $protocol = 'http' if ($protocol{$home} ne 'https'); - my $alias = &use_proxy_alias($r,$home); - $hostname = $alias if ($alias ne ''); - $prefix = $protocol.'://'.$hostname; - } - return $prefix; -} - # --------------------------------------------------- Assign a key to a student sub assign_access_key { @@ -3069,25 +2635,21 @@ 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{$remembered_id}); - delete($accessed{$remembered_id}); + delete($remembered{$id}); + delete($accessed{$id}); } sub is_cached_new { my ($name,$id,$debug) = @_; - my $remembered_id=$name.':'.$id; # this is to avoid make_key (which is slow) for - # keys in %remembered hash, which persists for - # duration of request (no restriction on key length). - if (exists($remembered{$remembered_id})) { - if ($debug) { &Apache::lonnet::logthis("Early return $remembered_id of $remembered{$remembered_id} "); } - $accessed{$remembered_id}=[&gettimeofday()]; + $id=&make_key($name,$id); + if (exists($remembered{$id})) { + if ($debug) { &Apache::lonnet::logthis("Early return $id of $remembered{$id} "); } + $accessed{$id}=[&gettimeofday()]; $hits++; - return ($remembered{$remembered_id},1); + return ($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"); } @@ -3097,14 +2659,13 @@ sub is_cached_new { if ($debug) { &Apache::lonnet::logthis("getting $id is __undef__"); } $value=undef; } - &make_room($remembered_id,$value,$debug); + &make_room($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)) { @@ -3120,17 +2681,17 @@ sub do_cache_new { $memcache->disconnect_all(); } # need to make a copy of $value - &make_room($remembered_id,$value,$debug); + &make_room($id,$value,$debug); return $value; } sub make_room { - my ($remembered_id,$value,$debug)=@_; + my ($id,$value,$debug)=@_; - $remembered{$remembered_id}= (ref($value)) ? &Storable::dclone($value) + $remembered{$id}= (ref($value)) ? &Storable::dclone($value) : $value; if ($to_remember<0) { return; } - $accessed{$remembered_id}=[&gettimeofday()]; + $accessed{$id}=[&gettimeofday()]; if (scalar(keys(%remembered)) <= $to_remember) { return; } my $to_kick; my $max_time=0; @@ -3368,27 +2929,6 @@ sub repcopy { } } -# ------------------------------------------------- Unsubscribe from a resource - -sub unsubscribe { - my ($fname) = @_; - my $answer; - if ($fname=~/\/(aboutme|syllabus|bulletinboard|smppg)$/) { return $answer; } - $fname=~s/[\n\r]//g; - my $author=$fname; - $author=~s/\/home\/httpd\/html\/res\/([^\/]*)\/([^\/]*).*/$1\/$2/; - my ($udom,$uname)=split(/\//,$author); - my $home=homeserver($uname,$udom); - if ($home eq 'no_host') { - $answer = 'no_host'; - } elsif (grep { $_ eq $home } ¤t_machine_ids()) { - $answer = 'home'; - } else { - $answer = reply("unsub:$fname",$home); - } - return $answer; -} - # ------------------------------------------------ Get server side include body sub ssi_body { my ($filelink,%form)=@_; @@ -3417,29 +2957,11 @@ sub ssi_body { # --------------------------------------------------------- Server Side Include sub absolute_url { - my ($host_name,$unalias,$keep_proto) = @_; + my ($host_name) = @_; my $protocol = ($ENV{'SERVER_PORT'} == 443?'https://':'http://'); if ($host_name eq '') { $host_name = $ENV{'SERVER_NAME'}; } - if ($unalias) { - my $alias = &get_proxy_alias(); - if ($alias eq $host_name) { - my $lonhost = $perlvar{'lonHostID'}; - my $hostname = &hostname($lonhost); - my $lcproto; - if (($keep_proto) || ($hostname eq '')) { - $lcproto = $protocol; - } else { - $lcproto = $protocol{$lonhost}; - $lcproto = 'http' if ($lcproto ne 'https'); - $lcproto .= '://'; - } - unless ($hostname eq '') { - return $lcproto.$hostname; - } - } - } return $protocol.$host_name; } @@ -3456,52 +2978,32 @@ sub absolute_url { sub ssi { my ($fn,%form)=@_; - my ($host,$request,$response); - $host = &absolute_url('',1); + 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',$host.$fn); - $request->content(join('&',map { + $request=new HTTP::Request('POST',&absolute_url().$fn); + $request->content(join('&',map { my $name = escape($_); - "$name=" . ( ref($form{$_}) eq 'ARRAY' - ? join("&$name=", map {escape($_) } @{$form{$_}}) - : &escape($form{$_}) ); + "$name=" . ( ref($form{$_}) eq 'ARRAY' + ? join("&$name=", map {escape($_) } @{$form{$_}}) + : &escape($form{$_}) ); } keys(%form))); } else { - $request=new HTTP::Request('GET',$host.$fn); + $request=new HTTP::Request('GET',&absolute_url().$fn); } $request->header(Cookie => $ENV{'HTTP_COOKIE'}); + my $response= $ua->request($request); + my $content = $response->content; + - if (($env{'request.course.id'}) && - ($form{'grade_courseid'} eq $env{'request.course.id'}) && - ($form{'grade_username'} ne '') && ($form{'grade_domain'} ne '') && - ($form{'grade_symb'} ne '') && - (&Apache::lonnet::allowed('mgr',$env{'request.course.id'}. - ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')))) { - if (LWP::UserAgent->VERSION >= 5.834) { - my $ua=new LWP::UserAgent; - $ua->local_address('127.0.0.1'); - $response = $ua->request($request); - } else { - { - require LWP::Protocol::http; - local @LWP::Protocol::http::EXTRA_SOCK_OPTS = (LocalAddr => '127.0.0.1'); - my $ua=new LWP::UserAgent; - $response = $ua->request($request); - @LWP::Protocol::http::EXTRA_SOCK_OPTS = (); - } - } - } else { - my $ua=new LWP::UserAgent; - $response = $ua->request($request); - } if (wantarray) { - return ($response->content, $response); + return ($content, $response); } else { - return $response->content; + return $content; } } @@ -3517,78 +3019,6 @@ 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 $hostname = &hostname($homeserver); - if ($hostname) { - my $protocol = $protocol{$homeserver}; - $protocol = 'http' if ($protocol ne 'https'); - my $uri = $protocol.'://'.$hostname.'/raw/'.&declutter($url); - my $ua=new LWP::UserAgent; - $ua->timeout(5); - my $request=new HTTP::Request('HEAD',$uri); - my $response=$ua->request($request); - 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) { - if (unlink($fname)) { - if ($uri!~/\.meta$/) { - if (-e $fname.'.meta') { - unlink($fname.'.meta'); - } - } - my $unsubresult = &unsubscribe($fname); - unless ($unsubresult eq 'ok') { - &logthis("no unsub of $fname from $homeserver, reason: $unsubresult"); - } - $removed = 1; - } - } - } - } - } - } - } - } - } - return $removed; -} - # -------------------------------- Allow a /uploaded/ URI to be vouched for sub allowuploaded { @@ -3605,7 +3035,7 @@ sub allowuploaded { # # 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 +# (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. @@ -3613,12 +3043,12 @@ sub allowuploaded { # 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 -- +# 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 +# $forceedit -- 1 if icon/link should be to go to edit mode # $forceview -- 1 if icon/link should be to go to view mode # @@ -3707,7 +3137,7 @@ sub can_edit_resource { $forceedit = 1; } $cfile = $resurl; - } elsif (($resurl ne '') && (&is_on_map($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'}) { @@ -3727,19 +3157,7 @@ sub can_edit_resource { $forceedit = 1; } $cfile = $resurl; - } elsif (($resurl =~ m{^/ext/}) && ($symb ne '')) { - my ($map,$id,$res) = &decode_symb($symb); - if ($map =~ /\.page$/) { - $incourse = 1; - if ($env{'form.forceedit'}) { - $forceview = 1; - $cfile = $map; - } else { - $forceedit = 1; - $cfile = '/adm/wrapper'.$resurl; - } - } - } elsif ($resurl =~ m{^/adm/wrapper/adm/$cdom/$cnum/\d+/ext\.tool$}) { + } elsif ($resurl =~ m{^/adm/wrapper/adm/$cdom/$cnum/\d+/exttools?$}) { $incourse = 1; if ($env{'form.forceedit'}) { $forceview = 1; @@ -3758,20 +3176,20 @@ sub can_edit_resource { } } elsif ($resurl eq '/res/lib/templates/simpleproblem.problem/smpedit') { my $template = '/res/lib/templates/simpleproblem.problem'; - if (&is_on_map($template)) { + 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 =~ m{^/adm/wrapper/adm/$cdom/$cnum/\d+/exttools?$}) && ($env{'form.folderpath'} =~ /^supplemental/)) { $incourse = 1; if ($env{'form.forceedit'}) { $forceview = 1; @@ -3789,7 +3207,7 @@ sub can_edit_resource { } else { $cfile = $env{'form.suppurl'}; my $escfile = &unescape($cfile); - if ($escfile =~ m{^/adm/$cdom/$cnum/\d+/ext\.tool$}) { + if ($escfile =~ m{^/adm/$cdom/$cnum/\d+/exttools?$}) { $cfile = '/adm/wrapper'.$escfile; } else { $escfile =~ s{^http://}{}; @@ -3818,7 +3236,7 @@ sub can_edit_resource { $cfile=$file; } } - if (($cfile ne '') && (!$incourse || $uploaded) && + if (($cfile ne '') && (!$incourse || $uploaded) && (($home ne '') && ($home ne 'no_host'))) { my @ids=¤t_machine_ids(); unless (grep(/^\Q$home\E$/,@ids)) { @@ -3845,9 +3263,9 @@ sub in_course { if ($hideprivileged) { my $skipuser; my %coursehash = &coursedescription($cdom.'_'.$cnum); - my @possdoms = ($cdom); - if ($coursehash{'checkforpriv'}) { - push(@possdoms,split(/,/,$coursehash{'checkforpriv'})); + my @possdoms = ($cdom); + if ($coursehash{'checkforpriv'}) { + push(@possdoms,split(/,/,$coursehash{'checkforpriv'})); } if (&privileged($uname,$udom,\@possdoms)) { $skipuser = 1; @@ -3950,7 +3368,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') { @@ -4008,7 +3426,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); @@ -4033,21 +3451,13 @@ sub clean_filename { } # Replace spaces by underscores $fname=~s/\s+/\_/g; -# Transliterate non-ascii text to ascii - my $lang = &Apache::lonlocal::current_language(); - $fname = &LONCAPA::transliterate::fname_to_ascii($fname,$lang); # Replace all other weird characters by nothing $fname=~s{[^/\w\.\-]}{}g; # Replace all .\d. sequences with _\d. so they no longer look like version # numbers $fname=~s/\.(\d+)(?=\.)/_$1/g; -# Replace three or more adjacent underscores with one for consistency -# with loncfile::filename_check() so complete url can be extracted by -# lonnet::decode_symb() - $fname=~s/_{3,}/_/g; return $fname; } - # This Function checks if an Image's dimensions exceed either $resizewidth (width) # or $resizeheight (height) - both pixels. If so, the image is scaled to produce an # image with the same aspect ratio as the original, but with dimensions which do @@ -4090,20 +3500,17 @@ sub resizeImage { # input: $formname - the contents of the file are in $env{"form.$formname"} # the desired filename is in $env{"form.$formname.filename"} # $context - possible values: coursedoc, existingfile, overwrite, -# canceloverwrite, scantron, toollogo or ''. +# canceloverwrite, or ''. # if 'coursedoc': upload to the current course # if 'existingfile': write file to tmp/overwrites directory # if 'canceloverwrite': delete file written to tmp/overwrites directory # $context is passed as argument to &finishuserfileupload # $subdir - directory in userfile to store the file into -# $parser - instruction to parse file for objects ($parser = parse) or -# if context is 'scantron', $parser is hashref of csv column mapping -# (e.g.,{ PaperID => 0, LastName => 1, FirstName => 2, ID => 3, -# Section => 4, CODE => 5, FirstQuestion => 9 }). +# $parser - instruction to parse file for objects ($parser = parse) # $allfiles - reference to hash for embedded objects # $codebase - reference to hash for codebase of java objects -# $destuname - username for permanent storage of uploaded file -# $destudom - domain for permanaent storage of uploaded file +# $desuname - username for permanent storage of uploaded file +# $dsetudom - domain for permanaent storage of uploaded file # $thumbwidth - width (pixels) of thumbnail to make for uploaded image # $thumbheight - height (pixels) of thumbnail to make for uploaded image # $resizewidth - width (pixels) to which to resize uploaded image @@ -4122,14 +3529,6 @@ sub userfileupload { $fname=&clean_filename($fname); # See if there is anything left unless ($fname) { return 'error: no uploaded file'; } - # If filename now begins with a . prepend unix timestamp _ milliseconds - if ($fname =~ /^\./) { - my ($s,$usec) = &gettimeofday(); - while (length($usec) < 6) { - $usec = '0'.$usec; - } - $fname = $s.'_'.substr($usec,0,3).$fname; - } # Files uploaded to help request form, or uploaded to "create course" page are handled differently if ((($formname eq 'screenshot') && ($subdir eq 'helprequests')) || (($formname eq 'coursecreatorxml') && ($subdir eq 'batchupload')) || @@ -4143,12 +3542,12 @@ sub userfileupload { '_'.$env{'user.domain'}.'/pending'; } elsif (($context eq 'existingfile') || ($context eq 'canceloverwrite')) { my ($docuname,$docudom); - if ($destudom =~ /^$match_domain$/) { + if ($destudom) { $docudom = $destudom; } else { $docudom = $env{'user.domain'}; } - if ($destuname =~ /^$match_username$/) { + if ($destuname) { $docuname = $destuname; } else { $docuname = $env{'user.name'}; @@ -4178,7 +3577,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') { @@ -4253,7 +3652,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'; @@ -4297,7 +3696,7 @@ sub finishuserfileupload { } } } - if (($context ne 'scantron') && ($parser eq 'parse')) { + if ($parser eq 'parse') { if ((ref($mimetype)) && ($$mimetype eq 'text/html')) { my $parse_result = &extract_embedded_items($filepath.'/'.$file, $allfiles,$codebase); @@ -4306,31 +3705,14 @@ sub finishuserfileupload { ' for embedded media: '.$parse_result); } } - } elsif (($context eq 'scantron') && (ref($parser) eq 'HASH')) { - my $format = $env{'form.scantron_format'}; - &bubblesheet_converter($docudom,$filepath.'/'.$file,$parser,$format); } if (($thumbwidth =~ /^\d+$/) && ($thumbheight =~ /^\d+$/)) { my $input = $filepath.'/'.$file; my $output = $filepath.'/'.'tn-'.$file; - my $makethumb; my $thumbsize = $thumbwidth.'x'.$thumbheight; - if ($context eq 'toollogo') { - my ($fullwidth,$fullheight) = &check_dimensions($input); - if ($fullwidth ne '' && $fullheight ne '') { - if ($fullwidth > $thumbwidth && $fullheight > $thumbheight) { - $makethumb = 1; - } - } - } else { - $makethumb = 1; - } - if ($makethumb) { - my @args = ('convert','-sample',$thumbsize,$input,$output); - system({$args[0]} @args); - if (-e $filepath.'/'.'tn-'.$file) { - $fetchthumb = 1; - } + system("convert -sample $thumbsize $input $output"); + if (-e $filepath.'/'.'tn-'.$file) { + $fetchthumb = 1; } } @@ -4387,7 +3769,7 @@ sub extract_embedded_items { } if (lc($tagname) eq 'a') { unless (($attr->{'href'} =~ /^#/) || ($attr->{'href'} eq '')) { - &add_filetype($allfiles,$attr->{'href'},'href'); + &add_filetype($allfiles,$attr->{'href'},'href'); } } if (lc($tagname) eq 'script') { @@ -4562,271 +3944,6 @@ sub embedded_dependency { return; } -sub check_dimensions { - my ($inputfile) = @_; - my ($fullwidth,$fullheight); - if (($inputfile =~ m|^[/\w.\-]+$|) && (-e $inputfile)) { - my $mm = new File::MMagic; - my $mime_type = $mm->checktype_filename($inputfile); - if ($mime_type =~ m{^image/}) { - if (open(PIPE,"identify $inputfile 2>&1 |")) { - my $imageinfo = ; - if (!close(PIPE)) { - &Apache::lonnet::logthis("Failed to close PIPE opened to retrieve image information for $inputfile"); - } - chomp($imageinfo); - my ($fullsize) = - ($imageinfo =~ /^\Q$inputfile\E\s+\w+\s+(\d+x\d+)/); - if ($fullsize) { - ($fullwidth,$fullheight) = split(/x/,$fullsize); - } - } - } - } - return ($fullwidth,$fullheight); -} - -sub bubblesheet_converter { - my ($cdom,$fullpath,$config,$format) = @_; - if ((&domain($cdom) ne '') && - ($fullpath =~ m{^\Q$perlvar{'lonDocRoot'}/userfiles/$cdom/\E$match_courseid/scantron_orig}) && - (-e $fullpath) && (ref($config) eq 'HASH') && ($format ne '')) { - my (%csvcols,%csvoptions); - if (ref($config->{'fields'}) eq 'HASH') { - %csvcols = %{$config->{'fields'}}; - } - if (ref($config->{'options'}) eq 'HASH') { - %csvoptions = %{$config->{'options'}}; - } - my %csvbynum = reverse(%csvcols); - my %scantronconf = &get_scantron_config($format,$cdom); - if (keys(%scantronconf)) { - my %bynum = ( - $scantronconf{CODEstart} => 'CODEstart', - $scantronconf{IDstart} => 'IDstart', - $scantronconf{PaperID} => 'PaperID', - $scantronconf{FirstName} => 'FirstName', - $scantronconf{LastName} => 'LastName', - $scantronconf{Qstart} => 'Qstart', - ); - my @ordered; - foreach my $item (sort { $a <=> $b } keys(%bynum)) { - push(@ordered,$bynum{$item}); - } - my %mapstart = ( - CODEstart => 'CODE', - IDstart => 'ID', - PaperID => 'PaperID', - FirstName => 'FirstName', - LastName => 'LastName', - Qstart => 'FirstQuestion', - ); - my %maplength = ( - CODEstart => 'CODElength', - IDstart => 'IDlength', - PaperID => 'PaperIDlength', - FirstName => 'FirstNamelength', - LastName => 'LastNamelength', - ); - if (open(my $fh,'<',$fullpath)) { - my $output; - my %lettdig = &letter_to_digits(); - my %diglett = reverse(%lettdig); - my $numletts = scalar(keys(%lettdig)); - my $num = 0; - while (my $line=<$fh>) { - $num ++; - next if (($num == 1) && ($csvoptions{'hdr'} == 1)); - $line =~ s{[\r\n]+$}{}; - my %found; - my @values = split(/,/,$line,-1); - my ($qstart,$record); - for (my $i=0; $i<@values; $i++) { - if ((($qstart ne '') && ($i > $qstart)) || - ($csvbynum{$i} eq 'FirstQuestion')) { - if ($values[$i] eq '') { - $values[$i] = $scantronconf{'Qoff'}; - } elsif ($scantronconf{'Qon'} eq 'number') { - if ($values[$i] =~ /^[A-Ja-j]$/) { - $values[$i] = $lettdig{uc($values[$i])}; - } - } elsif ($scantronconf{'Qon'} eq 'letter') { - if ($values[$i] =~ /^[0-9]$/) { - $values[$i] = $diglett{$values[$i]}; - } - } else { - if ($values[$i] =~ /^[0-9A-Ja-j]$/) { - my $digit; - if ($values[$i] =~ /^[A-Ja-j]$/) { - $digit = $lettdig{uc($values[$i])}-1; - if ($values[$i] eq 'J') { - $digit += $numletts; - } - } elsif ($values[$i] =~ /^[0-9]$/) { - $digit = $values[$i]-1; - if ($values[$i] eq '0') { - $digit += $numletts; - } - } - my $qval=''; - for (my $j=0; $j<$scantronconf{'Qlength'}; $j++) { - if ($j == $digit) { - $qval .= $scantronconf{'Qon'}; - } else { - $qval .= $scantronconf{'Qoff'}; - } - } - $values[$i] = $qval; - } - } - if (length($values[$i]) > $scantronconf{'Qlength'}) { - $values[$i] = substr($values[$i],0,$scantronconf{'Qlength'}); - } - my $numblank = $scantronconf{'Qlength'} - length($values[$i]); - if ($numblank > 0) { - $values[$i] .= ($scantronconf{'Qoff'} x $numblank); - } - if ($csvbynum{$i} eq 'FirstQuestion') { - $qstart = $i; - $found{$csvbynum{$i}} = $values[$i]; - } else { - $found{'FirstQuestion'} .= $values[$i]; - } - } elsif (exists($csvbynum{$i})) { - if ($csvoptions{'rem'}) { - $values[$i] =~ s/^\s+//; - } - if (($csvbynum{$i} eq 'PaperID') && ($csvoptions{'pad'})) { - while (length($values[$i]) < $scantronconf{$maplength{$csvbynum{$i}}}) { - $values[$i] = '0'.$values[$i]; - } - } - $found{$csvbynum{$i}} = $values[$i]; - } - } - foreach my $item (@ordered) { - my $currlength = 1+length($record); - my $numspaces = $scantronconf{$item} - $currlength; - if ($numspaces > 0) { - $record .= (' ' x $numspaces); - } - if (($mapstart{$item} ne '') && (exists($found{$mapstart{$item}}))) { - unless ($item eq 'Qstart') { - if (length($found{$mapstart{$item}}) > $scantronconf{$maplength{$item}}) { - $found{$mapstart{$item}} = substr($found{$mapstart{$item}},0,$scantronconf{$maplength{$item}}); - } - } - $record .= $found{$mapstart{$item}}; - } - } - $output .= "$record\n"; - } - close($fh); - if ($output) { - if (open(my $fh,'>',$fullpath)) { - print $fh $output; - close($fh); - } - } - } - } - return; - } -} - -sub letter_to_digits { - my %lettdig = ( - A => 1, - B => 2, - C => 3, - D => 4, - E => 5, - F => 6, - G => 7, - H => 8, - I => 9, - J => 0, - ); - return %lettdig; -} - -sub get_scantron_config { - my ($which,$cdom) = @_; - my @lines = &get_scantronformat_file($cdom); - my %config; - #FIXME probably should move to XML it has already gotten a bit much now - foreach my $line (@lines) { - my ($name,$descrip)=split(/:/,$line); - if ($name ne $which ) { next; } - chomp($line); - my @config=split(/:/,$line); - $config{'name'}=$config[0]; - $config{'description'}=$config[1]; - $config{'CODElocation'}=$config[2]; - $config{'CODEstart'}=$config[3]; - $config{'CODElength'}=$config[4]; - $config{'IDstart'}=$config[5]; - $config{'IDlength'}=$config[6]; - $config{'Qstart'}=$config[7]; - $config{'Qlength'}=$config[8]; - $config{'Qoff'}=$config[9]; - $config{'Qon'}=$config[10]; - $config{'PaperID'}=$config[11]; - $config{'PaperIDlength'}=$config[12]; - $config{'FirstName'}=$config[13]; - $config{'FirstNamelength'}=$config[14]; - $config{'LastName'}=$config[15]; - $config{'LastNamelength'}=$config[16]; - $config{'BubblesPerRow'}=$config[17]; - last; - } - return %config; -} - -sub get_scantronformat_file { - my ($cdom) = @_; - if ($cdom eq '') { - $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'}; - } - my %domconfig = &get_dom('configuration',['scantron'],$cdom); - my $gottab = 0; - my @lines; - if (ref($domconfig{'scantron'}) eq 'HASH') { - if ($domconfig{'scantron'}{'scantronformat'} ne '') { - my $formatfile = &getfile($perlvar{'lonDocRoot'}.$domconfig{'scantron'}{'scantronformat'}); - if ($formatfile ne '-1') { - @lines = split("\n",$formatfile,-1); - $gottab = 1; - } - } - } - if (!$gottab) { - my $confname = $cdom.'-domainconfig'; - my $default = $perlvar{'lonDocRoot'}.'/res/'.$cdom.'/'.$confname.'/default.tab'; - my $formatfile = &getfile($default); - if ($formatfile ne '-1') { - @lines = split("\n",$formatfile,-1); - $gottab = 1; - } - } - if (!$gottab) { - my @domains = ¤t_machine_domains(); - if (grep(/^\Q$cdom\E$/,@domains)) { - if (open(my $fh,'<',$perlvar{'lonTabDir'}.'/scantronformat.tab')) { - @lines = <$fh>; - close($fh); - } - } else { - if (open(my $fh,'<',$perlvar{'lonTabDir'}.'/default_scantronformat.tab')) { - @lines = <$fh>; - close($fh); - } - } - chomp(@lines); - } - return @lines; -} - sub removeuploadedurl { my ($url)=@_; my (undef,undef,$udom,$uname,$fname)=split('/',$url,5); @@ -4944,29 +4061,6 @@ sub flushcourselogs { if (! defined($dom) || $dom eq '' || ! defined($name) || $name eq '') { my $cid = $env{'request.course.id'}; -# -# FIXME 11/29/2021 -# Typo in rev. 1.458 (2003/12/09)?? -# These should likely by $env{'course.'.$cid.'.domain'} and $env{'course.'.$cid.'.num'} -# -# While these remain as $env{'request.'.$cid.'.domain'} and $env{'request.'.$cid.'.num'} -# $dom and $name will always be null, so the &inc() call will default to storing this data -# in a nohist_accesscount.db file for the user rather than the course. -# -# That said there is a lot of noise in the data being stored. -# So counts for prtspool/ and adm/ etc. are recorded. -# -# A review of which items ending '___count' are written to %accesshash should likely be -# made before deciding whether to set these to 'course.' instead of 'request.' -# -# Under the current scheme each user receives a nohist_accesscount.db file listing -# accesses for things which are not published resources, regardless of course, and -# there is not a nohist_accesscount.db file in a course, which might log accesses from -# anyone in the course for things which are not published resources. -# -# For an author, nohist_accesscount.db ends up having records for other items -# mixed up with the legitimate access counts for the author's published resources. -# $dom = $env{'request.'.$cid.'.domain'}; $name = $env{'request.'.$cid.'.num'}; } @@ -5000,7 +4094,7 @@ sub flushcourselogs { } } # -# Reverse lookup of domain roles (dc, ad, li, sc, dh, da, au) +# Reverse lookup of domain roles (dc, ad, li, sc, au) # my %domrolebuffer = (); foreach my $entry (keys(%domainrolehash)) { @@ -5015,19 +4109,10 @@ sub flushcourselogs { delete $domainrolehash{$entry}; } foreach my $dom (keys(%domrolebuffer)) { - 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'); - } + my %servers = &get_servers($dom,'library'); foreach my $tryserver (keys(%servers)) { - if (&reply('domroleput:'.$dom.':'. - $domrolebuffer{$dom},$tryserver) eq 'ok') { - last; - } else { + unless (&reply('domroleput:'.$dom.':'. + $domrolebuffer{$dom},$tryserver) eq 'ok') { &logthis('Put of domain roles failed for '.$dom.' and '.$tryserver); } } @@ -5076,11 +4161,7 @@ sub courseacclog { if ($formitem =~ /^HWFILE(?:SIZE|TOOBIG)/) { $what.=':'.$formitem.'='.$env{$key}; } elsif ($formitem !~ /^HWFILE(?:[^.]+)$/) { - if ($formitem eq 'proctorpassword') { - $what.=':'.$formitem.'=' . '*' x length($env{$key}); - } else { - $what.=':'.$formitem.'='.$env{$key}; - } + $what.=':'.$formitem.'='.$env{$key}; } } } @@ -5151,7 +4232,7 @@ sub userrolelog { {$trole.':'.$username.':'.$domain.':'.$env{'user.name'}.':'.$env{'user.domain'}.':'} =$tend.':'.$tstart; } - if ($trole =~ /^(dc|ad|li|au|dg|sc|dh|da)/ ) { + if ($trole =~ /^(dc|ad|li|au|dg|sc)/ ) { my (undef,$rudom,$runame,$rsec)=split(/\//,$area); $domainrolehash {$trole.':'.$username.':'.$domain.':'.$runame.':'.$rudom.':'.$rsec} @@ -5359,7 +4440,7 @@ sub get_my_roles { } else { my $possdoms = [$domain]; if (ref($roledoms) eq 'ARRAY') { - push(@{$possdoms},@{$roledoms}); + push(@{$possdoms},@{$roledoms}); } if (&privileged($username,$domain,$possdoms,\@privroles)) { if (!$nothide{$username.':'.$domain}) { @@ -5378,195 +4459,6 @@ 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 # # @@ -5580,7 +4472,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); @@ -5656,16 +4548,16 @@ sub courseiddump { if (($domfilter eq '') || (&host_domain($tryserver) eq $domfilter)) { my $rep; - if (grep { $_ eq $tryserver } ¤t_machine_ids()) { - $rep = &LONCAPA::Lond::dump_course_id_handler( - join(":", (&host_domain($tryserver), $sincefilter, - &escape($descfilter), &escape($instcodefilter), + 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($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 { @@ -5681,7 +4573,7 @@ sub courseiddump { &escape($creationcontext).':'.$domcloner.':'.$hasuniquecode. ':'.$reqcrsdom.':'.&escape($reqinstcode),$tryserver); } - + my @pairs=split(/\&/,$rep); foreach my $item (@pairs) { my ($key,$value)=split(/\=/,$item,2); @@ -5807,21 +4699,6 @@ 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 { @@ -5877,12 +4754,7 @@ sub set_first_access { } $cachedkey=''; my $firstaccess=&get_first_access($type,$symb,$map); - if ($firstaccess) { - &logthis("First access time already set ($firstaccess) when attempting ". - "to set new value (type: $type, extent: $res) for $uname:$udom ". - "in $courseid"); - return 'already_set'; - } else { + if (!$firstaccess) { my $start = time; my $putres = &put('firstaccesstimes',{"$courseid\0$res"=>$start}, $udom,$uname); @@ -5895,12 +4767,6 @@ sub set_first_access { 'course.'.$courseid.'.timerinterval.'.$res => $interval, } ); - if (($cachedtime) && (abs($start-$cachedtime) < 5)) { - $cachedtimes{"$courseid\0$res"} = $start; - } - } elsif ($putres ne 'refused') { - &logthis("Result: $putres when attempting to set first access time ". - "(type: $type, extent: $res) for $uname:$udom in $courseid"); } return $putres; } @@ -5908,93 +4774,6 @@ sub set_first_access { } } -sub checkout { - my ($symb,$tuname,$tudom,$tcrsid)=@_; - my $now=time; - my $lonhost=$perlvar{'lonHostID'}; - my $ip = &get_requestor_ip(); - my $infostr=&escape( - 'CHECKOUTTOKEN&'. - $tuname.'&'. - $tudom.'&'. - $tcrsid.'&'. - $symb.'&'. - $now.'&'.$ip); - my $token=&reply('tmpput:'.$infostr,$lonhost); - if ($token=~/^error\:/) { - &logthis("WARNING: ". - "Checkout tmpput failed ".$tudom.' - '.$tuname.' - '.$symb. - ""); - return ''; - } - - $token=~s/^(\d+)\_.*\_(\d+)$/$1\*$2\*$lonhost/; - $token=~tr/a-z/A-Z/; - - my %infohash=('resource.0.outtoken' => $token, - 'resource.0.checkouttime' => $now, - 'resource.0.outremote' => $ip); - - unless (&cstore(\%infohash,$symb,$tcrsid,$tudom,$tuname) eq 'ok') { - return ''; - } else { - &logthis("WARNING: ". - "Checkout cstore failed ".$tudom.' - '.$tuname.' - '.$symb. - ""); - } - - if (&log($tudom,$tuname,&homeserver($tuname,$tudom), - &escape('Checkout '.$infostr.' - '. - $token)) ne 'ok') { - return ''; - } else { - &logthis("WARNING: ". - "Checkout log failed ".$tudom.' - '.$tuname.' - '.$symb. - ""); - } - return $token; -} - -# ------------------------------------------------------------ Check in an item - -sub checkin { - my $token=shift; - my $now=time; - my ($ta,$tb,$lonhost)=split(/\*/,$token); - $lonhost=~tr/A-Z/a-z/; - my $dtoken=$ta.'_'.&hostname($lonhost).'_'.$tb; - $dtoken=~s/\W/\_/g; - my $ip = &get_requestor_ip(); - my ($dummy,$tuname,$tudom,$tcrsid,$symb,$chtim,$rmaddr)= - split(/\&/,&unescape(&reply('tmpget:'.$dtoken,$lonhost))); - - unless (($tuname) && ($tudom)) { - &logthis('Check in '.$token.' ('.$dtoken.') failed'); - return ''; - } - - unless (&allowed('mgr',$tcrsid)) { - &logthis('Check in '.$token.' ('.$dtoken.') unauthorized: '. - $env{'user.name'}.' - '.$env{'user.domain'}); - return ''; - } - - my %infohash=('resource.0.intoken' => $token, - 'resource.0.checkintime' => $now, - 'resource.0.inremote' => $ip); - - unless (&cstore(\%infohash,$symb,$tcrsid,$tudom,$tuname) eq 'ok') { - return ''; - } - - if (&log($tudom,$tuname,&homeserver($tuname,$tudom), - &escape('Checkin - '.$token)) ne 'ok') { - return ''; - } - - return ($symb,$tuname,$tudom,$tcrsid); -} - # --------------------------------------------- Set Expire Date for Spreadsheet sub expirespread { @@ -6249,7 +5028,7 @@ sub tmpreset { if (!$domain) { $domain=$env{'user.domain'}; } if (!$stuname) { $stuname=$env{'user.name'}; } if ($domain eq 'public' && $stuname eq 'public') { - $stuname=&get_requestor_ip(); + $stuname=$ENV{'REMOTE_ADDR'}; } my $path=LONCAPA::tempdir(); my %hash; @@ -6286,7 +5065,7 @@ sub tmpstore { if (!$domain) { $domain=$env{'user.domain'}; } if (!$stuname) { $stuname=$env{'user.name'}; } if ($domain eq 'public' && $stuname eq 'public') { - $stuname=&get_requestor_ip(); + $stuname=$ENV{'REMOTE_ADDR'}; } my $now=time; my %hash; @@ -6330,7 +5109,7 @@ sub tmprestore { if (!$domain) { $domain=$env{'user.domain'}; } if (!$stuname) { $stuname=$env{'user.name'}; } if ($domain eq 'public' && $stuname eq 'public') { - $stuname=&get_requestor_ip(); + $stuname=$ENV{'REMOTE_ADDR'}; } my %returnhash; $namespace=~s/\//\_/g; @@ -6386,7 +5165,7 @@ sub store { } if (!$home) { $home=$env{'user.home'}; } - $$storehash{'ip'}=&get_requestor_ip(); + $$storehash{'ip'}=$ENV{'REMOTE_ADDR'}; $$storehash{'host'}=$perlvar{'lonHostID'}; my $namevalue=''; @@ -6422,7 +5201,7 @@ sub cstore { } if (!$home) { $home=$env{'user.home'}; } - $$storehash{'ip'}=&get_requestor_ip(); + $$storehash{'ip'}=$ENV{'REMOTE_ADDR'}; $$storehash{'host'}=$perlvar{'lonHostID'}; my $namevalue=''; @@ -6588,7 +5367,7 @@ sub privileged { my $now = time; my $roles; if (ref($possroles) eq 'ARRAY') { - $roles = $possroles; + $roles = $possroles; } else { $roles = ['dc','su']; } @@ -6615,7 +5394,7 @@ sub privileged { for my $role (@rolesdump{grep { ! /^rolesdef_/ } keys(%rolesdump)}) { my ($trole, $tend, $tstart) = split(/_/, $role); if (grep(/^\Q$trole\E$/,@{$roles})) { - return 1 unless ($tend && $tend < $now) + return 1 unless ($tend && $tend < $now) or ($tstart && $tstart > $now); } } @@ -6653,7 +5432,7 @@ sub privileged_by_domain { 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} = + $privileged{$dom}{$trole}{$uname.':'.$udom} = $dompersonnel{$server}{$item}; } } @@ -6774,10 +5553,9 @@ sub rolesinit { } } - @userroles{'user.author','user.adv','user.rar'} = &set_userprivs(\%userroles, - \%allroles, \%allgroups); + @userroles{'user.author', 'user.adv'} = &set_userprivs(\%userroles, + \%allroles, \%allgroups); $env{'user.adv'} = $userroles{'user.adv'}; - $env{'user.rar'} = $userroles{'user.rar'}; return (\%userroles,\%firstaccenv,\%timerintenv); } @@ -6813,10 +5591,6 @@ 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; } @@ -6825,48 +5599,6 @@ 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; @@ -6901,7 +5633,6 @@ 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; @@ -6949,7 +5680,6 @@ sub set_userprivs { $thesepriv{$privilege}.=$restrictions; } if ($thesepriv{'adv'} eq 'F') { $adv=1; } - if ($thesepriv{'rar'} eq 'F') { $rar=1; } } } my $thesestr=''; @@ -6958,7 +5688,7 @@ sub set_userprivs { } $userroles->{'user.priv.'.$role} = $thesestr; } - return ($author,$adv,$rar); + return ($author,$adv); } sub role_status { @@ -7003,10 +5733,9 @@ sub role_status { push(@rolecodes,$$role); &standard_roleprivs(\%allroles,$$role,$tdomain,$spec,$trest,$$where); } - my ($author,$adv,$rar)= &set_userprivs(\%userroles,\%allroles,\%allgroups, - \%groups_roles); + my ($author,$adv)= &set_userprivs(\%userroles,\%allroles,\%allgroups,\%groups_roles); &appenv(\%userroles,\@rolecodes); - &log($env{'user.domain'},$env{'user.name'},$env{'user.home'},"Role ".$spec); + &log($env{'user.domain'},$env{'user.name'},$env{'user.home'},"Role ".$role); } } $$tstatus = 'is'; @@ -7082,57 +5811,39 @@ sub delete_env_groupprivs { } sub check_adhoc_privs { - my ($cdom,$cnum,$update,$refresh,$now,$checkrole,$caller,$sec) = @_; + my ($cdom,$cnum,$update,$refresh,$now,$checkrole,$caller) = @_; 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,$sec); + &set_adhoc_privileges($cdom,$cnum,$checkrole,$caller); $setprivs = 1; } } else { - &set_adhoc_privileges($cdom,$cnum,$checkrole,$caller,$sec); + &set_adhoc_privileges($cdom,$cnum,$checkrole,$caller); $setprivs = 1; } return $setprivs; } sub set_adhoc_privileges { -# role can be cc, ca, or cr//-domainconfig/role - my ($dcdom,$pickedcourse,$role,$caller,$sec) = @_; +# role can be cc or ca + my ($dcdom,$pickedcourse,$role,$caller) = @_; my $area = '/'.$dcdom.'/'.$pickedcourse; - if ($sec ne '') { - $area .= '/'.$sec; - } my $spec = $role.'.'.$area; my %userroles = &set_arearole($role,$area,'','',$env{'user.domain'}, $env{'user.name'},1); - my %rolehash = (); - if ($role =~ m{^\Qcr/$dcdom/$dcdom\E\-domainconfig/(\w+)$}) { - my $rolename = $1; - &custom_roleprivs(\%rolehash,$role,$dcdom,$pickedcourse,$spec,$area); - my %domdef = &get_domain_defaults($dcdom); - if (ref($domdef{'adhocroles'}) eq 'HASH') { - if (ref($domdef{'adhocroles'}{$rolename}) eq 'HASH') { - &appenv({'request.role.desc' => $domdef{'adhocroles'}{$rolename}{'desc'},}); - } - } - } else { - &standard_roleprivs(\%rolehash,$role,$dcdom,$spec,$pickedcourse,$area); - } - my ($author,$adv,$rar)= &set_userprivs(\%userroles,\%rolehash); + my %ccrole = (); + &standard_roleprivs(\%ccrole,$role,$dcdom,$spec,$pickedcourse,$area); + my ($author,$adv)= &set_userprivs(\%userroles,\%ccrole); &appenv(\%userroles,[$role,'cm']); - &log($env{'user.domain'},$env{'user.name'},$env{'user.home'},"Role ".$spec); - unless (($caller eq 'constructaccess' && $env{'request.course.id'}) || - ($caller eq 'tiny')) { + &log($env{'user.domain'},$env{'user.name'},$env{'user.home'},"Role ".$role); + unless ($caller eq 'constructaccess' && $env{'request.course.id'}) { &appenv( {'request.role' => $spec, 'request.role.domain' => $dcdom, - 'request.course.sec' => $sec, + 'request.course.sec' => '' } ); my $tadv=0; @@ -7192,19 +5903,20 @@ sub unserialize { return {} if $rep =~ /^error/; my %returnhash=(); - foreach my $item (split(/\&/,$rep)) { - my ($key, $value) = split(/=/, $item, 2); - $key = unescape($key) unless $escapedkeys; - next if $key =~ /^error: 2 /; - $returnhash{$key} = &thaw_unescape($value); - } + foreach my $item (split(/\&/,$rep)) { + my ($key, $value) = split(/=/, $item, 2); + $key = unescape($key) unless $escapedkeys; + next if $key =~ /^error: 2 /; + $returnhash{$key} = &thaw_unescape($value); + } + #return %returnhash; return \%returnhash; -} +} # see Lond::dump_with_regexp # if $escapedkeys hash keys won't get unescaped. sub dump { - my ($namespace,$udomain,$uname,$regexp,$range,$escapedkeys,$encrypt)=@_; + my ($namespace,$udomain,$uname,$regexp,$range,$escapedkeys)=@_; if (!$udomain) { $udomain=$env{'user.domain'}; } if (!$uname) { $uname=$env{'user.name'}; } my $uhome=&homeserver($uname,$udomain); @@ -7214,24 +5926,20 @@ sub dump { } else { $regexp='.'; } - if (grep { $_ eq $uhome } ¤t_machine_ids()) { + if (grep { $_ eq $uhome } current_machine_ids()) { # user is hosted on this machine - my $reply = LONCAPA::Lond::dump_with_regexp(join(':', ($udomain, + my $reply = LONCAPA::Lond::dump_with_regexp(join(":", ($udomain, $uname, $namespace, $regexp, $range)), $perlvar{'lonVersion'}); - return %{&unserialize($reply, $escapedkeys)}; - } - my $rep; - if ($encrypt) { - $rep=&reply("encrypt:edump:$udomain:$uname:$namespace:$regexp:$range",$uhome); - } else { - $rep=&reply("dump:$udomain:$uname:$namespace:$regexp:$range",$uhome); + return %{unserialize($reply, $escapedkeys)}; } + my $rep=&reply("dump:$udomain:$uname:$namespace:$regexp:$range",$uhome); my @pairs=split(/\&/,$rep); my %returnhash=(); if (!($rep =~ /^error/ )) { foreach my $item (@pairs) { my ($key,$value)=split(/=/,$item,2); - $key = &unescape($key) unless ($escapedkeys); + $key = unescape($key) unless $escapedkeys; + #$key = &unescape($key); next if ($key =~ /^error: 2 /); $returnhash{$key}=&thaw_unescape($value); } @@ -7275,7 +5983,7 @@ sub currentdump { my $rep; if (grep { $_ eq $uhome } current_machine_ids()) { - $rep = LONCAPA::Lond::dump_profile_database(join(":", ($sdom, $sname, + $rep = LONCAPA::Lond::dump_profile_database(join(":", ($sdom, $sname, $courseid))); } else { $rep = reply('currentdump:'.$sdom.':'.$sname.':'.$courseid,$uhome); @@ -7371,7 +6079,7 @@ sub inc { # --------------------------------------------------------------- put interface sub put { - my ($namespace,$storehash,$udomain,$uname,$encrypt)=@_; + my ($namespace,$storehash,$udomain,$uname)=@_; if (!$udomain) { $udomain=$env{'user.domain'}; } if (!$uname) { $uname=$env{'user.name'}; } my $uhome=&homeserver($uname,$udomain); @@ -7380,11 +6088,7 @@ sub put { $items.=&escape($item).'='.&freeze_escape($$storehash{$item}).'&'; } $items=~s/\&$//; - if ($encrypt) { - return &reply("encrypt:put:$udomain:$uname:$namespace:$items",$uhome); - } else { - return &reply("put:$udomain:$uname:$namespace:$items",$uhome); - } + return &reply("put:$udomain:$uname:$namespace:$items",$uhome); } # ------------------------------------------------------------ newput interface @@ -7424,8 +6128,7 @@ sub putstore { foreach my $key (keys(%{$storehash})) { $namevalue.=&escape($key).'='.&freeze_escape($storehash->{$key}).'&'; } - my $ip = &get_requestor_ip(); - $namevalue .= 'ip='.&escape($ip). + $namevalue .= 'ip='.&escape($ENV{'REMOTE_ADDR'}). '&host='.&escape($perlvar{'lonHostID'}). '&version='.$esc_v. '&by='.&escape($env{'user.name'}.':'.$env{'user.domain'}); @@ -7524,11 +6227,9 @@ sub tmpget { if (!defined($server)) { $server = $perlvar{'lonHostID'}; } my $rep=&reply("tmpget:$token",$server); my %returnhash; - if ($rep =~ /^(con_lost|error|no_such_host)/i) { - return %returnhash; - } foreach my $item (split(/\&/,$rep)) { my ($key,$value)=split(/=/,$item); + next if ($key =~ /^error: 2 /); $returnhash{&unescape($key)}=&thaw_unescape($value); } return %returnhash; @@ -7541,13 +6242,13 @@ sub tmpdel { return &reply("tmpdel:$token",$server); } -# ------------------------------------------------------------ get_timebased_id +# ------------------------------------------------------------ get_timebased_id sub get_timebased_id { my ($prefix,$keyid,$namespace,$cdom,$cnum,$idtype,$who,$locktries, $maxtries) = @_; my ($newid,$error,$dellock); - unless (($prefix =~ /^\w+$/) && ($keyid =~ /^\w+$/) && ($namespace ne '')) { + unless (($prefix =~ /^\w+$/) && ($keyid =~ /^\w+$/) && ($namespace ne '')) { return ('','ok','invalid call to get suffix'); } @@ -7561,7 +6262,7 @@ sub get_timebased_id { if (!$maxtries) { $maxtries = 10; } - + if (($cdom eq '') || ($cnum eq '')) { if ($env{'request.course.id'}) { $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; @@ -7649,15 +6350,15 @@ sub portfolio_access { if ($result) { my %setters; if ($env{'user.name'} eq 'public' && $env{'user.domain'} eq 'public') { - my ($startblock,$endblock,$triggerblock,$by_ip,$blockdom) = - &Apache::loncommon::blockcheck(\%setters,'port',$clientip,$unum,$udom); - if (($startblock && $endblock) || ($by_ip)) { + my ($startblock,$endblock) = + &Apache::loncommon::blockcheck(\%setters,'port',$unum,$udom); + if ($startblock && $endblock) { return 'B'; } } else { - my ($startblock,$endblock,$triggerblock,$by_ip,$blockdo) = - &Apache::loncommon::blockcheck(\%setters,'port',$clientip); - if (($startblock && $endblock) || ($by_ip)) { + my ($startblock,$endblock) = + &Apache::loncommon::blockcheck(\%setters,'port'); + if ($startblock && $endblock) { return 'B'; } } @@ -7716,7 +6417,7 @@ sub get_portfolio_access { if (ref($access_hash->{$ipkey}{'ip'}) eq 'ARRAY') { if (&Apache::loncommon::check_ip_acc(join(',',@{$access_hash->{$ipkey}{'ip'}}),$clientip)) { $allowed = 1; - last; + last; } } } @@ -7898,17 +6599,6 @@ sub is_portfolio_file { return; } -sub is_coursetool_logo { - my ($uri) = @_; - if ($env{'request.course.id'}) { - my $courseurl = &courseid_to_courseurl($env{'request.course.id'}); - if ($uri =~ m{^/*uploaded\Q$courseurl\E/toollogo/\d+/[^/]+$}) { - return 1; - } - } - return; -} - sub usertools_access { my ($uname,$udom,$tool,$action,$context,$userenvref,$domdefref,$is_advref)=@_; my ($access,%tools); @@ -7921,7 +6611,7 @@ sub usertools_access { unofficial => 1, community => 1, textbook => 1, - lti => 1, + placement => 1, ); } elsif ($context eq 'requestauthor') { %tools = ( @@ -7933,7 +6623,6 @@ sub usertools_access { blog => 1, webdav => 1, portfolio => 1, - timezone => 1, ); } return if (!defined($tools{$tool})); @@ -7957,7 +6646,7 @@ sub usertools_access { my ($toolstatus,$inststatus,$envkey); if ($context eq 'requestauthor') { - $envkey = $context; + $envkey = $context; } else { $envkey = $context.'.'.$tool; } @@ -8119,29 +6808,25 @@ sub is_advanced_user { } sub check_can_request { - my ($dom,$can_request,$request_domains,$uname,$udom) = @_; + my ($dom,$can_request,$request_domains) = @_; my $canreq = 0; - if (($env{'user.name'} ne '') && ($env{'user.domain'} ne '')) { - $uname = $env{'user.name'}; - $udom = $env{'user.domain'}; - } my ($types,$typename) = &Apache::loncommon::course_types(); my @options = ('approval','validate','autolimit'); my $optregex = join('|',@options); if ((ref($can_request) eq 'HASH') && (ref($types) eq 'ARRAY')) { foreach my $type (@{$types}) { - if (&usertools_access($uname,$udom,$type,undef, - 'requestcourses')) { + if (&usertools_access($env{'user.name'}, + $env{'user.domain'}, + $type,undef,'requestcourses')) { $canreq ++; if (ref($request_domains) eq 'HASH') { - push(@{$request_domains->{$type}},$udom); + push(@{$request_domains->{$type}},$env{'user.domain'}); } - if ($dom eq $udom) { + if ($dom eq $env{'user.domain'}) { $can_request->{$type} = 1; } } - if (($env{'user.name'} ne '') && ($env{'user.domain'} ne '') && - ($env{'environment.reqcrsotherdom.'.$type} ne '')) { + if ($env{'environment.reqcrsotherdom.'.$type} ne '') { my @curr = split(',',$env{'environment.reqcrsotherdom.'.$type}); if (@curr > 0) { foreach my $item (@curr) { @@ -8158,7 +6843,7 @@ sub check_can_request { } } } - unless ($dom eq $env{'user.domain'}) { + unless($dom eq $env{'user.domain'}) { $canreq ++; if (grep(/^\Q$dom\E:($optregex)(=?\d*)$/,@curr)) { $can_request->{$type} = 1; @@ -8223,14 +6908,14 @@ sub customaccess { # ------------------------------------------------- Check for a user privilege sub allowed { - my ($priv,$uri,$symb,$role,$clientip,$noblockcheck,$ignorecache,$nodeeplinkcheck,$nodeeplinkout)=@_; + my ($priv,$uri,$symb,$role,$clientip,$noblockcheck)=@_; my $ver_orguri=$uri; $uri=&deversion($uri); my $orguri=$uri; $uri=&declutter($uri); if ($priv eq 'evb') { -# Evade communication block restrictions for specified role in a course or domain +# Evade communication block restrictions for specified role in a course if ($env{'user.priv.'.$role} =~/evb\&([^\:]*)/) { return $1; } else { @@ -8240,7 +6925,7 @@ sub allowed { if (defined($env{'allowed.'.$priv})) { return $env{'allowed.'.$priv}; } # Free bre access to adm and meta resources - if (((($uri=~/^adm\//) && ($uri !~ m{/(?:smppg|bulletinboard|viewclasslist|aboutme|ext\.tool)$})) + if (((($uri=~/^adm\//) && ($uri !~ m{/(?:smppg|bulletinboard)$})) || (($uri=~/\.meta$/) && ($uri!~m|^uploaded/|) )) && ($priv eq 'bre')) { return 'F'; @@ -8251,9 +6936,9 @@ sub allowed { if (($space=~/^(uploaded|editupload)$/) && ($env{'user.name'} eq $name) && ($env{'user.domain'} eq $domain) && ('portfolio' eq $dir[0])) { my %setters; - my ($startblock,$endblock,$triggerblock,$by_ip,$blockdom) = - &Apache::loncommon::blockcheck(\%setters,'port',$clientip); - if (($startblock && $endblock) || ($by_ip)) { + my ($startblock,$endblock) = + &Apache::loncommon::blockcheck(\%setters,'port'); + if ($startblock && $endblock) { return 'B'; } else { return 'F'; @@ -8288,10 +6973,7 @@ sub allowed { # Free bre to public access if ($priv eq 'bre') { - my $copyright; - unless ($uri =~ /ext\.tool/) { - $copyright=&metadata($uri,'copyright'); - } + my $copyright=&metadata($uri,'copyright'); if (($copyright eq 'public') && (!$env{'request.course.id'})) { return 'F'; } @@ -8349,8 +7031,8 @@ sub allowed { my $adom = $1; foreach my $key (keys(%env)) { if ($key =~ m{^user\.role\.(ca|aa)/\Q$adom\E}) { - my ($start,$end) = split(/\./,$env{$key}); - if (($now >= $start) && (!$end || $end > $now)) { + my ($start,$end) = split('.',$env{$key}); + if (($now >= $start) && (!$end || $end < $now)) { $ownaccess = 1; last; } @@ -8362,8 +7044,8 @@ sub allowed { foreach my $role ('ca','aa') { if ($env{"user.role.$role./$adom/$aname"}) { my ($start,$end) = - split(/\./,$env{"user.role.$role./$adom/$aname"}); - if (($now >= $start) && (!$end || $end > $now)) { + split('.',$env{"user.role.$role./$adom/$aname"}); + if (($now >= $start) && (!$end || $end < $now)) { $ownaccess = 1; last; } @@ -8408,34 +7090,8 @@ sub allowed { if ($env{'user.priv.'.$env{'request.role'}.'.'.$courseuri} =~/\Q$priv\E\&([^\:]*)/) { - if ($priv eq 'mip') { - my $rem = $1; - if (($uri ne '') && ($env{'request.course.id'} eq $uri) && - ($env{'course.'.$env{'request.course.id'}.'.internal.courseowner'} eq $env{'user.name'}.':'.$env{'user.domain'})) { - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - if ($cdom ne '') { - my %passwdconf = &get_passwdconf($cdom); - if (ref($passwdconf{'crsownerchg'}) eq 'HASH') { - if (ref($passwdconf{'crsownerchg'}{'by'}) eq 'ARRAY') { - if (@{$passwdconf{'crsownerchg'}{'by'}}) { - my @inststatuses = split(':',$env{'environment.inststatus'}); - unless (@inststatuses) { - @inststatuses = ('default'); - } - foreach my $status (@inststatuses) { - if (grep(/^\Q$status\E$/,@{$passwdconf{'crsownerchg'}{'by'}})) { - $thisallowed.=$rem; - } - } - } - } - } - } - } - } else { - unless (($priv eq 'bro') && (!$ownaccess)) { - $thisallowed.=$1; - } + unless (($priv eq 'bro') && (!$ownaccess)) { + $thisallowed.=$1; } } @@ -8448,16 +7104,10 @@ sub allowed { if ($env{'user.priv.'.$env{'request.role'}.'./'} =~/\Q$priv\E\&([^\:]*)/) { my $value = $1; - my $deeplinkblock; - unless ($nodeeplinkcheck) { - $deeplinkblock = &deeplink_check($priv,$symb,$uri); - } - if ($deeplinkblock) { - $thisallowed='D'; - } elsif ($noblockcheck) { + if ($noblockcheck) { $thisallowed.=$value; } else { - my @blockers = &has_comm_blocking($priv,$symb,$uri,$ignorecache); + my @blockers = &has_comm_blocking($priv,$symb,$uri); if (@blockers > 0) { $thisallowed = 'B'; } else { @@ -8474,16 +7124,10 @@ sub allowed { $refuri=&declutter($refuri); my ($match) = &is_on_map($refuri); if ($match) { - my $deeplinkblock; - unless ($nodeeplinkcheck) { - $deeplinkblock = &deeplink_check($priv,$symb,$refuri); - } - if ($deeplinkblock) { - $thisallowed='D'; - } elsif ($noblockcheck) { + if ($noblockcheck) { $thisallowed='F'; } else { - my @blockers = &has_comm_blocking($priv,'',$refuri,'',1); + my @blockers = &has_comm_blocking($priv,$symb,$refuri); if (@blockers > 0) { $thisallowed = 'B'; } else { @@ -8502,7 +7146,7 @@ sub allowed { && &is_portfolio_url($uri)) { $thisallowed = &portfolio_access($uri,$clientip); } - + # Full access at system, domain or course-wide level? Exit. if ($thisallowed=~/F/) { return 'F'; @@ -8530,22 +7174,6 @@ sub allowed { if ($env{'request.course.id'}) { - if ($priv eq 'bre') { - if (&is_coursetool_logo($uri)) { - return 'F'; - } - } - -# If this is modifying password (internal auth) domains must match for user and user's role. - - if ($priv eq 'mip') { - if ($env{'user.domain'} eq $env{'request.role.domain'}) { - return $thisallowed; - } else { - return ''; - } - } - $courseprivid=$env{'request.course.id'}; if ($env{'request.course.sec'}) { $courseprivid.='/'.$env{'request.course.sec'}; @@ -8559,16 +7187,10 @@ sub allowed { =~/\Q$priv\E\&([^\:]*)/) { my $value = $1; if ($priv eq 'bre') { - my $deeplinkblock; - unless ($nodeeplinkcheck) { - $deeplinkblock = &deeplink_check($priv,$symb,$uri); - } - if ($deeplinkblock) { - $thisallowed = 'D'; - } elsif ($noblockcheck) { + if ($noblockcheck) { $thisallowed.=$value; } else { - my @blockers = &has_comm_blocking($priv,$symb,$uri,$ignorecache); + my @blockers = &has_comm_blocking($priv,$symb,$uri); if (@blockers > 0) { $thisallowed = 'B'; } else { @@ -8581,7 +7203,7 @@ sub allowed { $checkreferer=0; } } - + if ($checkreferer) { my $refuri=$env{'httpref.'.$orguri}; unless ($refuri) { @@ -8607,16 +7229,10 @@ sub allowed { =~/\Q$priv\E\&([^\:]*)/) { my $value = $1; if ($priv eq 'bre') { - my $deeplinkblock; - unless ($nodeeplinkcheck) { - $deeplinkblock = &deeplink_check($priv,$symb,$refuri); - } - if ($deeplinkblock) { - $thisallowed = 'D'; - } elsif ($noblockcheck) { + if ($noblockcheck) { $thisallowed.=$value; } else { - my @blockers = &has_comm_blocking($priv,'',$refuri,'',1); + my @blockers = &has_comm_blocking($priv,$symb,$refuri); if (@blockers > 0) { $thisallowed = 'B'; } else { @@ -8658,48 +7274,16 @@ sub allowed { # # Possibly locked functionality, check all courses -# In roles.tab, L (unless locked) available for bre, pch, plc, pac and sma. # Locks might take effect only after 10 minutes cache expiration for other -# courses, and 2 minutes for current course, in which user has st or ta role -# which is neither expired nor a future role (unless current course). +# courses, and 2 minutes for current course - my ($needlockcheck,$now,$crsonly); + my $envkey; if ($thisallowed=~/L/) { - $now = time; - if ($priv eq 'bre') { - if ($uri ne '') { - if ($orguri =~ m{^/+res/}) { - if ($uri =~ m{^lib/templates/}) { - if ($env{'request.course.id'}) { - $crsonly = 1; - $needlockcheck = 1; - } - } else { - $needlockcheck = 1; - } - } elsif ($env{'request.course.id'}) { - my ($crsdom,$crsnum) = split('_',$env{'request.course.id'}); - if (($uri =~ m{^(adm|uploaded|public)/$crsdom/$crsnum/}) || - ($uri =~ m{^adm/$match_domain/$match_username/\d+/(smppg|bulletinboard)$})) { - $crsonly = 1; - } - $needlockcheck = 1; - } - } - } elsif (($priv eq 'pch') || ($priv eq 'plc') || ($priv eq 'pac') || ($priv eq 'sma')) { - $needlockcheck = 1; - } - } - if ($needlockcheck) { - foreach my $envkey (keys(%env)) { + foreach $envkey (keys(%env)) { if ($envkey=~/^user\.role\.(st|ta)\.([^\.]*)/) { my $courseid=$2; my $roleid=$1.'.'.$2; $courseid=~s/^\///; - unless ($env{'request.role'} eq $roleid) { - my ($start,$end) = split(/\./,$env{$envkey}); - next unless (($now >= $start) && (!$end || $end > $now)); - } my $expiretime=600; if ($env{'request.role'} eq $roleid) { $expiretime=120; @@ -8722,7 +7306,7 @@ sub allowed { } if (($env{$prefix.'priv.'.$priv.'.lock.sections'}=~/\,\Q$csec\E\,/) || ($env{$prefix.'priv.'.$priv.'.lock.sections'} eq 'all')) { - if ($env{$prefix.'priv.'.$priv.'.lock.expire'}>time) { + if ($env{'priv.'.$priv.'.lock.expire'}>time) { &log($env{'user.domain'},$env{'user.name'}, $env{'user.home'}, 'Locked by priv: '.$priv.' for '.$uri.' due to '. @@ -8734,7 +7318,7 @@ sub allowed { } } } - + # # Rest of the restrictions depend on selected course # @@ -8761,7 +7345,7 @@ sub allowed { my $unamedom=$env{'user.name'}.':'.$env{'user.domain'}; if ($env{'course.'.$env{'request.course.id'}.'.'.$priv.'.roles.denied'} =~/\Q$rolecode\E/) { - if (($priv ne 'pch') && ($priv ne 'plc')) { + if (($priv ne 'pch') && ($priv ne 'plc') && ($priv ne 'pac')) { &logthis($env{'user.domain'}.':'.$env{'user.name'}.':'.$env{'user.home'}.':'. 'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode.' in '. $env{'request.course.id'}); @@ -8771,7 +7355,7 @@ sub allowed { if ($env{'course.'.$env{'request.course.id'}.'.'.$priv.'.users.denied'} =~/\Q$unamedom\E/) { - if (($priv ne 'pch') && ($priv ne 'plc')) { + if (($priv ne 'pch') && ($priv ne 'plc') && ($priv ne 'pac')) { &logthis($env{'user.domain'}.':'.$env{'user.name'}.':'.$env{'user.home'}. 'Denied by user: '.$priv.' for '.$uri.' as '.$unamedom.' in '. $env{'request.course.id'}); @@ -8793,17 +7377,6 @@ sub allowed { } } -# Restricted for deeplinked session? - - if ($env{'request.deeplink.login'}) { - if ($env{'acc.deeplinkout'} && !$nodeeplinkout) { - if (!$symb) { $symb=&symbread($uri,1); } - if (($symb) && ($env{'acc.deeplinkout'}=~/\&\Q$symb\E\&/)) { - return ''; - } - } - } - # Restricted by state or randomout? if ($thisallowed=~/X/) { @@ -8824,8 +7397,6 @@ sub allowed { return 'A'; } elsif ($thisallowed eq 'B') { return 'B'; - } elsif ($thisallowed eq 'D') { - return 'D'; } return 'F'; } @@ -8842,7 +7413,7 @@ sub constructaccess { my ($ownername,$ownerdomain,$ownerhome); ($ownerdomain,$ownername) = - ($url=~ m{^(?:\Q$perlvar{'lonDocRoot'}\E|)/priv/($match_domain)/($match_username)(?:/|$)}); + ($url=~ m{^(?:\Q$perlvar{'lonDocRoot'}\E|)(?:/daxepage|/daxeopen)?/priv/($match_domain)/($match_username)/}); # The URL does not really point to any authorspace, forget it unless (($ownername) && ($ownerdomain)) { return ''; } @@ -8863,6 +7434,15 @@ sub constructaccess { $ownerhome = &homeserver($ownername,$ownerdomain); return ($ownername,$ownerdomain,$ownerhome); } + if ($env{'request.course.id'}) { + if (($ownername eq $env{'course.'.$env{'request.course.id'}.'.num'}) && + ($ownerdomain eq $env{'course.'.$env{'request.course.id'}.'.domain'})) { + if (&allowed('mdc',$env{'request.course.id'})) { + $ownerhome = $env{'course.'.$env{'request.course.id'}.'.home'}; + return ($ownername,$ownerdomain,$ownerhome); + } + } + } } # We don't have any access right now. If we are not possibly going to do anything about this, @@ -8905,27 +7485,22 @@ sub constructaccess { # # User for whom data are being temporarily cached. my $cacheduser=''; -# Course for which data are being temporarily cached. -my $cachedcid=''; -# Cached blockers for this user (a hash of blocking items). +# Cached blockers for this user (a hash of blocking items). my %cachedblockers=(); # When the data were last cached. my $cachedlast=''; sub load_all_blockers { - my ($uname,$udom)=@_; - if (($uname ne '') && ($udom ne '')) { + my ($uname,$udom,$blocks)=@_; + if (($uname ne '') && ($udom ne '')) { if (($cacheduser eq $uname.':'.$udom) && - ($cachedcid eq $env{'request.course.id'}) && (abs($cachedlast-time)<5)) { return; } } $cachedlast=time; $cacheduser=$uname.':'.$udom; - $cachedcid=$env{'request.course.id'}; - %cachedblockers = &get_commblock_resources(); - return; + %cachedblockers = &get_commblock_resources($blocks); } sub get_comm_blocks { @@ -8952,18 +7527,14 @@ sub get_commblock_resources { my ($blocks) = @_; my %blockers = (); return %blockers unless ($env{'request.course.id'}); - my $courseurl = &courseid_to_courseurl($env{'request.course.id'}); - if ($env{'request.course.sec'}) { - $courseurl .= '/'.$env{'request.course.sec'}; - } - return %blockers if ($env{'user.priv.'.$env{'request.role'}.'.'.$courseurl} =~/evb\&([^\:]*)/); + return %blockers if ($env{'user.priv.'.$env{'request.role'}} =~/evb\&([^\:]*)/); my %commblocks; if (ref($blocks) eq 'HASH') { %commblocks = %{$blocks}; } else { %commblocks = &get_comm_blocks(); } - return %blockers unless (keys(%commblocks) > 0); + return %blockers unless (keys(%commblocks) > 0); my $navmap = Apache::lonnavmaps::navmap->new(); return %blockers unless (ref($navmap)); my $now = time; @@ -8975,7 +7546,7 @@ sub get_commblock_resources { if (ref($commblocks{$block}{'blocks'}{'docs'}) eq 'HASH') { if (ref($commblocks{$block}{'blocks'}{'docs'}{'maps'}) eq 'HASH') { if (keys(%{$commblocks{$block}{'blocks'}{'docs'}{'maps'}})) { - $blockers{$block}{maps} = $commblocks{$block}{'blocks'}{'docs'}{'maps'}; + $blockers{$block}{maps} = $commblocks{$block}{'blocks'}{'docs'}{'maps'}; } } if (ref($commblocks{$block}{'blocks'}{'docs'}{'resources'}) eq 'HASH') { @@ -8988,9 +7559,10 @@ sub get_commblock_resources { } } elsif ($block =~ /^firstaccess____(.+)$/) { my $item = $1; + my @to_test; if (ref($commblocks{$block}{'blocks'}) eq 'HASH') { if (ref($commblocks{$block}{'blocks'}{'docs'}) eq 'HASH') { - my (@interval,$mapname); + my @interval; my $type = 'map'; if ($item eq 'course') { $type = 'course'; @@ -8999,16 +7571,32 @@ sub get_commblock_resources { if ($item =~ /___\d+___/) { $type = 'resource'; @interval=&EXT("resource.0.interval",$item); + if (ref($navmap)) { + my $res = $navmap->getBySymb($item); + push(@to_test,$res); + } } else { - $mapname = &deversion($item); - if (ref($navmap)) { - my $timelimit = $navmap->get_mapparam(undef,$mapname,'0.interval'); - @interval = ($timelimit,'map'); + my $mapsymb = &symbread($item,1); + if ($mapsymb) { + if (ref($navmap)) { + my $mapres = $navmap->getBySymb($mapsymb); + @to_test = $mapres->retrieveResources($mapres,undef,0,0,0,1); + foreach my $res (@to_test) { + my $symb = $res->symb(); + next if ($symb eq $mapsymb); + if ($symb ne '') { + @interval=&EXT("resource.0.interval",$symb); + if ($interval[1] eq 'map') { + last; + } + } + } + } } } } if ($interval[0] =~ /^(\d+)/) { - my $timelimit = $1; + my $timelimit = $1; my $first_access; if ($type eq 'resource') { $first_access=&get_first_access($interval[1],$item); @@ -9021,37 +7609,10 @@ sub get_commblock_resources { my $timesup = $first_access+$timelimit; if ($timesup > $now) { my $activeblock; - if ($type eq 'resource') { - if (ref($navmap)) { - my $res = $navmap->getBySymb($item); - if ($res->answerable()) { - $activeblock = 1; - } - } - } elsif ($type eq 'map') { - my $mapsymb = &symbread($mapname,1); - if (($mapsymb) && (ref($navmap))) { - my $mapres = $navmap->getBySymb($mapsymb); - if (ref($mapres)) { - my $first = $mapres->map_start(); - my $finish = $mapres->map_finish(); - my $it = $navmap->getIterator($first,$finish,undef,0,0); - if (ref($it)) { - my $res; - while ($res = $it->next(undef,1)) { - next unless (ref($res)); - my $symb = $res->symb(); - next if (($symb eq $mapsymb) || ($symb eq '')); - @interval=&EXT("resource.0.interval",$symb); - if ($interval[1] eq 'map') { - if ($res->answerable()) { - $activeblock = 1; - last; - } - } - } - } - } + foreach my $res (@to_test) { + if ($res->answerable()) { + $activeblock = 1; + last; } } if ($activeblock) { @@ -9077,154 +7638,59 @@ sub get_commblock_resources { } sub has_comm_blocking { - my ($priv,$symb,$uri,$ignoresymbdb,$noenccheck,$blocked,$blocks) = @_; + my ($priv,$symb,$uri,$blocks) = @_; my @blockers; return unless ($env{'request.course.id'}); return unless ($priv eq 'bre'); + return if ($env{'user.priv.'.$env{'request.role'}} =~/evb\&([^\:]*)/); return if ($env{'request.state'} eq 'construct'); - my $courseurl = &courseid_to_courseurl($env{'request.course.id'}); - if ($env{'request.course.sec'}) { - $courseurl .= '/'.$env{'request.course.sec'}; - } - return if ($env{'user.priv.'.$env{'request.role'}.'.'.$courseurl} =~/evb\&([^\:]*)/); - my %blockinfo; - if (ref($blocks) eq 'HASH') { - %blockinfo = &get_commblock_resources($blocks); - } else { - &load_all_blockers($env{'user.name'},$env{'user.domain'}); - %blockinfo = %cachedblockers; - } - return unless (keys(%blockinfo) > 0); + &load_all_blockers($env{'user.name'},$env{'user.domain'},$blocks); + return unless (keys(%cachedblockers) > 0); my (%possibles,@symbs); if (!$symb) { - $symb = &symbread($uri,1,1,1,\%possibles,$ignoresymbdb,$noenccheck); + $symb = &symbread($uri,1,1,1,\%possibles); } if ($symb) { @symbs = ($symb); - } elsif (keys(%possibles)) { + } elsif (keys(%possibles)) { @symbs = keys(%possibles); } my $noblock; foreach my $symb (@symbs) { last if ($noblock); my ($map,$resid,$resurl)=&decode_symb($symb); - foreach my $block (keys(%blockinfo)) { + foreach my $block (keys(%cachedblockers)) { if ($block =~ /^firstaccess____(.+)$/) { my $item = $1; - unless ($blocked) { - if (($item eq $map) || ($item eq $symb)) { - $noblock = 1; - last; - } + if (($item eq $map) || ($item eq $symb)) { + $noblock = 1; + last; } } - if (ref($blockinfo{$block}) eq 'HASH') { - if (ref($blockinfo{$block}{'resources'}) eq 'HASH') { - if ($blockinfo{$block}{'resources'}{$symb}) { - unless (grep(/^\Q$block\E$/,@blockers)) { - push(@blockers,$block); - } - } - } - if (ref($blockinfo{$block}{'maps'}) eq 'HASH') { - if ($blockinfo{$block}{'maps'}{$map}) { + if (ref($cachedblockers{$block}) eq 'HASH') { + if (ref($cachedblockers{$block}{'resources'}) eq 'HASH') { + if ($cachedblockers{$block}{'resources'}{$symb}) { unless (grep(/^\Q$block\E$/,@blockers)) { push(@blockers,$block); } } } } - } - } - unless ($noblock) { - return @blockers; - } - return; -} -} - -sub deeplink_check { - my ($priv,$symb,$uri) = @_; - return unless ($env{'request.course.id'}); - return unless ($priv eq 'bre'); - return if ($env{'request.state'} eq 'construct'); - return if ($env{'request.role.adv'}); - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; - my (%possibles,@symbs); - if (!$symb) { - $symb = &symbread($uri,1,1,1,\%possibles); - } - if ($symb) { - @symbs = ($symb); - } elsif (keys(%possibles)) { - @symbs = keys(%possibles); - } - - my ($deeplink_symb,$allow); - if ($env{'request.deeplink.login'}) { - $deeplink_symb = &Apache::loncommon::deeplink_login_symb($cnum,$cdom); - } - foreach my $symb (@symbs) { - last if ($allow); - my $deeplink = &EXT("resource.0.deeplink",$symb); - if ($deeplink eq '') { - $allow = 1; - } else { - my ($state,$others,$listed,$scope,$protect) = split(/,/,$deeplink); - if ($state ne 'only') { - $allow = 1; - } else { - my $check_deeplink_entry; - if ($protect ne 'none') { - my ($acctype,$item) = split(/:/,$protect); - if (($acctype eq 'ltic') && ($env{'user.linkprotector'})) { - if (grep(/^\Q$item\Ec$/,split(/,/,$env{'user.linkprotector'}))) { - $check_deeplink_entry = 1 - } - } elsif (($acctype eq 'ltid') && ($env{'user.linkprotector'})) { - if (grep(/^\Q$item\Ed$/,split(/,/,$env{'user.linkprotector'}))) { - $check_deeplink_entry = 1; - } - } elsif (($acctype eq 'key') && ($env{'user.deeplinkkey'})) { - if (grep(/^\Q$item\E$/,split(/,/,$env{'user.deeplinkkey'}))) { - $check_deeplink_entry = 1; - } - } - } - if (($protect eq 'none') || ($check_deeplink_entry)) { - if ($scope eq 'res') { - if ($symb eq $deeplink_symb) { - $allow = 1; - } - } elsif (($scope eq 'map') || ($scope eq 'rec')) { - my ($map_from_symb,$map_from_login); - $map_from_symb = &deversion((&decode_symb($symb))[0]); - if ($deeplink_symb =~ /\.(page|sequence)$/) { - $map_from_login = &deversion((&decode_symb($deeplink_symb))[2]); - } else { - $map_from_login = &deversion((&decode_symb($deeplink_symb))[0]); - } - if (($map_from_symb) && ($map_from_login)) { - if ($map_from_symb eq $map_from_login) { - $allow = 1; - } elsif ($scope eq 'rec') { - my @recurseup = &get_map_hierarchy($map_from_symb,$env{'request.course.id'}); - if (grep(/^\Q$map_from_login\E$/,@recurseup)) { - $allow = 1; - } - } - } + if (ref($cachedblockers{$block}{'maps'}) eq 'HASH') { + if ($cachedblockers{$block}{'maps'}{$map}) { + unless (grep(/^\Q$block\E$/,@blockers)) { + push(@blockers,$block); } } } } } - return if ($allow); - return 1; + return if ($noblock); + return @blockers; +} } -# -------------------------------- Deversion and split uri into path an filename +# -------------------------------- Deversion and split uri into path an filename # # Removes the version from a URI and @@ -9295,7 +7761,7 @@ sub get_symb_from_alias { sub definerole { if (allowed('mcr','/')) { - my ($rolename,$sysrole,$domrole,$courole,$uname,$udom)=@_; + my ($rolename,$sysrole,$domrole,$courole)=@_; foreach my $role (split(':',$sysrole)) { my ($crole,$cqual)=split(/\&/,$role); if ($pr{'cr:s'}!~/\Q$crole\E/) { return "refused:s:$crole"; } @@ -9323,19 +7789,11 @@ sub definerole { } } } - my $uhome; - if (($uname ne '') && ($udom ne '')) { - $uhome = &homeserver($uname,$udom); - return $uhome if ($uhome eq 'no_host'); - } else { - $uname = $env{'user.name'}; - $udom = $env{'user.domain'}; - $uhome = $env{'user.home'}; - } my $command="encrypt:rolesput:$env{'user.domain'}:$env{'user.name'}:". - "$udom:$uname:rolesdef_$rolename=". + "$env{'user.domain'}:$env{'user.name'}:". + "rolesdef_$rolename=". escape($sysrole.'_'.$domrole.'_'.$courole); - return reply($command,$uhome); + return reply($command,$env{'user.home'}); } else { return 'refused'; } @@ -9350,9 +7808,9 @@ sub metadata_query { my @server_list = (defined($server_array) ? @$server_array : keys(%libserv) ); for my $server (@server_list) { - my $domains = ''; + my $domains = ''; if (ref($domains_hash) eq 'HASH') { - $domains = $domains_hash->{$server}; + $domains = $domains_hash->{$server}; } unless ($custom or $customshow) { my $reply=&reply("querysend:".&escape($query).':::'.&escape($domains),$server); @@ -9417,12 +7875,10 @@ sub update_allusers_table { sub fetch_enrollment_query { my ($context,$affiliatesref,$replyref,$dom,$cnum) = @_; - my ($homeserver,$sleep,$loopmax); + my $homeserver; my $maxtries = 1; if ($context eq 'automated') { $homeserver = $perlvar{'lonHostID'}; - $sleep = 2; - $loopmax = 100; $maxtries = 10; # will wait for up to 2000s for retrieval of classlist data before timeout } else { $homeserver = &homeserver($cnum,$dom); @@ -9440,17 +7896,17 @@ sub fetch_enrollment_query { &logthis('fetch_enrollment_query: invalid queryid: '.$queryid.' for host: '.$host.' and homeserver: '.$homeserver.' context: '.$context.' '.$cnum); return 'error: '.$queryid; } - my $reply = &get_query_reply($queryid,$sleep,$loopmax); + my $reply = &get_query_reply($queryid); my $tries = 1; while (($reply=~/^timeout/) && ($tries < $maxtries)) { - $reply = &get_query_reply($queryid,$sleep,$loopmax); + $reply = &get_query_reply($queryid); $tries ++; } if ( ($reply =~/^timeout/) || ($reply =~/^error/) ) { &logthis('fetch_enrollment_query error: '.$reply.' for '.$dom.' '.$env{'user.name'}.' for '.$queryid.' context: '.$context.' '.$cnum.' maxtries: '.$maxtries.' tries: '.$tries); } else { my @responses = split(/:/,$reply); - if (grep { $_ eq $homeserver } ¤t_machine_ids()) { + if ($homeserver eq $perlvar{'lonHostID'}) { foreach my $line (@responses) { my ($key,$value) = split(/=/,$line,2); $$replyref{$key} = $value; @@ -9468,7 +7924,7 @@ sub fetch_enrollment_query { if ($xml_classlist =~ /^error/) { &logthis('fetch_enrollment_query - autoretrieve error: '.$xml_classlist.' for '.$filename.' from server: '.$homeserver.' '.$context.' '.$cnum); } else { - if ( open(FILE,">",$destname) ) { + if ( open(FILE,">$destname") ) { print FILE &unescape($xml_classlist); close(FILE); } else { @@ -9485,19 +7941,13 @@ sub fetch_enrollment_query { } sub get_query_reply { - my ($queryid,$sleep,$loopmax) = @_; - if (($sleep eq '') || ($sleep !~ /^\d+\.?\d*$/)) { - $sleep = 0.2; - } - if (($loopmax eq '') || ($loopmax =~ /\D/)) { - $loopmax = 100; - } + my $queryid=shift; my $replyfile=LONCAPA::tempdir().$queryid; my $reply=''; - for (1..$loopmax) { - sleep($sleep); + for (1..100) { + sleep(0.2); if (-e $replyfile.'.end') { - if (open(my $fh,"<",$replyfile)) { + if (open(my $fh,$replyfile)) { $reply = join('',<$fh>); close($fh); } else { return 'error: reply_file_error'; } @@ -9618,25 +8068,6 @@ sub auto_validate_instcode { return ($outcome,$description,$defaultcredits); } -sub auto_validate_inst_crosslist { - my ($cnum,$cdom,$instcode,$inst_xlist,$coowner) = @_; - my ($homeserver,$response); - if (($cdom =~ /^$match_domain$/) && ($cnum =~ /^$match_courseid$/)) { - $homeserver = &homeserver($cnum,$cdom); - } - if (!defined($homeserver)) { - if ($cdom =~ /^$match_domain$/) { - $homeserver = &domain($cdom,'primary'); - } - } - unless (($homeserver eq '') || ($homeserver eq 'no_host')) { - $response=&reply('autovalidateinstcrosslist:'.$cdom.':'. - &escape($instcode).':'.&escape($inst_xlist).':'. - &escape($coowner),$homeserver); - } - return $response; -} - sub auto_create_password { my ($cnum,$cdom,$authparam,$udom) = @_; my ($homeserver,$response); @@ -9908,65 +8339,6 @@ sub auto_validate_class_sec { return $response; } -sub auto_instsec_reformat { - my ($cdom,$action,$instsecref) = @_; - return unless(($action eq 'clutter') || ($action eq 'declutter')); - my @homeservers; - if (defined(&domain($cdom,'primary'))) { - push(@homeservers,&domain($cdom,'primary')); - } else { - my %servers = &get_servers($cdom,'library'); - foreach my $tryserver (keys(%servers)) { - if (!grep(/^\Q$tryserver\E$/,@homeservers)) { - push(@homeservers,$tryserver); - } - } - } - my $response; - my %reformatted = %{$instsecref}; - foreach my $server (@homeservers) { - if (ref($instsecref) eq 'HASH') { - my $info = &freeze_escape($instsecref); - my $response=&reply('autoinstsecreformat:'.$cdom.':'. - $action.':'.$info,$server); - next if ($response =~ /(con_lost|error|no_such_host|refused|unknown_command)/); - my @items = split(/&/,$response); - foreach my $item (@items) { - my ($key,$value) = split(/=/,$item); - $reformatted{&unescape($key)} = &thaw_unescape($value); - } - } - } - return %reformatted; -} - -sub auto_validate_instclasses { - my ($cdom,$cnum,$owners,$classesref) = @_; - my ($homeserver,%validations); - $homeserver = &homeserver($cnum,$cdom); - unless ($homeserver eq 'no_host') { - my $ownerlist; - if (ref($owners) eq 'ARRAY') { - $ownerlist = join(',',@{$owners}); - } else { - $ownerlist = $owners; - } - if (ref($classesref) eq 'HASH') { - my $classes = &freeze_escape($classesref); - my $response=&reply('autovalidateinstclasses:'.&escape($ownerlist). - ':'.$cdom.':'.$classes,$homeserver); - unless ($response =~ /(con_lost|error|no_such_host|refused)/) { - my @items = split(/&/,$response); - foreach my $item (@items) { - my ($key,$value) = split('=',$item); - $validations{&unescape($key)} = &thaw_unescape($value); - } - } - } - } - return %validations; -} - sub auto_crsreq_update { my ($cdom,$cnum,$crstype,$action,$ownername,$ownerdomain,$fullname,$title, $code,$accessstart,$accessend,$inbound) = @_; @@ -9983,7 +8355,8 @@ sub auto_crsreq_update { ':'.&escape($action).':'.&escape($ownername).':'. &escape($ownerdomain).':'.&escape($fullname).':'. &escape($title).':'.&escape($code).':'. - &escape($accessstart).':'.&escape($accessend).':'.$info,$homeserver); + &escape($accessstart).':'.&escape($accessend).':'.$info, + $homeserver); unless ($response =~ /(con_lost|error|no_such_host|refused)/) { my @items = split(/&/,$response); foreach my $item (@items) { @@ -10243,6 +8616,7 @@ sub plaintext { my %rolenames = ( Course => 'std', Community => 'alt1', + Placement => 'std', ); if ($cid ne '') { if ($env{'course.'.$cid.'.'.$short.'.plaintext'} ne '') { @@ -10344,12 +8718,8 @@ sub assignrole { } } } - } elsif (($selfenroll == 1) && ($udom eq $env{'user.domain'}) && ($uname eq $env{'user.name'})) { - if ($role eq 'st') { - $refused = ''; - } elsif (($context eq 'ltienroll') && ($env{'request.lti.login'})) { - $refused = ''; - } + } elsif (($selfenroll == 1) && ($role eq 'st') && ($udom eq $env{'user.domain'}) && ($uname eq $env{'user.name'})) { + $refused = ''; } elsif ($context eq 'requestcourses') { my @possroles = ('st','ta','ep','in','cc','co'); if ((grep(/^\Q$role\E$/,@possroles)) && ($env{'user.name'} ne '' && $env{'user.domain'} ne '')) { @@ -10368,7 +8738,7 @@ sub assignrole { } } } elsif ($context eq 'requestauthor') { - if (($udom eq $env{'user.domain'}) && ($uname eq $env{'user.name'}) && + if (($udom eq $env{'user.domain'}) && ($uname eq $env{'user.name'}) && ($url eq '/'.$udom.'/') && ($role eq 'au')) { if ($env{'environment.requestauthor'} eq 'automatic') { $refused = ''; @@ -10376,13 +8746,13 @@ sub assignrole { my %domdefaults = &get_domain_defaults($udom); if (ref($domdefaults{'requestauthor'}) eq 'HASH') { my $checkbystatus; - if ($env{'user.adv'}) { + if ($env{'user.adv'}) { my $disposition = $domdefaults{'requestauthor'}{'_LC_adv'}; if ($disposition eq 'automatic') { $refused = ''; } elsif ($disposition eq '') { $checkbystatus = 1; - } + } } else { $checkbystatus = 1; } @@ -10464,13 +8834,12 @@ sub assignrole { &courserolelog($role,$uname,$udom,$url,$origstart,$origend,$delflag, $selfenroll,$context); } elsif (($role eq 'li') || ($role eq 'dg') || ($role eq 'sc') || - ($role eq 'au') || ($role eq 'dc') || ($role eq 'dh') || - ($role eq 'da')) { + ($role eq 'au') || ($role eq 'dc')) { &domainrolelog($role,$uname,$udom,$url,$origstart,$origend,$delflag, $context); } elsif (($role eq 'ca') || ($role eq 'aa')) { &coauthorrolelog($role,$uname,$udom,$url,$origstart,$origend,$delflag, - $context); + $context); } if ($role eq 'cc') { &autoupdate_coowners($url,$end,$start,$uname,$udom); @@ -10488,23 +8857,11 @@ sub autoupdate_coowners { if ($domdesign{$cdom.'.autoassign.co-owners'}) { my %coursehash = &coursedescription($cdom.'_'.$cnum); my $instcode = $coursehash{'internal.coursecode'}; - my $xlists = $coursehash{'internal.crosslistings'}; if ($instcode ne '') { if (($start && $start <= $now) && ($end == 0) || ($end > $now)) { unless ($coursehash{'internal.courseowner'} eq $uname.':'.$udom) { my ($delcoowners,@newcoowners,$putresult,$delresult,$coowners); my ($result,$desc) = &auto_validate_instcode($cnum,$cdom,$instcode,$uname.':'.$udom); - unless ($result eq 'valid') { - if ($xlists ne '') { - foreach my $xlist (split(',',$xlists)) { - my ($inst_crosslist,$lcsec) = split(':',$xlist); - $result = - &auto_validate_inst_crosslist($cnum,$cdom,$instcode, - $inst_crosslist,$uname.':'.$udom); - last if ($result eq 'valid'); - } - } - } if ($result eq 'valid') { if ($coursehash{'internal.co-owners'}) { foreach my $coowner (split(',',$coursehash{'internal.co-owners'})) { @@ -10517,15 +8874,17 @@ sub autoupdate_coowners { } else { push(@newcoowners,$uname.':'.$udom); } - } elsif ($coursehash{'internal.co-owners'}) { - foreach my $coowner (split(',',$coursehash{'internal.co-owners'})) { - unless ($coowner eq $uname.':'.$udom) { - push(@newcoowners,$coowner); + } else { + if ($coursehash{'internal.co-owners'}) { + foreach my $coowner (split(',',$coursehash{'internal.co-owners'})) { + unless ($coowner eq $uname.':'.$udom) { + push(@newcoowners,$coowner); + } + } + unless (@newcoowners > 0) { + $delcoowners = 1; + $coowners = ''; } - } - unless (@newcoowners > 0) { - $delcoowners = 1; - $coowners = ''; } } if (@newcoowners || $delcoowners) { @@ -10579,35 +8938,19 @@ sub store_coowners { sub modifyuserauth { my ($udom,$uname,$umode,$upass)=@_; my $uhome=&homeserver($uname,$udom); - my $allowed; - if (&allowed('mau',$udom)) { - $allowed = 1; - } elsif (($umode eq 'internal') && ($udom eq $env{'user.domain'}) && - ($env{'request.course.id'}) && (&allowed('mip',$env{'request.course.id'})) && - (!$env{'course.'.$env{'request.course.id'}.'.internal.nopasswdchg'})) { - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; - if (($cdom ne '') && ($cnum ne '')) { - my $is_owner = &is_course_owner($cdom,$cnum); - if ($is_owner) { - $allowed = 1; - } - } - } - unless ($allowed) { return 'refused'; } + unless (&allowed('mau',$udom)) { return 'refused'; } &logthis('Call to modify user authentication '.$udom.', '.$uname.', '. $umode.' by '.$env{'user.name'}.' at '.$env{'user.domain'}. ' in domain '.$env{'request.role.domain'}); my $reply=&reply('encrypt:changeuserauth:'.$udom.':'.$uname.':'.$umode.':'. &escape($upass),$uhome); - my $ip = &get_requestor_ip(); &log($env{'user.domain'},$env{'user.name'},$env{'user.home'}, 'Authentication changed for '.$udom.', '.$uname.', '.$umode. - '(Remote '.$ip.'): '.$reply); + '(Remote '.$ENV{'REMOTE_ADDR'}.'): '.$reply); &log($udom,,$uname,$uhome, 'Authentication changed by '.$env{'user.domain'}.', '. $env{'user.name'}.', '.$umode. - '(Remote '.$ip.'): '.$reply); + '(Remote '.$ENV{'REMOTE_ADDR'}.'): '.$reply); unless ($reply eq 'ok') { &logthis('Authentication mode error: '.$reply); return 'error: '.$reply; @@ -10641,14 +8984,10 @@ sub modifyuser { my $newuser; if ($uhome eq 'no_host') { $newuser = 1; - unless (($umode && ($upass ne '')) || ($umode eq 'localauth') || - ($umode eq 'lti')) { - return 'error: more information needed to create new user'; - } } # ----------------------------------------------------------------- Create User if (($uhome eq 'no_host') && - (($umode && $upass) || ($umode eq 'localauth') || ($umode eq 'lti'))) { + (($umode && $upass) || ($umode eq 'localauth'))) { my $unhome=''; if (defined($desiredhome) && &host_domain($desiredhome) eq $udom) { $unhome = $desiredhome; @@ -10690,7 +9029,7 @@ sub modifyuser { 'current user id "'.$uidhash{$uname}.'".'; } } else { - &idput($udom,($uname => $uid)); + &idput($udom,{$uname => $uid},$uhome,'ids'); } } # -------------------------------------------------------------- Add names, etc @@ -10815,7 +9154,7 @@ sub modifystudent { # student's environment $uid = undef if (!$forceid); $reply = &modify_student_enrollment($udom,$uname,$uid,$first,$middle,$last, - $gene,$usec,$end,$start,$type,$locktype, + $gene,$usec,$end,$start,$type,$locktype, $cid,$selfenroll,$context,$credits,$instsec); return $reply; } @@ -10936,19 +9275,14 @@ sub writecoursepref { sub createcourse { my ($udom,$description,$url,$course_server,$nonstandard,$inst_code, - $course_owner,$crstype,$cnum,$context,$category,$callercontext)=@_; + $course_owner,$crstype,$cnum,$context,$category)=@_; $url=&declutter($url); my $cid=''; if ($context eq 'requestcourses') { my $can_create = 0; my ($ownername,$ownerdom) = split(':',$course_owner); if ($udom eq $ownerdom) { - my $reload; - if (($callercontext eq 'auto') && - ($ownerdom eq $env{'user.domain'}) && ($ownername eq $env{'user.name'})) { - $reload = 'reload'; - } - if (&usertools_access($ownername,$ownerdom,$category,$reload, + if (&usertools_access($ownername,$ownerdom,$category,undef, $context)) { $can_create = 1; } @@ -11097,25 +9431,13 @@ sub generate_coursenum { sub is_course { my ($cdom, $cnum) = scalar(@_) == 1 ? ($_[0] =~ /^($match_domain)_($match_courseid)$/) : @_; - return unless (($cdom =~ /^$match_domain$/) && ($cnum =~ /^$match_courseid$/)); - my $uhome=&homeserver($cnum,$cdom); - my $iscourse; - if (grep { $_ eq $uhome } current_machine_ids()) { - $iscourse = &LONCAPA::Lond::is_course($cdom,$cnum); - } else { - my $hashid = $cdom.':'.$cnum; - ($iscourse,my $cached) = &is_cached_new('iscourse',$hashid); - unless (defined($cached)) { - my %courses = &courseiddump($cdom, '.', 1, '.', '.', - $cnum,undef,undef,'.'); - $iscourse = 0; - if (exists($courses{$cdom.'_'.$cnum})) { - $iscourse = 1; - } - &do_cache_new('iscourse',$hashid,$iscourse,3600); - } - } - return unless($iscourse); + + return unless $cdom and $cnum; + + my %courses = &courseiddump($cdom, '.', 1, '.', '.', $cnum, undef, undef, + '.'); + + return unless(exists($courses{$cdom.'_'.$cnum})); return wantarray ? ($cdom, $cnum) : $cdom.'_'.$cnum; } @@ -11132,7 +9454,7 @@ sub store_userdata { if (($uhome eq '') || ($uhome eq 'no_host')) { $result = 'error: no_host'; } else { - $storehash->{'ip'} = &get_requestor_ip(); + $storehash->{'ip'} = $ENV{'REMOTE_ADDR'}; $storehash->{'host'} = $perlvar{'lonHostID'}; my $namevalue=''; @@ -11251,7 +9573,7 @@ sub save_selected_files { my ($user, $path, @files) = @_; my $filename = $user."savedfiles"; my @other_files = &files_not_in_path($user, $path); - open (OUT,'>',LONCAPA::tempdir().$filename); + open (OUT, '>'.$tmpdir.$filename); foreach my $file (@files) { print (OUT $env{'form.currentpath'}.$file."\n"); } @@ -11265,7 +9587,7 @@ sub save_selected_files { sub clear_selected_files { my ($user) = @_; my $filename = $user."savedfiles"; - open (OUT,'>',LONCAPA::tempdir().$filename); + open (OUT, '>'.LONCAPA::tempdir().$filename); print (OUT undef); close (OUT); return ("ok"); @@ -11275,7 +9597,7 @@ sub files_in_path { my ($user, $path) = @_; my $filename = $user."savedfiles"; my %return_files; - open (IN,'<',LONCAPA::tempdir().$filename); + open (IN, '<'.LONCAPA::tempdir().$filename); while (my $line_in = ) { chomp ($line_in); my @paths_and_file = split (m!/!, $line_in); @@ -11297,7 +9619,7 @@ sub files_not_in_path { my $filename = $user."savedfiles"; my @return_files; my $path_part; - open(IN, '<',LONCAPA::tempdir().$filename); + open(IN, '<'.LONCAPA::.$filename); while (my $line = ) { #ok, I know it's clunky, but I want it to work my @paths_and_file = split(m|/|, $line); @@ -11314,6 +9636,90 @@ sub files_not_in_path { return (@return_files); } +#------------------------------Submitted/Handedback Portfolio Files Versioning + +sub portfiles_versioning { + my ($symb,$domain,$stu_name,$portfiles,$versioned_portfiles) = @_; + my $portfolio_root = '/userfiles/portfolio'; + return unless ((ref($portfiles) eq 'ARRAY') && (ref($versioned_portfiles) eq 'ARRAY')); + foreach my $file (@{$portfiles}) { + &unmark_as_readonly($domain,$stu_name,[$symb,$env{'request.course.id'}],$file); + my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*)$/); + my ($answer_name,$answer_ver,$answer_ext) = &file_name_version_ext($answer_file); + my $getpropath = 1; + my ($dir_list,$listerror) = &dirlist($portfolio_root.$directory,$domain, + $stu_name,$getpropath); + my $version = &get_next_version($answer_name,$answer_ext,$dir_list); + my $new_answer = + &version_selected_portfile($domain,$stu_name,$directory,$answer_file,$version); + if ($new_answer ne 'problem getting file') { + push(@{$versioned_portfiles}, $directory.$new_answer); + &mark_as_readonly($domain,$stu_name,[$directory.$new_answer], + [$symb,$env{'request.course.id'},'graded']); + } + } +} + +sub get_next_version { + my ($answer_name, $answer_ext, $dir_list) = @_; + my $version; + if (ref($dir_list) eq 'ARRAY') { + foreach my $row (@{$dir_list}) { + my ($file) = split(/\&/,$row,2); + my ($file_name,$file_version,$file_ext) = + &file_name_version_ext($file); + if (($file_name eq $answer_name) && + ($file_ext eq $answer_ext)) { + # gets here if filename and extension match, + # regardless of version + if ($file_version ne '') { + # a versioned file is found so save it for later + if ($file_version > $version) { + $version = $file_version; + } + } + } + } + } + $version ++; + return($version); +} + +sub version_selected_portfile { + my ($domain,$stu_name,$directory,$file_name,$version) = @_; + my ($answer_name,$answer_ver,$answer_ext) = + &file_name_version_ext($file_name); + my $new_answer; + $env{'form.copy'} = + &getfile("/uploaded/$domain/$stu_name/portfolio$directory$file_name"); + if($env{'form.copy'} eq '-1') { + $new_answer = 'problem getting file'; + } else { + $new_answer = $answer_name.'.'.$version.'.'.$answer_ext; + my $copy_result = + &finishuserfileupload($stu_name,$domain,'copy', + '/portfolio'.$directory.$new_answer); + } + undef($env{'form.copy'}); + return ($new_answer); +} + +sub file_name_version_ext { + my ($file)=@_; + my @file_parts = split(/\./, $file); + my ($name,$version,$ext); + if (@file_parts > 1) { + $ext=pop(@file_parts); + if (@file_parts > 1 && $file_parts[-1] =~ /^\d+$/) { + $version=pop(@file_parts); + } + $name=join('.',@file_parts); + } else { + $name=join('.',@file_parts); + } + return($name,$version,$ext); +} + #----------------------------------------------Get portfolio file permissions sub get_portfile_permissions { @@ -11458,49 +9864,132 @@ sub modify_access_controls { } sub make_public_indefinitely { - my ($requrl) = @_; + my (@requrl) = @_; + return &automated_portfile_access('public',\@requrl); +} + +sub automated_portfile_access { + my ($accesstype,$addsref,$delsref,$info) = @_; + unless (($accesstype eq 'public') || ($accesstype eq 'ip')) { + return 'invalid'; + } + my %urls; + if (ref($addsref) eq 'ARRAY') { + foreach my $requrl (@{$addsref}) { + if (&is_portfolio_url($requrl)) { + unless (exists($urls{$requrl})) { + $urls{$requrl} = 'add'; + } + } + } + } + if (ref($delsref) eq 'ARRAY') { + foreach my $requrl (@{$delsref}) { + if (&is_portfolio_url($requrl)) { + unless (exists($urls{$requrl})) { + $urls{$requrl} = 'delete'; + } + } + } + } + unless (keys(%urls)) { + return 'invalid'; + } + my $ip; + if ($accesstype eq 'ip') { + if (ref($info) eq 'HASH') { + if ($info->{'ip'} ne '') { + $ip = $info->{'ip'}; + } + } + if ($ip eq '') { + return 'invalid'; + } + } + my $errors; my $now = time; - my $action = 'activate'; - my $aclnum = 0; - if (&is_portfolio_url($requrl)) { + my %current_perms; + foreach my $requrl (sort(keys(%urls))) { + my $action; + if ($urls{$requrl} eq 'add') { + $action = 'activate'; + } else { + $action = 'none'; + } + my $aclnum = 0; my (undef,$udom,$unum,$file_name,$group) = &parse_portfolio_url($requrl); - my $current_perms = &get_portfile_permissions($udom,$unum); - my %access_controls = &get_access_controls($current_perms, + unless (exists($current_perms{$unum.':'.$udom})) { + $current_perms{$unum.':'.$udom} = &get_portfile_permissions($udom,$unum); + } + my %access_controls = &get_access_controls($current_perms{$unum.':'.$udom}, $group,$file_name); foreach my $key (keys(%{$access_controls{$file_name}})) { my ($num,$scope,$end,$start) = ($key =~ /^([^:]+):([a-z]+)_(\d*)_?(\d*)$/); - if ($scope eq 'public') { - if ($start <= $now && $end == 0) { - $action = 'none'; - } else { + if ($scope eq $accesstype) { + if (($start <= $now) && ($end == 0)) { + if ($accesstype eq 'ip') { + if (ref($access_controls{$file_name}{$key}) eq 'HASH') { + if (ref($access_controls{$file_name}{$key}{'ip'}) eq 'ARRAY') { + if (grep(/^\Q$ip\E$/,@{$access_controls{$file_name}{$key}{'ip'}})) { + if ($urls{$requrl} eq 'add') { + $action = 'none'; + last; + } else { + $action = 'delete'; + $aclnum = $num; + last; + } + } + } + } + } elsif ($accesstype eq 'public') { + if ($urls{$requrl} eq 'add') { + $action = 'none'; + last; + } else { + $action = 'delete'; + $aclnum = $num; + last; + } + } + } elsif ($accesstype eq 'public') { $action = 'update'; $aclnum = $num; + last; } - last; } } if ($action eq 'none') { - return 'ok'; + next; } else { my %changes; my $newend = 0; my $newstart = $now; - my $newkey = $aclnum.':public_'.$newend.'_'.$newstart; + my $newkey = $aclnum.':'.$accesstype.'_'.$newend.'_'.$newstart; $changes{$action}{$newkey} = { - type => 'public', + type => $accesstype, time => { start => $newstart, end => $newend, }, }; + if ($accesstype eq 'ip') { + $changes{$action}{$newkey}{'ip'} = [$ip]; + } my ($outcome,$deloutcome,$new_values,$translation) = &modify_access_controls($file_name,\%changes,$udom,$unum); - return $outcome; + unless ($outcome eq 'ok') { + $errors .= $outcome.' '; + } } + } + if ($errors) { + $errors =~ s/\s$//; + return $errors; } else { - return 'invalid'; + return 'ok'; } } @@ -11705,23 +10194,7 @@ sub dirlist { foreach my $user (sort(keys(%allusers))) { push(@alluserslist,$user.'&user'); } - if (!%listerror) { - # no errors - return (\@alluserslist); - } elsif (scalar(keys(%servers)) == 1) { - # one library server, one error - my ($key) = keys(%listerror); - return (\@alluserslist, $listerror{$key}); - } elsif ( grep { $_ eq 'con_lost' } values(%listerror) ) { - # con_lost indicates that we might miss data from at least one - # library server - return (\@alluserslist, 'con_lost'); - } else { - # multiple library servers and no con_lost -> data should be - # complete. - return (\@alluserslist); - } - + return (\@alluserslist); } else { return ([],'missing username'); } @@ -11794,6 +10267,115 @@ sub stat_file { return (); } +# --------------------------------------------------------- recursedirs +# Recursive function to traverse either a specific user's Authoring Space +# or corresponding Published Resource Space, and populate the hash ref: +# $dirhashref with URLs of all directories, and if $filehashref hash +# ref arg is provided, the URLs of any files, excluding versioned, .meta, +# or .rights files in resource space, and .meta, .save, .log, and .bak +# files in Authoring Space. +# +# Inputs: +# +# $is_home - true if current server is home server for user's space +# $context - either: priv, or res respectively for Authoring or Resource Space. +# $docroot - Document root (i.e., /home/httpd/html +# $toppath - Top level directory (i.e., /res/$dom/$uname or /priv/$dom/$uname +# $relpath - Current path (relative to top level). +# $dirhashref - reference to hash to populate with URLs of directories (Required) +# $filehashref - reference to hash to populate with URLs of files (Optional) +# +# Returns: nothing +# +# Side Effects: populates $dirhashref, and $filehashref (if provided). +# +# Currently used by interface/londocs.pm to create linked select boxes for +# directory and filename to import a Course "Author" resource into a course, and +# also to create linked select boxes for Authoring Space and Directory to choose +# save location for creation of a new "standard" problem from the Course Editor. +# + +sub recursedirs { + my ($is_home,$context,$docroot,$toppath,$relpath,$dirhashref,$filehashref) = @_; + return unless (ref($dirhashref) eq 'HASH'); + my $currpath = $docroot.$toppath; + if ($relpath) { + $currpath .= "/$relpath"; + } + my $savefile; + if (ref($filehashref)) { + $savefile = 1; + } + if ($is_home) { + if (opendir(my $dirh,$currpath)) { + foreach my $item (sort { lc($a) cmp lc($b) } grep(!/^\.+$/,readdir($dirh))) { + next if ($item eq ''); + if (-d "$currpath/$item") { + my $newpath; + if ($relpath) { + $newpath = "$relpath/$item"; + } else { + $newpath = $item; + } + $dirhashref->{&Apache::lonlocal::js_escape($newpath)} = 1; + &recursedirs($is_home,$context,$docroot,$toppath,$newpath,$dirhashref,$filehashref); + } elsif ($savefile) { + if ($context eq 'priv') { + unless ($item =~ /\.(meta|save|log|bak|DS_Store)$/) { + $filehashref->{&Apache::lonlocal::js_escape($relpath)}{$item} = 1; + } + } else { + unless (($item =~ /\.meta$/) || ($item =~ /\.\d+\.\w+$/) || ($item =~ /\.rights$/)) { + $filehashref->{&Apache::lonlocal::js_escape($relpath)}{$item} = 1; + } + } + } + } + closedir($dirh); + } + } else { + my ($dirlistref,$listerror) = + &dirlist($toppath.$relpath); + my @dir_lines; + my $dirptr=16384; + if (ref($dirlistref) eq 'ARRAY') { + foreach my $dir_line (sort + { + my ($afile)=split('&',$a,2); + my ($bfile)=split('&',$b,2); + return (lc($afile) cmp lc($bfile)); + } (@{$dirlistref})) { + my ($item,$dom,undef,$testdir,undef,undef,undef,undef,$size,undef,$mtime,undef,undef,undef,$obs,undef) = + split(/\&/,$dir_line,16); + $item =~ s/\s+$//; + next if (($item =~ /^\.\.?$/) || ($obs)); + if ($dirptr&$testdir) { + my $newpath; + if ($relpath) { + $newpath = "$relpath/$item"; + } else { + $relpath = '/'; + $newpath = $item; + } + $dirhashref->{&Apache::lonlocal::js_escape($newpath)} = 1; + &recursedirs($is_home,$context,$docroot,$toppath,$newpath,$dirhashref,$filehashref); + } elsif ($savefile) { + if ($context eq 'priv') { + unless ($item =~ /\.(meta|save|log|bak|DS_Store)$/) { + $filehashref->{$relpath}{$item} = 1; + } + } else { + unless (($item =~ /\.meta$/) || ($item =~ /\.\d+\.\w+$/)) { + $filehashref->{$relpath}{$item} = 1; + } + } + } + } + } + } + return; +} + # -------------------------------------------------------- Value of a Condition # gets the value of a specific preevaluated condition @@ -11957,7 +10539,14 @@ sub get_userresdata { # Parameters: # $name - Course/user name. # $domain - Name of the domain the user/course is registered on. -# $type - Type of thing $name is (must be 'course' or 'user' +# $type - Type of thing $name is (must be 'course' or 'user') +# $mapp - decluttered URL of enclosing map +# $recursed - Ref to scalar -- set to 1, if nested maps have been recursed. +# $recurseup - Ref to array of map URLs, starting with map containing +# $mapp up through hierarchy of nested maps to top level map. +# $courseid - CourseID (first part of param identifier). +# $modifier - Middle part of param identifier. +# $what - Last part of param identifier. # @which - Array of names of resources desired. # Returns: # The value of the first reasource in @which that is found in the @@ -11967,7 +10556,8 @@ sub get_userresdata { # 'user', an undefined reference is returned. # If none of the resources are found, an undef is returned sub resdata { - my ($name,$domain,$type,@which)=@_; + my ($name,$domain,$type,$mapp,$recursed,$recurseup,$courseid, + $modifier,$what,@which)=@_; my $result; if ($type eq 'course') { $result=&get_courseresdata($name,$domain); @@ -11976,250 +10566,64 @@ sub resdata { } if (!ref($result)) { return $result; } foreach my $item (@which) { - if (defined($result->{$item->[0]})) { + if ($item->[1] eq 'course') { + if ((ref($recurseup) eq 'ARRAY') && (ref($recursed) eq 'SCALAR')) { + unless ($$recursed) { + @{$recurseup} = &get_map_hierarchy($mapp,$courseid); + $$recursed = 1; + } + foreach my $item (@${recurseup}) { + my $norecursechk=$courseid.$modifier.$item.'___(all).'.$what; + last if (defined($result->{$norecursechk})); + my $recursechk=$courseid.$modifier.$item.'___(rec).'.$what; + if (defined($result->{$recursechk})) { return [$result->{$recursechk},'map']; } + } + } + } + if (defined($result->{$item->[0]})) { return [$result->{$item->[0]},$item->[1]]; } } return undef; } -sub get_domain_lti { - my ($cdom,$context) = @_; - my ($name,$cachename,%lti); - if ($context eq 'consumer') { - $name = 'ltitools'; - } elsif ($context eq 'provider') { - $name = 'lti'; - } elsif ($context eq 'linkprot') { - $name = 'ltisec'; - } else { - return %lti; - } - if ($context eq 'linkprot') { - $cachename = $context; - } else { - $cachename = $name; - } - my ($result,$cached)=&is_cached_new($cachename,$cdom); +sub get_domain_ltitools { + my ($cdom) = @_; + my %ltitools; + my ($result,$cached)=&is_cached_new('ltitools',$cdom); if (defined($cached)) { if (ref($result) eq 'HASH') { - %lti = %{$result}; + %ltitools = %{$result}; } } else { - my %domconfig = &get_dom('configuration',[$name],$cdom); - if (ref($domconfig{$name}) eq 'HASH') { - if ($context eq 'linkprot') { - if (ref($domconfig{$name}{'linkprot'}) eq 'HASH') { - %lti = %{$domconfig{$name}{'linkprot'}}; - } - } else { - %lti = %{$domconfig{$name}}; - } - } - my $cachetime = 24*60*60; - &do_cache_new($cachename,$cdom,\%lti,$cachetime); - } - return %lti; -} - -sub get_course_lti { - my ($cnum,$cdom,$context) = @_; - my ($name,$cachename,%lti); - if ($context eq 'consumer') { - $name = 'ltitools'; - $cachename = 'courseltitools'; - } elsif ($context eq 'provider') { - $name = 'lti'; - $cachename = 'courselti'; - } else { - return %lti; - } - my $hashid=$cdom.'_'.$cnum; - my ($result,$cached)=&is_cached_new($cachename,$hashid); - if (defined($cached)) { - if (ref($result) eq 'HASH') { - %lti = %{$result}; + my %domconfig = &get_dom('configuration',['ltitools'],$cdom); + if (ref($domconfig{'ltitools'}) eq 'HASH') { + %ltitools = %{$domconfig{'ltitools'}}; } - } else { - %lti = &dump($name,$cdom,$cnum,undef,undef,undef,1); my $cachetime = 24*60*60; - &do_cache_new($cachename,$hashid,\%lti,$cachetime); - } - return %lti; -} - -sub courselti_itemid { - my ($cnum,$cdom,$url,$method,$params,$context) = @_; - my ($chome,$itemid); - $chome = &homeserver($cnum,$cdom); - return if ($chome eq 'no_host'); - if (ref($params) eq 'HASH') { - my $rep; - if (grep { $_ eq $chome } current_machine_ids()) { - $rep = LONCAPA::Lond::crslti_itemid($cdom,$cnum,$url,$method,$params,$perlvar{'lonVersion'}); - } else { - my $escurl = &escape($url); - my $escmethod = &escape($method); - my $items = &freeze_escape($params); - $rep = &reply("encrypt:lti:$cdom:$cnum:$context:$escurl:$escmethod:$items",$chome); - } - unless (($rep=~/^(refused|rejected|error)/) || ($rep eq 'con_lost') || - ($rep eq 'unknown_cmd')) { - $itemid = $rep; - } + &do_cache_new('ltitools',$cdom,\%ltitools,$cachetime); } - return $itemid; + return %ltitools; } -sub domainlti_itemid { - my ($cdom,$url,$method,$params,$context) = @_; - my ($primary_id,$itemid); - $primary_id = &domain($cdom,'primary'); - return if ($primary_id eq ''); - if (ref($params) eq 'HASH') { - my $rep; - if (grep { $_ eq $primary_id } current_machine_ids()) { - $rep = LONCAPA::Lond::domlti_itemid($cdom,$context,$url,$method,$params,$perlvar{'lonVersion'}); - } else { - my $cnum = ''; - my $escurl = &escape($url); - my $escmethod = &escape($method); - my $items = &freeze_escape($params); - $rep = &reply("encrypt:lti:$cdom:$cnum:$context:$escurl:$escmethod:$items",$primary_id); - } - unless (($rep=~/^(refused|rejected|error)/) || ($rep eq 'con_lost') || - ($rep eq 'unknown_cmd')) { - $itemid = $rep; - } - } - return $itemid; -} - -sub get_ltitools_id { - my ($context,$cdom,$cnum,$title) = @_; - my ($lockhash,$tries,$gotlock,$id,$error); - - # get lock on ltitools db - $lockhash = { - lock => $env{'user.name'}. - ':'.$env{'user.domain'}, - }; - $tries = 0; - if ($context eq 'domain') { - $gotlock = &newput_dom('ltitools',$lockhash,$cdom); - } else { - $gotlock = &newput('ltitools',$lockhash,$cdom,$cnum); - } - while (($gotlock ne 'ok') && ($tries<10)) { - $tries ++; - sleep (0.1); - if ($context eq 'domain') { - $gotlock = &newput_dom('ltitools',$lockhash,$cdom); - } else { - $gotlock = &newput('ltitools',$lockhash,$cdom,$cnum); - } - } - if ($gotlock eq 'ok') { - my %currids; - if ($context eq 'domain') { - %currids = &dump_dom('ltitools',$cdom); - } else { - %currids = &dump('ltitools',$cdom,$cnum); - } - if ($currids{'lock'}) { - delete($currids{'lock'}); - if (keys(%currids)) { - my @curr = sort { $a <=> $b } keys(%currids); - if ($curr[-1] =~ /^\d+$/) { - $id = 1 + $curr[-1]; - } - } else { - $id = 1; - } - if ($id) { - if ($context eq 'domain') { - unless (&newput_dom('ltitools',{ $id => $title },$cdom) eq 'ok') { - $error = 'nostore'; - } - } else { - unless (&newput('ltitools',{ $id => $title },$cdom,$cnum) eq 'ok') { - $error = 'nostore'; - } - } - } else { - $error = 'nonumber'; - } - } - my $dellockoutcome; - if ($context eq 'domain') { - $dellockoutcome = &del_dom('ltitools',['lock'],$cdom); - } else { - $dellockoutcome = &del('ltitools',['lock'],$cdom,$cnum); - } - } else { - $error = 'nolock'; - } - return ($id,$error); -} - -sub count_supptools { - my ($cnum,$cdom,$ignorecache,$reload)=@_; +sub get_numsuppfiles { + my ($cnum,$cdom,$ignorecache)=@_; my $hashid=$cnum.':'.$cdom; - my ($numexttools,$cached); + my ($suppcount,$cached); unless ($ignorecache) { - ($numexttools,$cached) = &is_cached_new('supptools',$hashid); + ($suppcount,$cached) = &is_cached_new('suppcount',$hashid); } unless (defined($cached)) { my $chome=&homeserver($cnum,$cdom); - $numexttools = 0; unless ($chome eq 'no_host') { - my ($supplemental) = &Apache::loncommon::get_supplemental($cnum,$cdom,$reload); - if (ref($supplemental) eq 'HASH') { - if ((ref($supplemental->{'ids'}) eq 'HASH') && (ref($supplemental->{'hidden'}) eq 'HASH')) { - foreach my $key (keys(%{$supplemental->{'ids'}})) { - if ($key =~ m{^/adm/$cdom/$cnum/\d+/ext\.tool$}) { - $numexttools ++; - } - } - } - } - } - &do_cache_new('supptools',$hashid,$numexttools,600); - } - return $numexttools; -} - -sub has_unhidden_suppfiles { - my ($cnum,$cdom,$ignorecache,$possdel)=@_; - my $hashid=$cnum.':'.$cdom; - my ($showsupp,$cached); - unless ($ignorecache) { - ($showsupp,$cached) = &is_cached_new('showsupp',$hashid); - } - unless (defined($cached)) { - my $chome=&homeserver($cnum,$cdom); - unless ($chome eq 'no_host') { - my ($supplemental) = &Apache::loncommon::get_supplemental($cnum,$cdom,$ignorecache,$possdel); - if (ref($supplemental) eq 'HASH') { - if ((ref($supplemental->{'ids'}) eq 'HASH') && (ref($supplemental->{'hidden'}) eq 'HASH')) { - foreach my $key (keys(%{$supplemental->{'ids'}})) { - next if ($key =~ /\.sequence$/); - if (ref($supplemental->{'ids'}->{$key}) eq 'ARRAY') { - foreach my $id (@{$supplemental->{'ids'}->{$key}}) { - unless ($supplemental->{'hidden'}->{$id}) { - $showsupp = 1; - last; - } - } - } - last if ($showsupp); - } - } - } + ($suppcount,my $errors) = (0,0); + my $suppmap = 'supplemental.sequence'; + ($suppcount,$errors) = + &Apache::loncommon::recurse_supplemental($cnum,$cdom,$suppmap,$suppcount,$errors); } - &do_cache_new('showsupp',$hashid,$showsupp,600); + &do_cache_new('suppcount',$hashid,$suppcount,600); } - return $showsupp; + return $suppcount; } # @@ -12292,7 +10696,7 @@ sub EXT { if ( (defined($Apache::lonhomework::parsing_a_problem) || defined($Apache::lonhomework::parsing_a_task)) && - ($symbparm eq &symbread()) ) { + ($symbparm eq &symbread()) ) { # if we are in the middle of processing the resource the # get the value we are planning on committing if (defined($Apache::lonhomework::results{$qualifierrest})) { @@ -12413,23 +10817,22 @@ sub EXT { } } - my ($section, $group, @groups); - my ($courselevelm,$courselevel); + my ($section, $group, @groups, @recurseup, $recursed); + my ($courselevelm,$courseleveli,$courselevel,$mapp); if (($courseid eq '') && ($cid)) { $courseid = $cid; } if (($symbparm && $courseid) && - (($courseid eq $env{'request.course.id'}) || ($courseid eq $cid))) { + (($courseid eq $env{'request.course.id'}) || ($courseid eq $cid))) { #print '
'.$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'}; @@ -12446,17 +10849,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); } @@ -12464,15 +10871,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); } @@ -12489,23 +10899,19 @@ sub EXT { if ($thisparm) { return &get_reply([$thisparm,'resource']); } } # ------------------------------------------ fourth, look in resource metadata - + my $what = $spacequalifierrest; - $what=~s/\./\_/; - my $filename; + $what=~s/\./\_/; + my $filename; if (!$symbparm) { $symbparm=&symbread(); } if ($symbparm) { $filename=(&decode_symb($symbparm))[2]; } else { $filename=$env{'request.filename'}; } - my $toolsymb; - if (($filename =~ /ext\.tool$/) && ($what ne '0_gradable')) { - $toolsymb = $symbparm; - } - my $metadata=&metadata($filename,$what,$toolsymb); + my $metadata=&metadata($filename,$what); if (defined($metadata)) { return &get_reply([$metadata,'resource']); } - $metadata=&metadata($filename,'parameter_'.$what,$toolsymb); + $metadata=&metadata($filename,'parameter_'.$what); if (defined($metadata)) { return &get_reply([$metadata,'resource']); } # ----------------------------------------------- fifth, look in rest of course @@ -12513,8 +10919,10 @@ sub EXT { $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); } } @@ -12529,7 +10937,7 @@ sub EXT { if (defined($partgeneral[0])) { return &get_reply(\@partgeneral); } } if ($recurse) { return undef; } - my $pack_def=&packages_tab_default($filename,$varname,$toolsymb); + my $pack_def=&packages_tab_default($filename,$varname); if (defined($pack_def)) { return &get_reply([$pack_def,'resource']); } # ---------------------------------------------------- Any other user namespace } elsif ($realm eq 'environment') { @@ -12554,10 +10962,6 @@ sub EXT { if ($space eq 'name') { return $ENV{'SERVER_NAME'}; } - } elsif ($realm eq 'client') { - if ($space eq 'remote_addr') { - return &get_requestor_ip(); - } } return ''; } @@ -12575,19 +10979,24 @@ 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; } @@ -12622,11 +11031,11 @@ sub sort_course_groups { # Sort groups b } sub packages_tab_default { - my ($uri,$varname,$toolsymb)=@_; + my ($uri,$varname)=@_; my (undef,$part,$name)=split(/\./,$varname); my (@extension,@specifics,$do_default); - foreach my $package (split(/,/,&metadata($uri,'packages',$toolsymb))) { + foreach my $package (split(/,/,&metadata($uri,'packages'))) { my ($pack_type,$pack_part)=split(/_/,$package,2); if ($pack_type eq 'default') { $do_default=1; @@ -12693,14 +11102,13 @@ sub add_prefix_and_part { my %metaentry; my %importedpartids; -my %importedrespids; sub metadata { - my ($uri,$what,$toolsymb,$liburi,$prefix,$depthcount)=@_; + my ($uri,$what,$liburi,$prefix,$depthcount)=@_; $uri=&declutter($uri); # if it is a non metadata possible uri return quickly if (($uri eq '') || (($uri =~ m|^/*adm/|) && - ($uri !~ m|^adm/includes|) && ($uri !~ m{/(smppg|bulletinboard|ext\.tool)$})) || + ($uri !~ m|^adm/includes|) && ($uri !~ m{/(smppg|bulletinboard|exttools?)$})) || ($uri =~ m|/$|) || ($uri =~ m|/.meta$|) || ($uri =~ m{^/*uploaded/.+\.sequence$})) { return undef; } @@ -12719,72 +11127,11 @@ sub metadata { my ($result,$cached)=&is_cached_new('meta',$uri); if (defined($cached)) { return $result->{':'.$what}; } } - -# -# If the uri is for an external tool the file from -# which metadata should be retrieved depends on whether -# the tool had been configured to be gradable (set in the Course -# Editor or Resource Editor). -# -# If a valid symb has been included as the third arg in the call -# to &metadata() that can be used to retrieve the value of -# parameter_0_gradable set for the resource, and included in the -# uploaded map containing the tool. The value is retrieved via -# &EXT(), if a valid symb is available. Otherwise the value of -# gradable in the exttool_$marker.db file for the tool instance -# is retrieved via &get(). -# -# When lonuserstate::traceroute() calls lonnet::EXT() for -# hiddenresource and encrypturl (during course initialization) -# the map-level parameter for resource.0.gradable included in the -# uploaded map containing the tool will not yet have been stored -# in the user_course_parms.db file for the user's session, so in -# this case fall back to retrieving gradable status from the -# exttool_$marker.db file. -# -# In order to avoid an infinite loop, &metadata() will return -# before a call to &EXT(), if the uri is for an external tool -# and the $what for which metadata is being requested is -# parameter_0_gradable or 0_gradable. -# - - if ($uri =~ /ext\.tool$/) { - if (($what eq 'parameter_0_gradable') || ($what eq '0_gradable')) { - return; - } else { - my ($checked,$use_passback); - if ($toolsymb ne '') { - (undef,undef,my $tooluri) = &decode_symb($toolsymb); - if (($tooluri eq $uri) && (&EXT('resource.0.gradable',$toolsymb))) { - $checked = 1; - if (&EXT('resource.0.gradable',$toolsymb) =~ /^yes$/i) { - $use_passback = 1; - } - } - } - unless ($checked) { - my ($ignore,$cdom,$cnum,$marker) = split(m{/},$uri); - $marker=~s/\D//g; - if ($marker) { - my %toolsettings=&get('exttool_'.$marker,['gradable'],$cdom,$cnum); - $use_passback = $toolsettings{'gradable'}; - } - } - if ($use_passback) { - $filename = '/home/httpd/html/res/lib/templates/LTIpassback.tool'; - } else { - $filename = '/home/httpd/html/res/lib/templates/LTIstandard.tool'; - } - } - } - { # Imported parts would go here - my @origfiletagids=(); + my %importedids=(); + my @origfileimportpartids=(); my $importedparts=0; - -# Imported responseids would go here - my $importedresponses=0; # # Is this a recursive call for a library? # @@ -12879,37 +11226,8 @@ sub metadata { my $dir=$filename; $dir=~s|[^/]*$||; $location=&filelocation($dir,$location); - - my $importid=$token->[2]->{'id'}; + my $importmode=$token->[2]->{'importmode'}; -# -# Check metadata for imported file to -# see if it contained response items -# - my %currmetaentry = %metaentry; - my $libresponseorder = &metadata($location,'responseorder'); - my $origfile; - if ($libresponseorder ne '') { - if ($#origfiletagids<0) { - undef(%importedrespids); - undef(%importedpartids); - } - @{$importedrespids{$importid}} = split(/\s*,\s*/,$libresponseorder); - if (@{$importedrespids{$importid}} > 0) { - $importedresponses = 1; -# We need to get the original file and the imported file to get the response order correct -# Load and inspect original file - if ($#origfiletagids<0) { - my $origfilelocation=$perlvar{'lonDocRoot'}.&clutter($uri); - $origfile=&getfile($origfilelocation); - @origfiletagids=($origfile=~/<((?:\w+)response|import|part)[^>]*id\s*=\s*[\"\']([^\"\']+)[\"\'][^>]*>/gs); - } - } - } -# Do not overwrite contents of %metaentry hash for resource itself with -# hash populated for imported library file - %metaentry = %currmetaentry; - undef(%currmetaentry); if ($importmode eq 'problem') { # Import as problem/response $unikey=&add_prefix_and_part($prefix,$token->[2]->{'part'}); @@ -12918,15 +11236,12 @@ sub metadata { $importedparts=1; # We need to get the original file and the imported file to get the part order correct # Good news: we do not need to worry about nested libraries, since parts cannot be nested -# Load and inspect original file if we didn't do that already - if ($#origfiletagids<0) { - undef(%importedrespids); - undef(%importedpartids); - if ($origfile eq '') { - my $origfilelocation=$perlvar{'lonDocRoot'}.&clutter($uri); - $origfile=&getfile($origfilelocation); - @origfiletagids=($origfile=~/<(part|import)[^>]*id\s*=\s*[\"\']([^\"\']+)[\"\'][^>]*>/gs); - } +# Load and inspect original file + if ($#origfileimportpartids<0) { + undef(%importedpartids); + my $origfilelocation=$perlvar{'lonDocRoot'}.&clutter($uri); + my $origfile=&getfile($origfilelocation); + @origfileimportpartids=($origfile=~/<(part|import)[^>]*id\s*=\s*[\"\']([^\"\']+)[\"\'][^>]*>/gs); } # Load and inspect imported file @@ -12951,7 +11266,7 @@ sub metadata { if ($depthcount<20) { my $metadata = - &metadata($uri,'keys',$toolsymb,$location,$unikey, + &metadata($uri,'keys', $location,$unikey, $depthcount+1); foreach my $meta (split(',',$metadata)) { $metaentry{':'.$meta}=$metaentry{':'.$meta}; @@ -13026,7 +11341,7 @@ sub metadata { $dir=~s|[^/]*$||; $location=&filelocation($dir,$location); my $rights_metadata = - &metadata($uri,'keys',$toolsymb,$location,'_rights', + &metadata($uri,'keys',$location,'_rights', $depthcount+1); foreach my $rights (split(',',$rights_metadata)) { #$metaentry{':'.$rights}=$metacache{$uri}->{':'.$rights}; @@ -13040,48 +11355,20 @@ sub metadata { grep { ! $seen{$_} ++ } (split(',',$metaentry{':packages'})); $metaentry{':packages'} = join(',',@uniq_packages); - if (($importedresponses) || ($importedparts)) { - if ($importedparts) { + if ($importedparts) { # We had imported parts and need to rebuild partorder - $metaentry{':partorder'}=''; - $metathesekeys{'partorder'}=1; - } - if ($importedresponses) { -# We had imported responses and need to rebuild responseorder - $metaentry{':responseorder'}=''; - $metathesekeys{'responseorder'}=1; - } - for (my $index=0;$index<$#origfiletagids;$index+=2) { - my $origid = $origfiletagids[$index+1]; - if ($origfiletagids[$index] eq 'part') { -# Original part, part of the problem - if ($importedparts) { - $metaentry{':partorder'}.=','.$origid; - } - } elsif ($origfiletagids[$index] eq 'import') { - if ($importedparts) { -# We have imported parts at this position - $metaentry{':partorder'}.=','.$importedpartids{$origid}; - } - if ($importedresponses) { -# We have imported responses at this position - if (ref($importedrespids{$origid}) eq 'ARRAY') { - $metaentry{':responseorder'}.=','.join(',',map { $origid.'_'.$_ } @{$importedrespids{$origid}}); - } - } - } else { -# Original response item, part of the problem - if ($importedresponses) { - $metaentry{':responseorder'}.=','.$origid; - } - } - } - if ($importedparts) { - $metaentry{':partorder'}=~s/^\,//; - } - if ($importedresponses) { - $metaentry{':responseorder'}=~s/^\,//; - } + $metaentry{':partorder'}=''; + $metathesekeys{'partorder'}=1; + for (my $index=0;$index<$#origfileimportpartids;$index+=2) { + if ($origfileimportpartids[$index] eq 'part') { +# original part, part of the problem + $metaentry{':partorder'}.=','.$origfileimportpartids[$index+1]; + } else { +# we have imported parts at this position + $metaentry{':partorder'}.=','.$importedpartids{$origfileimportpartids[$index+1]}; + } + } + $metaentry{':partorder'}=~s/^\,//; } $metaentry{':keys'} = join(',',keys(%metathesekeys)); @@ -13295,68 +11582,11 @@ sub get_coursechange { } sub devalidate_coursechange_cache { - my ($cdom,$cnum)=@_; - my $hashid=$cdom.'_'.$cnum; + my ($cnum,$cdom)=@_; + my $hashid=$cnum.':'.$cdom; &devalidate_cache_new('crschange',$hashid); } -sub get_suppchange { - 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('suppchange',$hashid); - if ((defined($cached)) && ($change ne '')) { - return $change; - } else { - my %crshash = &get('environment',['internal.supplementalchange'],$cdom,$cnum); - if ($crshash{'internal.supplementalchange'} 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.supplementalchange'}; - } - my $cachetime = 600; - &do_cache_new('suppchange',$hashid,$change,$cachetime); - } - return $change; -} - -sub devalidate_suppchange_cache { - my ($cdom,$cnum)=@_; - my $hashid=$cdom.'_'.$cnum; - &devalidate_cache_new('suppchange',$hashid); -} - -sub update_supp_caches { - my ($cdom,$cnum) = @_; - my %servers = &internet_dom_servers($cdom); - my @ids=¤t_machine_ids(); - foreach my $server (keys(%servers)) { - next if (grep(/^\Q$server\E$/,@ids)); - my $hashid=$cnum.':'.$cdom; - my $cachekey = &escape('showsupp').':'.&escape($hashid); - &remote_devalidate_cache($server,[$cachekey]); - } - &has_unhidden_suppfiles($cnum,$cdom,1,1); - &count_supptools($cnum,$cdom,1); - my $now = time; - if ($env{'request.course.id'} eq $cdom.'_'.$cnum) { - &Apache::lonnet::appenv({'request.course.suppupdated' => $now}); - } - &put('environment',{'internal.supplementalchange' => $now}, - $cdom,$cnum); - &Apache::lonnet::appenv( - {'course.'.$cdom.'_'.$cnum.'.internal.supplementalchange' => $now}); - &do_cache_new('suppchange',$cdom.'_'.$cnum,$now,600); -} - # ------------------------------------------------- Update symbolic store links sub symblist { @@ -13403,21 +11633,23 @@ 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 ($map =~ m{^uploaded/.+\.page$}) { - $ids=$bighash{'ids_'.&clutter_with_no_wrapper($thisurl)}; + if ($noclutter) { + $ids=$bighash{'ids_'.$thisurl}; } else { $ids=$bighash{'ids_'.&clutter($thisurl)}; } unless ($ids) { - my $idkey = 'ids_'.($thisurl =~ m{^/}? '' : '/').$thisurl; + my $idkey = 'ids_'.($thisurl =~ m{^/}? '' : '/').$thisurl; $ids=$bighash{$idkey}; } if ($ids) { @@ -13433,14 +11665,14 @@ sub symbverify { if (ref($encstate)) { $$encstate = $bighash{'encrypted_'.$id}; } - if (($env{'request.role.adv'}) || - ($bighash{'encrypted_'.$id} eq $env{'request.enc'}) || + if (($env{'request.role.adv'}) || + ($bighash{'encrypted_'.$id} eq $env{'request.enc'}) || ($thisurl eq '/adm/navmaps')) { - $okay=1; + $okay=1; last; - } - } - } + } + } + } } untie(%bighash); } @@ -13512,24 +11744,21 @@ sub deversion { # ------------------------------------------------------ Return symb list entry sub symbread { - my ($thisfn,$donotrecurse,$ignorecachednull,$checkforblock,$possibles, - $ignoresymbdb,$noenccheck)=@_; + my ($thisfn,$donotrecurse,$ignorecachednull,$checkforblock,$possibles)=@_; my $cache_str='request.symbread.cached.'.$thisfn; if (defined($env{$cache_str})) { - unless (ref($possibles) eq 'HASH') { - if ($ignorecachednull) { - return $env{$cache_str} unless ($env{$cache_str} eq ''); - } else { - return $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'}) { - return $env{$cache_str}=&symbclean($env{'request.symb'}); - } - $thisfn=$env{'request.filename'}; + return $env{$cache_str}=&symbclean($env{'request.symb'}); + } + $thisfn=$env{'request.filename'}; } if ($thisfn=~m|^/enc/|) { $thisfn=&Apache::lonenc::unencrypted($thisfn); } # is that filename actually a symb? Verify, clean, and return @@ -13543,18 +11772,17 @@ sub symbread { my %bighash; my $syval=''; if (($env{'request.course.fn'}) && ($thisfn)) { - unless ($ignoresymbdb) { - if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db', - &GDBM_READER(),0640)) { - $syval=$hash{$thisfn}; - untie(%hash); - } - if ($syval && $checkforblock) { - my @blockers = &has_comm_blocking('bre',$syval,$thisfn,$ignoresymbdb,$noenccheck); - if (@blockers) { - $syval=''; - } - } + my $targetfn = $thisfn; + if ( ($thisfn =~ m/^(uploaded|editupload)\//) && ($thisfn !~ m/\.(page|sequence)$/) ) { + $targetfn = 'adm/wrapper/'.$thisfn; + } + if ($targetfn =~ m|^adm/wrapper/(ext/.*)|) { + $targetfn=$1; + } + if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db', + &GDBM_READER(),0640)) { + $syval=$hash{$targetfn}; + untie(%hash); } # ---------------------------------------------------------- There was an entry if ($syval) { @@ -13587,21 +11815,16 @@ sub symbread { $syval=&encode_symb($bighash{'map_id_'.$mapid}, $resid,$thisfn); if (ref($possibles) eq 'HASH') { - unless ($bighash{'randomout_'.$ids} || $env{'request.role.adv'}) { - $possibles->{$syval} = 1; - } + $possibles->{$syval} = 1; } if ($checkforblock) { - unless ($bighash{'randomout_'.$ids} || $env{'request.role.adv'}) { - my @blockers = &has_comm_blocking('bre',$syval,$bighash{'src_'.$ids},'',$noenccheck); - if (@blockers) { - $syval = ''; - untie(%bighash); - return $env{$cache_str}=''; - } + my @blockers = &has_comm_blocking('bre',$syval,$bighash{'src_'.$ids}); + if (@blockers) { + $syval = ''; + return; } } - } elsif ((!$donotrecurse) || ($checkforblock) || (ref($possibles) eq 'HASH')) { + } elsif ((!$donotrecurse) || ($checkforblock) || (ref($possibles) eq 'HASH')) { # ------------------------------------------ There is more than one possibility my $realpossible=0; foreach my $id (@possibilities) { @@ -13609,21 +11832,20 @@ sub symbread { my $canaccess; if (($donotrecurse) || ($checkforblock) || (ref($possibles) eq 'HASH')) { $canaccess = 1; - } else { + } 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); - next if ($bighash{'randomout_'.$id} && !$env{'request.role.adv'}); - next unless (($noenccheck) || ($bighash{'encrypted_'.$id} eq $env{'request.enc'})); + $resid,$thisfn); + if (ref($possibles) eq 'HASH') { + $possibles->{$syval} = 1; + } if ($checkforblock) { - my @blockers = &has_comm_blocking('bre',$poss_syval,$file,'',$noenccheck); - if (@blockers > 0) { - $syval = ''; - } else { + my @blockers = &has_comm_blocking('bre',$poss_syval,$file); + unless (@blockers > 0) { $syval = $poss_syval; $realpossible++; } @@ -13631,11 +11853,6 @@ sub symbread { $syval = $poss_syval; $realpossible++; } - if ($syval) { - if (ref($possibles) eq 'HASH') { - $possibles->{$syval} = 1; - } - } } } } @@ -13797,6 +12014,7 @@ sub rndseed { $which =&get_rand_alg($courseid); } if (defined(&getCODE())) { + if ($which eq '64bit5') { return &rndseed_CODE_64bit5($symb,$courseid,$domain,$username); } elsif ($which eq '64bit4') { @@ -13982,7 +12200,7 @@ sub rndseed_CODE_64bit5 { sub setup_random_from_rndseed { my ($rndseed)=@_; if ($rndseed =~/([,:])/) { - my ($num1,$num2) = map { abs($_); } (split(/[,:]/,$rndseed)); + my ($num1,$num2) = map { abs($_); } (split(/[,:]/,$rndseed)); if ((!$num1) || (!$num2) || ($num1 > 2147483562) || ($num2 > 2147483398)) { &Math::Random::random_set_seed_from_phrase($rndseed); } else { @@ -14173,10 +12391,9 @@ sub repcopy_userfile { my $request; $uri=~s/^\///; my $homeserver = &homeserver($cnum,$cdom); - my $hostname = &hostname($homeserver); my $protocol = $protocol{$homeserver}; $protocol = 'http' if ($protocol ne 'https'); - $request=new HTTP::Request('GET',$protocol.'://'.$hostname.'/raw/'.$uri); + $request=new HTTP::Request('GET',$protocol.'://'.&hostname($homeserver).'/raw/'.$uri); my $response=$ua->request($request,$transferfile); # did it work? if ($response->is_error()) { @@ -14200,10 +12417,9 @@ sub tokenwrapper { $file=~s|(\?\.*)*$||; &appenv({"userfile.$udom/$uname/$file" => $env{'request.course.id'}}); my $homeserver = &homeserver($uname,$udom); - my $hostname = &hostname($homeserver); my $protocol = $protocol{$homeserver}; $protocol = 'http' if ($protocol ne 'https'); - return $protocol.'://'.$hostname.'/'.$uri. + return $protocol.'://'.&hostname($homeserver).'/'.$uri. (($uri=~/\?/)?'&':'?').'token='.$token. '&tokenissued='.$perlvar{'lonHostID'}; } else { @@ -14219,10 +12435,9 @@ sub getuploaded { my ($reqtype,$uri,$cdom,$cnum,$info,$rtncode) = @_; $uri=~s/^\///; my $homeserver = &homeserver($cnum,$cdom); - my $hostname = &hostname($homeserver); my $protocol = $protocol{$homeserver}; $protocol = 'http' if ($protocol ne 'https'); - $uri = $protocol.'://'.$hostname.'/raw/'.$uri; + $uri = $protocol.'://'.&hostname($homeserver).'/raw/'.$uri; my $ua=new LWP::UserAgent; my $request=new HTTP::Request($reqtype,$uri); my $response=$ua->request($request); @@ -14242,7 +12457,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; @@ -14355,15 +12570,10 @@ sub machine_ids { sub additional_machine_domains { my @domains; - if (-e "$perlvar{'lonTabDir'}/expected_domains.tab") { - if (open(my $fh,"<","$perlvar{'lonTabDir'}/expected_domains.tab")) { - while( my $line = <$fh>) { - chomp($line); - $line =~ s/\s//g; - push(@domains,$line); - } - close($fh); - } + open(my $fh,"<$perlvar{'lonTabDir'}/expected_domains.tab"); + while( my $line = <$fh>) { + $line =~ s/\s//g; + push(@domains,$line); } return @domains; } @@ -14381,293 +12591,6 @@ sub default_login_domain { return $domain; } -sub shared_institution { - my ($dom,$lonhost) = @_; - if ($lonhost eq '') { - $lonhost = $perlvar{'lonHostID'}; - } - my $same_intdom; - my $hostintdom = &internet_dom($lonhost); - if ($hostintdom ne '') { - my %iphost = &get_iphost(); - my $primary_id = &domain($dom,'primary'); - my $primary_ip = &get_host_ip($primary_id); - if (ref($iphost{$primary_ip}) eq 'ARRAY') { - foreach my $id (@{$iphost{$primary_ip}}) { - my $intdom = &internet_dom($id); - if ($intdom eq $hostintdom) { - $same_intdom = 1; - last; - } - } - } - } - return $same_intdom; -} - -sub uses_sts { - my ($ignore_cache) = @_; - my $lonhost = $perlvar{'lonHostID'}; - my $hostname = &hostname($lonhost); - my $sts_on; - if ($protocol{$lonhost} eq 'https') { - my $cachetime = 12*3600; - if (!$ignore_cache) { - ($sts_on,my $cached)=&is_cached_new('stspolicy',$lonhost); - if (defined($cached)) { - return $sts_on; - } - } - my $ua=new LWP::UserAgent; - my $url = $protocol{$lonhost}.'://'.$hostname.'/index.html'; - my $request=new HTTP::Request('HEAD',$url); - my $response=$ua->request($request); - if ($response->is_success) { - my $has_sts = $response->header('Strict-Transport-Security'); - if ($has_sts eq '') { - $sts_on = 0; - } else { - if ($has_sts =~ /\Qmax-age=\E(\d+)/) { - my $maxage = $1; - if ($maxage) { - $sts_on = 1; - } else { - $sts_on = 0; - } - } else { - $sts_on = 0; - } - } - return &do_cache_new('stspolicy',$lonhost,$sts_on,$cachetime); - } - } - return; -} - -sub waf_allssl { - my ($host_name) = @_; - my $alias = &get_proxy_alias(); - if ($host_name eq '') { - $host_name = $ENV{'SERVER_NAME'}; - } - if (($host_name ne '') && ($alias eq $host_name)) { - my $serverhomedom = &host_domain($perlvar{'lonHostID'}); - my %defdomdefaults = &get_domain_defaults($serverhomedom); - if ($defdomdefaults{'waf_sslopt'}) { - return $defdomdefaults{'waf_sslopt'}; - } - } - return; -} - -sub get_requestor_ip { - my ($r,$nolookup,$noproxy) = @_; - my $from_ip; - if (ref($r)) { - if ($r->can('useragent_ip')) { - if ($noproxy && $r->can('client_ip')) { - $from_ip = $r->client_ip(); - } else { - $from_ip = $r->useragent_ip(); - } - } elsif ($r->connection->can('remote_ip')) { - $from_ip = $r->connection->remote_ip(); - } else { - $from_ip = $r->get_remote_host($nolookup); - } - } else { - $from_ip = $ENV{'REMOTE_ADDR'}; - } - return $from_ip if ($noproxy); - # Who controls proxy settings for server - my $dom_in_use = $Apache::lonnet::perlvar{'lonDefDomain'}; - my $proxyinfo = &get_proxy_settings($dom_in_use); - if ((ref($proxyinfo) eq 'HASH') && ($from_ip)) { - if ($proxyinfo->{'vpnint'}) { - if (&ip_match($from_ip,$proxyinfo->{'vpnint'})) { - return $from_ip; - } - } - if ($proxyinfo->{'trusted'}) { - if (&ip_match($from_ip,$proxyinfo->{'trusted'})) { - my $ipheader = $proxyinfo->{'ipheader'}; - my ($ip,$xfor); - if (ref($r)) { - if ($ipheader) { - $ip = $r->headers_in->{$ipheader}; - } - $xfor = $r->headers_in->{'X-Forwarded-For'}; - } else { - if ($ipheader) { - $ip = $ENV{'HTTP_'.uc($ipheader)}; - } - $xfor = $ENV{'HTTP_X_FORWARDED_FOR'}; - } - if (($ip eq '') && ($xfor ne '')) { - foreach my $poss_ip (reverse(split(/\s*,\s*/,$xfor))) { - unless (&ip_match($poss_ip,$proxyinfo->{'trusted'})) { - $ip = $poss_ip; - last; - } - } - } - if ($ip ne '') { - return $ip; - } - } - } - } - return $from_ip; -} - -sub get_proxy_settings { - my ($dom_in_use) = @_; - my %domdefaults = &Apache::lonnet::get_domain_defaults($dom_in_use); - my $proxyinfo = { - ipheader => $domdefaults{'waf_ipheader'}, - trusted => $domdefaults{'waf_trusted'}, - vpnint => $domdefaults{'waf_vpnint'}, - vpnext => $domdefaults{'waf_vpnext'}, - sslopt => $domdefaults{'waf_sslopt'}, - }; - return $proxyinfo; -} - -sub ip_match { - my ($ip,$pattern_str) = @_; - $ip=Net::CIDR::cidrvalidate($ip); - if ($ip) { - return Net::CIDR::cidrlookup($ip,split(/\s*,\s*/,$pattern_str)); - } - return; -} - -sub get_proxy_alias { - my ($lonid) = @_; - if ($lonid eq '') { - $lonid = $perlvar{'lonHostID'}; - } - if (!defined(&hostname($lonid))) { - return; - } - if ($lonid ne '') { - my ($alias,$cached) = &is_cached_new('proxyalias',$lonid); - if ($cached) { - return $alias; - } - my $dom = &Apache::lonnet::host_domain($lonid); - if ($dom ne '') { - my $cachetime = 60*60*24; - my %domconfig = - &Apache::lonnet::get_dom('configuration',['wafproxy'],$dom); - if (ref($domconfig{'wafproxy'}) eq 'HASH') { - if (ref($domconfig{'wafproxy'}{'alias'}) eq 'HASH') { - $alias = $domconfig{'wafproxy'}{'alias'}{$lonid}; - } - } - return &do_cache_new('proxyalias',$lonid,$alias,$cachetime); - } - } - return; -} - -sub use_proxy_alias { - my ($r,$lonid) = @_; - my $alias = &get_proxy_alias($lonid); - if ($alias) { - my $dom = &host_domain($lonid); - if ($dom ne '') { - my $proxyinfo = &get_proxy_settings($dom); - my ($vpnint,$remote_ip); - if (ref($proxyinfo) eq 'HASH') { - $vpnint = $proxyinfo->{'vpnint'}; - if ($vpnint) { - $remote_ip = &get_requestor_ip($r,1,1); - } - } - unless ($vpnint && &ip_match($remote_ip,$vpnint)) { - return $alias; - } - } - } - return; -} - -sub alias_sso { - my ($lonid) = @_; - if ($lonid eq '') { - $lonid = $perlvar{'lonHostID'}; - } - if (!defined(&hostname($lonid))) { - return; - } - if ($lonid ne '') { - my ($use_alias,$cached) = &is_cached_new('proxysaml',$lonid); - if ($cached) { - return $use_alias; - } - my $dom = &Apache::lonnet::host_domain($lonid); - if ($dom ne '') { - my $cachetime = 60*60*24; - my %domconfig = - &Apache::lonnet::get_dom('configuration',['wafproxy'],$dom); - if (ref($domconfig{'wafproxy'}) eq 'HASH') { - if (ref($domconfig{'wafproxy'}{'saml'}) eq 'HASH') { - $use_alias = $domconfig{'wafproxy'}{'saml'}{$lonid}; - } - } - return &do_cache_new('proxysaml',$lonid,$use_alias,$cachetime); - } - } - return; -} - -sub get_saml_landing { - my ($lonid) = @_; - if ($lonid eq '') { - my $defdom = &default_login_domain(); - my @hosts = ¤t_machine_ids(); - if (@hosts > 1) { - foreach my $hostid (@hosts) { - if (&host_domain($hostid) eq $defdom) { - $lonid = $hostid; - last; - } - } - } else { - $lonid = $perlvar{'lonHostID'}; - } - if ($lonid) { - unless (&Apache::lonnet::host_domain($lonid) eq $defdom) { - return; - } - } else { - return; - } - } elsif (!defined(&hostname($lonid))) { - return; - } - my ($landing,$cached) = &is_cached_new('samllanding',$lonid); - if ($cached) { - return $landing; - } - my $dom = &Apache::lonnet::host_domain($lonid); - if ($dom ne '') { - my $cachetime = 60*60*24; - my %domconfig = - &Apache::lonnet::get_dom('configuration',['login'],$dom); - if (ref($domconfig{'login'}) eq 'HASH') { - if (ref($domconfig{'login'}{'saml'}) eq 'HASH') { - if (ref($domconfig{'login'}{'saml'}{$lonid}) eq 'HASH') { - $landing = 1; - } - } - } - return &do_cache_new('samllanding',$lonid,$landing,$cachetime); - } - return; -} - # ------------------------------------------------------------- Declutters URLs sub declutter { @@ -14718,7 +12641,7 @@ sub clutter { # &logthis("Got a blank emb style"); } } - } elsif ($thisfn =~ m{^/adm/$match_domain/$match_courseid/\d+/ext\.tool$}) { + } elsif ($thisfn =~ m{^/adm/$match_domain/$match_courseid/\d+/exttools?$}) { $thisfn='/adm/wrapper'.$thisfn; } return $thisfn; @@ -14793,51 +12716,37 @@ sub get_dns { } my %alldns; - if (open(my $config,"<","$perlvar{'lonTabDir'}/hosts.tab")) { - foreach my $dns (<$config>) { - next if ($dns !~ /^\^(\S*)/x); - my $line = $1; - my ($host,$protocol) = split(/:/,$line); - if ($protocol ne 'https') { - $protocol = 'http'; - } - $alldns{$host} = $protocol; + open(my $config,"<$perlvar{'lonTabDir'}/hosts.tab"); + foreach my $dns (<$config>) { + next if ($dns !~ /^\^(\S*)/x); + my $line = $1; + my ($host,$protocol) = split(/:/,$line); + if ($protocol ne 'https') { + $protocol = 'http'; } - close($config); + $alldns{$host} = $protocol; } while (%alldns) { my ($dns) = sort { $b cmp $a } keys(%alldns); - my @content; - if ($dns eq Sys::Hostname::FQDN::fqdn()) { - my $command = (split('/',$url))[3]; - my ($dir,$file) = &parse_getdns_url($command,$url); - delete($alldns{$dns}); - next if (($dir eq '') || ($file eq '')); - if (open(my $config,'<',"$dir/$file")) { - @content = <$config>; - close($config); - } - } else { - my $ua=new LWP::UserAgent; - $ua->timeout(30); - my $request=new HTTP::Request('GET',"$alldns{$dns}://$dns$url"); - my $response=$ua->request($request); - delete($alldns{$dns}); - next if ($response->is_error()); - @content = split("\n",$response->content); - } - unless ($nocache) { + my $ua=new LWP::UserAgent; + $ua->timeout(30); + my $request=new HTTP::Request('GET',"$alldns{$dns}://$dns$url"); + my $response=$ua->request($request); + delete($alldns{$dns}); + next if ($response->is_error()); + my @content = split("\n",$response->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"); - if (open(my $config,"<","$perlvar{'lonTabDir'}/dns_$which.tab")) { - my @content = <$config>; - &$func(\@content,$hashref); - } + open($config,"<$perlvar{'lonTabDir'}/dns_$which.tab"); + my @content = <$config>; + &$func(\@content,$hashref); return; } @@ -14865,7 +12774,7 @@ sub parse_dns_checksums_tab { if (ref($lines) eq 'ARRAY') { chomp(@{$lines}); my $version = shift(@{$lines}); - if ($version eq $release) { + if ($version eq $release) { foreach my $line (@{$lines}) { my ($file,$version,$shasum) = split(/,/,$line); if ($file =~ m{^/etc/httpd/conf}) { @@ -14897,21 +12806,6 @@ sub fetch_dns_checksums { return \%checksums; } -sub parse_getdns_url { - my ($command,$url) = @_; - my $dir = $perlvar{'lonTabDir'}; - my $file; - if ($command eq 'hosts') { - $file = 'dns_hosts.tab'; - } elsif ($command eq 'domain') { - $file = 'dns_domain.tab'; - } elsif ($command eq 'checksums') { - my $version = (split('/',$url))[4]; - $file = "dns_checksums/$version.tab", - } - return ($dir,$file); -} - # ------------------------------------------------------------ Read domain file { my $loaded; @@ -14943,7 +12837,7 @@ sub parse_getdns_url { 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); } @@ -14995,23 +12889,8 @@ sub parse_getdns_url { 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)) { @@ -15044,7 +12923,7 @@ sub parse_getdns_url { sub load_hosts_tab { my ($ignore_cache,$nocache) = @_; &get_dns('/adm/dns/hosts',\&parse_hosts_tab,$ignore_cache,$nocache); - open(my $config,"<","$perlvar{'lonTabDir'}/hosts.tab"); + open(my $config,"<$perlvar{'lonTabDir'}/hosts.tab"); my @config = <$config>; &parse_hosts_tab(\@config); close($config); @@ -15306,11 +13185,11 @@ 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 2.11); } -# ------------------------------------------------------- Read loncaparev table +# ---------------------------------------------------------- Read loncaparev table { - sub load_loncaparevs { + sub load_loncaparevs { if (-e "$perlvar{'lonTabDir'}/loncaparevs.tab") { - if (open(my $config,"<","$perlvar{'lonTabDir'}/loncaparevs.tab")) { + if (open(my $config,"<$perlvar{'lonTabDir'}/loncaparevs.tab")) { while (my $configline=<$config>) { chomp($configline); my ($hostid,$loncaparev)=split(/:/,$configline); @@ -15322,11 +13201,11 @@ sub all_loncaparevs { } } -# ----------------------------------------------------- Read serverhostID table +# ---------------------------------------------------------- Read serverhostID table { sub load_serverhomeIDs { if (-e "$perlvar{'lonTabDir'}/serverhomeIDs.tab") { - if (open(my $config,"<","$perlvar{'lonTabDir'}/serverhomeIDs.tab")) { + if (open(my $config,"<$perlvar{'lonTabDir'}/serverhomeIDs.tab")) { while (my $configline=<$config>) { chomp($configline); my ($name,$id)=split(/:/,$configline); @@ -15351,7 +13230,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); @@ -15365,7 +13244,7 @@ BEGIN { } # ------------------------------------------------------------ Read permissions { - open(my $config,"<","$perlvar{'lonTabDir'}/roles.tab"); + open(my $config,"<$perlvar{'lonTabDir'}/roles.tab"); while (my $configline=<$config>) { chomp($configline); @@ -15379,7 +13258,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); @@ -15399,7 +13278,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; } @@ -15414,11 +13293,11 @@ BEGIN { close($config); } -# --------------------------------------------------------- Read loncaparev table +# ---------------------------------------------------------- Read loncaparev table &load_loncaparevs(); -# ------------------------------------------------------- Read serverhostID table +# ---------------------------------------------------------- Read serverhostID table &load_serverhomeIDs(); @@ -15432,7 +13311,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; @@ -15445,7 +13332,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 =~ /^\#/); @@ -15464,16 +13351,6 @@ BEGIN { } -# ------------- set default texengine (domain default overrides this) -{ - $deftex = LONCAPA::texengine(); -} - -# ------------- set default minimum length for passwords for internal auth users -{ - $passwdmin = LONCAPA::passwd_min(); -} - $memcache=new Cache::Memcached({'servers' => ['127.0.0.1:11211'], 'compress_threshold'=> 20_000, }); @@ -15715,10 +13592,12 @@ the answer, and also caches if there is =item * X -B: find the usernames behind a list of IDs -(IDs are a unique resource in a domain, there must be only 1 ID per -username, and only 1 username per ID in a specific domain) (returns -hash: id=>name,id=>name) +B: find the usernames behind either +a list of student/employee IDs or clicker IDs +(student/employee IDs are a unique resource in a domain, there must be +only 1 ID per username, and only 1 username per ID in a specific domain). +clickerIDs are not necessarily unique, as students might share clickers. +(returns hash: id=>name,id=>name) =item * X @@ -15727,7 +13606,27 @@ usernames (returns hash: name=>id,name=> =item * X -B: store away a list of names and associated IDs +B: store away a list of +names and associated student/employee IDs or clicker IDs. + +=item * +X +B: delete unwanted +student/employee ID or clicker ID username look-ups from domain. +The homeserver ($uhome) and namespace ($namespace) are optional. +If no $uhome is provided, it will be determined usig &homeserver() +for each user. If no $namespace is provided, the default is ids. + +=item * +X +B: update +clicker ID-to-username look-ups in clickers.db on library server. +Permitted actions are add or del (i.e., add or delete). The +clickers.db contains clickerID as keys (escaped), and each corresponding +value is an escaped comma-separated list of usernames (for whom the +library server is the homeserver), who registered that particular ID. +If $critical is true, the update will be sent via &critical, otherwise +&reply() will be used. =item * X @@ -15775,13 +13674,13 @@ The first argument is required, all othe $priv is the privilege being checked. $uri contains additional information about what is being checked for access (e.g., -URL, course ID etc.). +URL, course ID etc.). $symb is the unique resource instance identifier in a course; if needed, -but not provided, it will be retrieved via a call to &symbread(). -$role is the role for which a priv is being checked (only used if priv is evb). -$clientip is the user's IP address (only used when checking for access to portfolio +but not provided, it will be retrieved via a call to &symbread(). +$role is the role for which a priv is being checked (only used if priv is evb). +$clientip is the user's IP address (only used when checking for access to portfolio files). -$noblockcheck, if true, skips calls to &has_comm_blocking() for the bre priv. This +$noblockcheck, if true, skips calls to &has_comm_blocking() for the bre priv. This prevents recursive calls to &allowed. F: full access @@ -15791,7 +13690,6 @@ prevents recursive calls to &allowed. 2: browse allowed A: passphrase authentication needed B: access temporarily blocked because of a blocking event in a course. - D: access blocked because access is required via session initiated via deep-link =item * @@ -15810,10 +13708,9 @@ in which case the null string is returne =item * -definerole($rolename,$sysrole,$domrole,$courole,$uname,$udom) : define role; -define a custom role rolename set privileges in format of lonTabs/roles.tab -for system, domain, and course level. $uname and $udom are optional (current -user's username and domain will be used when either of $uname or $udom are absent. +definerole($rolename,$sysrole,$domrole,$courole) : define role; define a custom +role rolename set privileges in format of lonTabs/roles.tab for system, domain, +and course level =item * @@ -15844,9 +13741,9 @@ provided for types, will default to retu =item * in_course($udom,$uname,$cdom,$cnum,$type,$hideprivileged) : determine if -user: $uname:$udom has a role in the course: $cdom_$cnum. +user: $uname:$udom has a role in the course: $cdom_$cnum. -Additional optional arguments are: $type (if role checking is to be restricted +Additional optional arguments are: $type (if role checking is to be restricted to certain user status types -- previous (expired roles), active (currently available roles) or future (roles available in the future), and $hideprivileged -- if true will not report course roles for users who @@ -16084,6 +13981,10 @@ data base, returning a hash that is keye values that are the resource value. I believe that the timestamps and versions are also returned. +get_numsuppfiles($cnum,$cdom) : retrieve number of files in a course's +supplemental content area. This routine caches the number of files for +10 minutes. + =back =head2 Course Modification @@ -16118,88 +14019,6 @@ Returns: =back -=head2 Bubblesheet Configuration - -=over 4 - -=item * - -get_scantron_config($which) - -$which - the name of the configuration to parse from the file. - -Parses and returns the bubblesheet configuration line selected as a -hash of configuration file fields. - - -Returns: - If the named configuration is not in the file, an empty - hash is returned. - - a hash with the fields - name - internal name for the this configuration setup - description - text to display to operator that describes this config - CODElocation - if 0 or the string 'none' - - no CODE exists for this config - if -1 || the string 'letter' - - a CODE exists for this config and is - a string of letters - Unsupported value (but planned for future support) - if a positive integer - - The CODE exists as the first n items from - the question section of the form - if the string 'number' - - The CODE exists for this config and is - a string of numbers - CODEstart - (only matter if a CODE exists) column in the line where - the CODE starts - CODElength - length of the CODE - IDstart - column where the student/employee ID starts - IDlength - length of the student/employee ID info - Qstart - column where the information from the bubbled - 'questions' start - Qlength - number of columns comprising a single bubble line from - the sheet. (usually either 1 or 10) - Qon - either a single character representing the character used - to signal a bubble was chosen in the positional setup, or - the string 'letter' if the letter of the chosen bubble is - in the final, or 'number' if a number representing the - chosen bubble is in the file (1->A 0->J) - Qoff - the character used to represent that a bubble was - left blank - PaperID - if the scanning process generates a unique number for each - sheet scanned the column that this ID number starts in - PaperIDlength - number of columns that comprise the unique ID number - for the sheet of paper - FirstName - column that the first name starts in - FirstNameLength - number of columns that the first name spans - LastName - column that the last name starts in - LastNameLength - number of columns that the last name spans - BubblesPerRow - number of bubbles available in each row used to - bubble an answer. (If not specified, 10 assumed). - - -=item * - -get_scantronformat_file($cdom) - -$cdom - the course's domain (optional); if not supplied, uses -domain for current $env{'request.course.id'}. - -Returns an array containing lines from the scantron format file for -the domain of the course. - -If a url for a custom.tab file is listed in domain's configuration.db, -lines are from this file. - -Otherwise, if a default.tab has been published in RES space by the -domainconfig user, lines are from this file. - -Otherwise, fall back to getting lines from the legacy file on the -local server: /home/httpd/lonTabs/default_scantronformat.tab - -=back - =head2 Resource Subroutines =over 4 @@ -16251,14 +14070,10 @@ condval($condidx) : value of condition i =item * -metadata($uri,$what,$toolsymb,$liburi,$prefix,$depthcount) : request a +metadata($uri,$what,$liburi,$prefix,$depthcount) : request a resource's metadata, $what should be either a specific key, or either 'keys' (to get a list of possible keys) or 'packages' to get a list of -packages that this resource currently uses, the last 3 arguments are -only used internally for recursive metadata. - -the toolsymb is only used where the uri is for an external tool (for which -the uri as well as the symb are guaranteed to be unique). +packages that this resource currently uses, the last 3 arguments are only used internally for recursive metadata. this function automatically caches all requests @@ -16270,20 +14085,20 @@ will be stored for query =item * -symbread($filename,$donotrecurse,$ignorecachednull,$checkforblock,$possibles) : -return symbolic list entry (all arguments optional). +symbread($filename,$donotrecurse,$ignorecachednull,$checkforblock,$possibles) : +return symbolic list entry (all arguments optional). -Args: filename is the filename (including path) for the file for which a symb -is required; donotrecurse, if true will prevent calls to allowed() being made -to check access status if more than one resource was found in the bighash -(see rev. 1.249) to avoid an infinite loop if an ambiguous resource is part of -a randompick); ignorecachednull, if true will prevent a symb of '' being +Args: filename is the filename (including path) for the file for which a symb +is required; donotrecurse, if true will prevent calls to allowed() being made +to check access status if more than one resource was found in the bighash +(see rev. 1.249) to avoid an infinite loop if an ambiguous resource is part of +a randompick); ignorecachednull, if true will prevent a symb of '' being returned if $env{$cache_str} is defined as ''; checkforblock if true will cause possible symbs to be checked to determine if they are subject to content blocking, if so they will not be included as possible symbs; possibles is a -ref to a hash, which, as a side effect, will be populated with all possible +ref to a hash, which, as a side effect, will be populated with all possible symbs (content blocking not tested). - + returns the data handle =item * @@ -16293,9 +14108,9 @@ and is a possible symb for the URL in $t resource that the user accessed using /enc/ returns a 1 on success, 0 on failure, user must be in a course, as it assumes the existence of the course initial hash, and uses $env('request.course.id'}. The third -arg is an optional reference to a scalar. If this arg is passed in the +arg is an optional reference to a scalar. If this arg is passed in the call to symbverify, it will be set to 1 if the symb has been set to be -encrypted; otherwise it will be null. +encrypted; otherwise it will be null. =item * @@ -16348,13 +14163,13 @@ expirespread($uname,$udom,$stype,$usymb) devalidate($symb) : devalidate temporary spreadsheet calculations, forcing spreadsheet to reevaluate the resource scores next time. -=item * +=item * can_edit_resource($file,$cnum,$cdom,$resurl,$symb,$group) : determine if current user can edit a particular resource, when viewing in course context. input: six args -- filename (decluttered), course number, course domain, - url, symb (if registered) and group (if this is a + url, symb (if registered) and group (if this is a group item -- e.g., bulletin board, group page etc.). output: array of five scalars -- @@ -16362,15 +14177,15 @@ when viewing in course context. $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 + $forceedit -- 1 if icon/link should be to go to edit mode $forceview -- 1 if icon/link should be to go to view mode =item * is_course_upload($file,$cnum,$cdom) -Used in course context to determine if current file was uploaded to -the course (i.e., would be found in /userfiles/docs on the course's +Used in course context to determine if current file was uploaded to +the course (i.e., would be found in /userfiles/docs on the course's homeserver. input: 3 args -- filename (decluttered), course number and course domain. @@ -16384,20 +14199,20 @@ homeserver. =item * -store($storehash,$symb,$namespace,$udom,$uname,$laststore) : stores hash +store($storehash,$symb,$namespace,$udom,$uname,$laststore) : stores hash permanently for this url; hashref needs to be given and should be a \%hashname; the remaining args aren't required and if they aren't passed or are '' they will -be derived from the env (with the exception of $laststore, which is an +be derived from the env (with the exception of $laststore, which is an optional arg used when a user's submission is stored in grading). $laststore is $version=$timestamp, where $version is the most recent version number retrieved for the corresponding $symb in the $namespace db file, and $timestamp is the timestamp for that transaction (UNIX time). -$laststore is currently only passed when cstore() is called by +$laststore is currently only passed when cstore() is called by structuretags::finalize_storage(). =item * -cstore($storehash,$symb,$namespace,$udom,$uname,$laststore) : same as store +cstore($storehash,$symb,$namespace,$udom,$uname,$laststore) : same as store but uses critical subroutine =item * @@ -16535,7 +14350,7 @@ server ($udom and $uhome are optional) =item * -get_domain_defaults($target_domain,$ignore_cache) : returns hash with defaults +get_domain_defaults($target_domain,$ignore_cache) : returns hash with defaults for: authentication, language, quotas, timezone, date locale, and portal URL in the target domain. @@ -16569,7 +14384,7 @@ requestcourses: ability to request cours =over =item -official, unofficial, community, textbook +official, unofficial, community, textbook, placement =back @@ -16590,8 +14405,8 @@ for course's uploaded content. =over =item -canuse_pdfforms, officialcredits, unofficialcredits, textbookcredits, officialquota, unofficialquota, -communityquota, textbookquota +canuse_pdfforms, officialcredits, unofficialcredits, textbookcredits, officialquota, unofficialquota, +communityquota, textbookquota, placementquota =back @@ -16601,7 +14416,7 @@ on your servers. =over -=item +=item remotesessions, hostedsessions =back @@ -16609,10 +14424,10 @@ remotesessions, hostedsessions =back In cases where a domain coordinator has never used the "Set Domain Configuration" -utility to create a configuration.db file on a domain's primary library server +utility to create a configuration.db file on a domain's primary library server only the following domain defaults: auth_def, auth_arg_def, lang_def -- corresponding values are authentication type (internal, krb4, krb5, -or localauth), initial password or a kerberos realm, language (e.g., en-us) -- +or localauth), initial password or a kerberos realm, language (e.g., en-us) -- will be available. Values are retrieved from cache (if current), unless the optional $ignore_cache arg is true, or from domain's configuration.db (if available), or lastly from values in lonTabs/dns_domain,tab, or lonTabs/domain.tab. @@ -16895,7 +14710,6 @@ userspace, probably shouldn't be called formname: same as for userfileupload() fname: filename (including subdirectories) for the file parser: if 'parse', will parse (html) file to extract references to objects, links etc. - if hashref, and context is scantron, will convert csv format to standard format allfiles: reference to hash used to store objects found by parser codebase: reference to hash used for codebases of java objects found by parser thumbwidth: width (pixels) of thumbnail to be created for uploaded image @@ -17041,8 +14855,8 @@ Returns: get_timebased_id(): -Attempts to get a unique timestamp-based suffix for use with items added to a -course via the Course Editor (e.g., folders, composite pages, +Attempts to get a unique timestamp-based suffix for use with items added to a +course via the Course Editor (e.g., folders, composite pages, group bulletin boards). Args: (first three required; six others optional) @@ -17053,24 +14867,24 @@ Args: (first three required; six others 2. keyid (alphanumeric): name of temporary locking key in hash, e.g., num, boardids -3. namespace: name of gdbm file used to store suffixes already assigned; +3. namespace: name of gdbm file used to store suffixes already assigned; file will be named nohist_namespace.db 4. cdom: domain of course; default is current course domain from %env 5. cnum: course number; default is current course number from %env -6. idtype: set to concat if an additional digit is to be appended to the +6. idtype: set to concat if an additional digit is to be appended to the unix timestamp to form the suffix, if the plain timestamp is already - in use. Default is to not do this, but simply increment the unix + in use. Default is to not do this, but simply increment the unix timestamp by 1 until a unique key is obtained. 7. who: holder of locking key; defaults to user:domain for user. -8. locktries: number of attempts to obtain a lock (sleep of 1s before +8. locktries: number of attempts to obtain a lock (sleep of 1s before retrying); default is 3. -9. maxtries: number of attempts to obtain a unique suffix; default is 20. +9. maxtries: number of attempts to obtain a unique suffix; default is 20. Returns: