--- loncom/interface/loncommon.pm 2020/02/12 22:06:59 1.1075.2.141.2.3
+++ loncom/interface/loncommon.pm 2020/11/12 01:18:26 1.1075.2.149
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1075.2.141.2.3 2020/02/12 22:06:59 raeburn Exp $
+# $Id: loncommon.pm,v 1.1075.2.149 2020/11/12 01:18:26 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -83,8 +83,6 @@ use Crypt::DES;
use DynaLoader; # for Crypt::DES version
use File::Copy();
use File::Path();
-use String::CRC32();
-use Short::URL();
# ---------------------------------------------- Designs
use vars qw(%defaultdesign);
@@ -4425,6 +4423,59 @@ sub get_student_view_with_retries {
}
}
+sub css_links {
+ my ($currsymb,$level) = @_;
+ my ($links,@symbs,%cssrefs,%httpref);
+ if ($level eq 'map') {
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (ref($navmap)) {
+ my ($map,undef,$url)=&Apache::lonnet::decode_symb($currsymb);
+ my @resources = $navmap->retrieveResources($map,sub { $_[0]->is_problem() },0,0);
+ foreach my $res (@resources) {
+ if (ref($res) && $res->symb()) {
+ push(@symbs,$res->symb());
+ }
+ }
+ }
+ } else {
+ @symbs = ($currsymb);
+ }
+ foreach my $symb (@symbs) {
+ my $css_href = &Apache::lonnet::EXT('resource.0.cssfile',$symb);
+ if ($css_href =~ /\S/) {
+ unless ($css_href =~ m{https?://}) {
+ my $url = (&Apache::lonnet::decode_symb($symb))[-1];
+ my $proburl = &Apache::lonnet::clutter($url);
+ my ($probdir) = ($proburl =~ m{(.+)/[^/]+$});
+ unless ($css_href =~ m{^/}) {
+ $css_href = &Apache::lonnet::hreflocation($probdir,$css_href);
+ }
+ if ($css_href =~ m{^/(res|uploaded)/}) {
+ unless (($httpref{'httpref.'.$css_href}) ||
+ (&Apache::lonnet::is_on_map($css_href))) {
+ my $thisurl = $proburl;
+ if ($env{'httpref.'.$proburl}) {
+ $thisurl = $env{'httpref.'.$proburl};
+ }
+ $httpref{'httpref.'.$css_href} = $thisurl;
+ }
+ }
+ }
+ $cssrefs{$css_href} = 1;
+ }
+ }
+ if (keys(%httpref)) {
+ &Apache::lonnet::appenv(\%httpref);
+ }
+ if (keys(%cssrefs)) {
+ foreach my $css_href (keys(%cssrefs)) {
+ next unless ($css_href =~ m{^(/res/|/uploaded/|https?://)});
+ $links .= ''."\n";
+ }
+ }
+ return $links;
+}
+
=pod
=item * &get_student_answers()
@@ -4680,13 +4731,13 @@ sub findallcourses {
###############################################
sub blockcheck {
- my ($setters,$activity,$uname,$udom,$url,$is_course) = @_;
+ my ($setters,$activity,$uname,$udom,$url,$is_course,$symb,$caller) = @_;
if (defined($udom) && defined($uname)) {
# If uname and udom are for a course, check for blocks in the course.
if (($is_course) || (&Apache::lonnet::is_course($udom,$uname))) {
my ($startblock,$endblock,$triggerblock) =
- &get_blocks($setters,$activity,$udom,$uname,$url);
+ &get_blocks($setters,$activity,$udom,$uname,$url,$symb,$caller);
return ($startblock,$endblock,$triggerblock);
}
} else {
@@ -4813,7 +4864,7 @@ sub blockcheck {
# of specified user, unless user has 'evb' privilege.
my ($start,$end,$trigger) =
- &get_blocks($setters,$activity,$cdom,$cnum,$url);
+ &get_blocks($setters,$activity,$cdom,$cnum,$url,$symb,$caller);
if (($start != 0) &&
(($startblock == 0) || ($startblock > $start))) {
$startblock = $start;
@@ -4833,7 +4884,7 @@ sub blockcheck {
}
sub get_blocks {
- my ($setters,$activity,$cdom,$cnum,$url) = @_;
+ my ($setters,$activity,$cdom,$cnum,$url,$symb,$caller) = @_;
my $startblock = 0;
my $endblock = 0;
my $triggerblock = '';
@@ -4846,7 +4897,13 @@ sub get_blocks {
my $now = time;
my %commblocks = &Apache::lonnet::get_comm_blocks($cdom,$cnum);
if ($activity eq 'docs') {
- @blockers = &Apache::lonnet::has_comm_blocking('bre',undef,$url,\%commblocks);
+ my ($blocked,$nosymbcache,$noenccheck);
+ if (($caller eq 'blockedaccess') || ($caller eq 'blockingstatus')) {
+ $blocked = 1;
+ $nosymbcache = 1;
+ $noenccheck = 1;
+ }
+ @blockers = &Apache::lonnet::has_comm_blocking('bre',$symb,$url,$nosymbcache,$noenccheck,$blocked,\%commblocks);
foreach my $block (@blockers) {
if ($block =~ /^firstaccess____(.+)$/) {
my $item = $1;
@@ -4968,12 +5025,12 @@ sub parse_block_record {
}
sub blocking_status {
- my ($activity,$uname,$udom,$url,$is_course) = @_;
+ my ($activity,$uname,$udom,$url,$is_course,$symb,$caller) = @_;
my %setters;
# check for active blocking
my ($startblock,$endblock,$triggerblock) =
- &blockcheck(\%setters,$activity,$uname,$udom,$url,$is_course);
+ &blockcheck(\%setters,$activity,$uname,$udom,$url,$is_course,$symb,$caller);
my $blocked = 0;
if ($startblock && $endblock) {
$blocked = 1;
@@ -4989,7 +5046,12 @@ sub blocking_status {
$querystring .= "&udom=$udom" if ($udom =~ /^$match_domain$/);
$querystring .= "&uname=$uname" if ($uname =~ /^$match_username$/);
} elsif ($activity eq 'docs') {
- $querystring .= '&url='.&HTML::Entities::encode($url,'&"');
+ my $showurl = &Apache::lonenc::check_encrypt($url);
+ $querystring .= '&url='.&HTML::Entities::encode($showurl,'\'&"<>');
+ if ($symb) {
+ my $showsymb = &Apache::lonenc::check_encrypt($symb);
+ $querystring .= '&symb='.&HTML::Entities::encode($showsymb,'\'&"<>');
+ }
}
my $output .= <<'END_MYBLOCK';
@@ -5037,38 +5099,23 @@ sub check_ip_acc {
if (!defined($acc) || $acc =~ /^\s*$/ || $acc =~/^\s*no\s*$/i) {
return 1;
}
- my $allowed;
- my $ip=$ENV{'REMOTE_ADDR'} || $clientip || $env{'request.host'};
+ my $allowed=0;
+ my $ip;
+ if (($ENV{'REMOTE_ADDR'} eq '127.0.0.1') ||
+ ($ENV{'REMOTE_ADDR'} eq &Apache::lonnet::get_host_ip($Apache::lonnet::perlvar{'lonHostID'}))) {
+ $ip = $env{'request.host'} || $ENV{'REMOTE_ADDR'} || $clientip;
+ } else {
+ $ip = $ENV{'REMOTE_ADDR'} || $env{'request.host'} || $clientip;
+ }
my $name;
- my %access = (
- allowfrom => 1,
- denyfrom => 0,
- );
- my @allows;
- my @denies;
- foreach my $item (split(',',$acc)) {
- $item =~ s/^\s*//;
- $item =~ s/\s*$//;
- if ($item =~ /^\!(.+)$/) {
- push(@denies,$1);
- } else {
- push(@allows,$item);
- }
- }
- my $numdenies = scalar(@denies);
- my $numallows = scalar(@allows);
- my $count = 0;
- foreach my $pattern (@denies,@allows) {
- $count ++;
- my $acctype = 'allowfrom';
- if ($count <= $numdenies) {
- $acctype = 'denyfrom';
- }
+ foreach my $pattern (split(',',$acc)) {
+ $pattern =~ s/^\s*//;
+ $pattern =~ s/\s*$//;
if ($pattern =~ /\*$/) {
#35.8.*
$pattern=~s/\*//;
- if ($ip =~ /^\Q$pattern\E/) { $allowed=$access{$acctype}; }
+ if ($ip =~ /^\Q$pattern\E/) { $allowed=1; }
} elsif ($pattern =~ /(\d+\.\d+\.\d+)\.\[(\d+)-(\d+)\]$/) {
#35.8.3.[34-56]
my $low=$2;
@@ -5076,7 +5123,7 @@ sub check_ip_acc {
$pattern=$1;
if ($ip =~ /^\Q$pattern\E/) {
my $last=(split(/\./,$ip))[3];
- if ($last <=$high && $last >=$low) { $allowed=$access{$acctype}; }
+ if ($last <=$high && $last >=$low) { $allowed=1; }
}
} elsif ($pattern =~ /^\*/) {
#*.msu.edu
@@ -5086,10 +5133,10 @@ sub check_ip_acc {
my $netaddr=inet_aton($ip);
($name)=gethostbyaddr($netaddr,AF_INET);
}
- if ($name =~ /\Q$pattern\E$/i) { $allowed=$access{$acctype}; }
+ if ($name =~ /\Q$pattern\E$/i) { $allowed=1; }
} elsif ($pattern =~ /\d+\.\d+\.\d+\.\d+/) {
#127.0.0.1
- if ($ip =~ /^\Q$pattern\E/) { $allowed=$access{$acctype}; }
+ if ($ip =~ /^\Q$pattern\E/) { $allowed=1; }
} else {
#some.name.com
if (!defined($name)) {
@@ -5097,16 +5144,9 @@ sub check_ip_acc {
my $netaddr=inet_aton($ip);
($name)=gethostbyaddr($netaddr,AF_INET);
}
- if ($name =~ /\Q$pattern\E$/i) { $allowed=$access{$acctype}; }
- }
- if ($allowed =~ /^(0|1)$/) { last; }
- }
- if ($allowed eq '') {
- if ($numdenies && !$numallows) {
- $allowed = 1;
- } else {
- $allowed = 0;
+ if ($name =~ /\Q$pattern\E$/i) { $allowed=1; }
}
+ if ($allowed) { last; }
}
return $allowed;
}
@@ -7951,43 +7991,85 @@ ADDMETA
my $dom_in_use = $Apache::lonnet::perlvar{'lonDefDomain'};
unless (&Apache::lonnet::allowed('mau',$dom_in_use)) {
my %domdefs = &Apache::lonnet::get_domain_defaults($dom_in_use);
+ my $lonhost = $Apache::lonnet::perlvar{'lonHostID'};
+ my $offload;
if (ref($domdefs{'offloadnow'}) eq 'HASH') {
- my $lonhost = $Apache::lonnet::perlvar{'lonHostID'};
if ($domdefs{'offloadnow'}{$lonhost}) {
- my $newserver = &Apache::lonnet::spareserver(30000,undef,1,$dom_in_use);
- if (($newserver) && ($newserver ne $lonhost)) {
- my $numsec = 5;
- my $timeout = $numsec * 1000;
- my ($newurl,$locknum,%locks,$msg);
- if ($env{'request.role.adv'}) {
- ($locknum,%locks) = &Apache::lonnet::get_locks();
- }
- my $disable_submit = 0;
- if ($requrl =~ /$LONCAPA::assess_re/) {
- $disable_submit = 1;
+ $offload = 1;
+ }
+ }
+ unless ($offload) {
+ if (ref($domdefs{'offloadoth'}) eq 'HASH') {
+ if ($domdefs{'offloadoth'}{$lonhost}) {
+ if (($env{'user.domain'} ne '') && ($env{'user.domain'} ne $dom_in_use) &&
+ (!(($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public')))) {
+ unless (&Apache::lonnet::shared_institution($env{'user.domain'})) {
+ $offload = 1;
+ $dom_in_use = $env{'user.domain'};
+ }
}
- if ($locknum) {
- my @lockinfo = sort(values(%locks));
- $msg = &mt('Once the following tasks are complete: ')."\\n".
- join(", ",sort(values(%locks)))."\\n".
- &mt('your session will be transferred to a different server, after you click "Roles".');
+ }
+ }
+ }
+ if ($offload) {
+ my $newserver = &Apache::lonnet::spareserver(30000,undef,1,$dom_in_use);
+ if (($newserver) && ($newserver ne $lonhost)) {
+ my $numsec = 5;
+ my $timeout = $numsec * 1000;
+ my ($newurl,$locknum,%locks,$msg);
+ if ($env{'request.role.adv'}) {
+ ($locknum,%locks) = &Apache::lonnet::get_locks();
+ }
+ my $disable_submit = 0;
+ if ($requrl =~ /$LONCAPA::assess_re/) {
+ $disable_submit = 1;
+ }
+ if ($locknum) {
+ my @lockinfo = sort(values(%locks));
+ $msg = &mt('Once the following tasks are complete: ')."\n".
+ join(", ",sort(values(%locks)))."\n";
+ if (&show_course()) {
+ $msg .= &mt('your session will be transferred to a different server, after you click "Courses".');
} else {
- if (($requrl =~ m{^/res/}) && ($env{'form.submitted'} =~ /^part_/)) {
- $msg = &mt('Your LON-CAPA submission has been recorded')."\\n";
- }
- $msg .= &mt('Your current LON-CAPA session will be transferred to a different server in [quant,_1,second].',$numsec);
- $newurl = '/adm/switchserver?otherserver='.$newserver;
- if (($env{'request.role'}) && ($env{'request.role'} ne 'cm')) {
- $newurl .= '&role='.$env{'request.role'};
+ $msg .= &mt('your session will be transferred to a different server, after you click "Roles".');
+ }
+ } else {
+ if (($requrl =~ m{^/res/}) && ($env{'form.submitted'} =~ /^part_/)) {
+ $msg = &mt('Your LON-CAPA submission has been recorded')."\n";
+ }
+ $msg .= &mt('Your current LON-CAPA session will be transferred to a different server in [quant,_1,second].',$numsec);
+ $newurl = '/adm/switchserver?otherserver='.$newserver;
+ if (($env{'request.role'}) && ($env{'request.role'} ne 'cm')) {
+ $newurl .= '&role='.$env{'request.role'};
+ }
+ if ($env{'request.symb'}) {
+ my $shownsymb = &Apache::lonenc::check_encrypt($env{'request.symb'});
+ if ($shownsymb =~ m{^/enc/}) {
+ my $reqdmajor = 2;
+ my $reqdminor = 11;
+ my $reqdsubminor = 3;
+ my $newserverrev = &Apache::lonnet::get_server_loncaparev('',$newserver);
+ my $remoterev = &Apache::lonnet::get_server_loncaparev(undef,$newserver);
+ my ($major,$minor,$subminor) = ($remoterev =~ /^\'?(\d+)\.(\d+)\.(\d+|)[\w.\-]+\'?$/);
+ if (($major eq '' && $minor eq '') ||
+ (($reqdmajor > $major) || (($reqdmajor == $major) && ($reqdminor > $minor)) ||
+ (($reqdmajor == $major) && ($reqdminor == $minor) && (($subminor eq '') ||
+ ($reqdsubminor > $subminor))))) {
+ undef($shownsymb);
+ }
}
- if ($env{'request.symb'}) {
- $newurl .= '&symb='.$env{'request.symb'};
- } else {
- $newurl .= '&origurl='.$requrl;
+ if ($shownsymb) {
+ &js_escape(\$shownsymb);
+ $newurl .= '&symb='.$shownsymb;
}
+ } else {
+ my $shownurl = &Apache::lonenc::check_encrypt($requrl);
+ &js_escape(\$shownurl);
+ $newurl .= '&origurl='.$shownurl;
}
- &js_escape(\$msg);
- $result.=<
OFFLOAD
- }
}
}
}
@@ -15493,12 +15574,17 @@ sub construct_course {
# Open all assignments
#
if ($args->{'openall'}) {
+ my $opendate = time;
+ if ($args->{'openallfrom'} =~ /^\d+$/) {
+ $opendate = $args->{'openallfrom'};
+ }
my $storeunder=$$crsudom.'_'.$$crsunum.'.0.opendate';
- my %storecontent = ($storeunder => time,
+ my %storecontent = ($storeunder => $opendate,
$storeunder.'.type' => 'date_start');
-
- $outcome .= &mt('Opening all assignments').': '.&Apache::lonnet::cput
- ('resourcedata',\%storecontent,$$crsudom,$$crsunum).$linefeed;
+ $outcome .= &mt('All assignments open starting [_1]',
+ &Apache::lonlocal::locallocaltime($opendate)).': '.
+ &Apache::lonnet::cput
+ ('resourcedata',\%storecontent,$$crsudom,$$crsunum).$linefeed;
}
#
# Set first page
@@ -17202,131 +17288,6 @@ sub des_decrypt {
return $plaintext;
}
-sub make_short_symbs {
- my ($cdom,$cnum,$navmap) = @_;
- return unless (ref($navmap));
- my ($numnew,@errors);
- my @toshorten = &Apache::loncommon::get_env_multiple('form.addtiny');
- if (@toshorten) {
- my (%maps,%resources,%titles);
- &Apache::loncourserespicker::enumerate_course_contents($navmap,\%maps,\%resources,\%titles,
- 'shorturls',$cdom,$cnum);
- my %tocreate;
- if (keys(%resources)) {
- foreach my $item (sort {$a <=> $b} (@toshorten)) {
- my $symb = $resources{$item};
- if ($symb) {
- $tocreate{$cnum.'&'.$symb} = 1;
- }
- }
- }
- if (keys(%tocreate)) {
- my %coursetiny = &Apache::lonnet::dump('tiny',$cdom,$cnum);
- my $su = Short::URL->new(no_vowels => 1);
- my $init = '';
- my (%newunique,%addcourse,%courseonly,%failed);
- # get lock on tiny db
- my $now = time;
- my $lockhash = {
- "lock\0$now" => $env{'user.name'}.
- ':'.$env{'user.domain'},
- };
- my $tries = 0;
- my $gotlock = &Apache::lonnet::newput_dom('tiny',$lockhash,$cdom);
- my ($code,$error);
- while (($gotlock ne 'ok') && ($tries<3)) {
- $tries ++;
- sleep 1;
- $gotlock = &Apache::lonnet::newput_dom('tiny',$lockhash,$cdom);
- }
- if ($gotlock eq 'ok') {
- $init = &shorten_symbs($cdom,$init,$su,\%coursetiny,\%tocreate,\%newunique,
- \%addcourse,\%courseonly,\%failed);
- if (keys(%failed)) {
- my $numfailed = scalar(keys(%failed));
- push(@errors,&mt('error: could not obtain unique six character URL for [quant,_1,resource]',$numfailed));
- }
- if (keys(%newunique)) {
- my $putres = &Apache::lonnet::newput_dom('tiny',\%newunique,$cdom);
- if ($putres eq 'ok') {
- $numnew = scalar(keys(%newunique));
- my $newputres = &Apache::lonnet::newput('tiny',\%addcourse,$cdom,$cnum);
- unless ($newputres eq 'ok') {
- push(@errors,&mt('error: could not store course look-up of short URLs'));
- }
- } else {
- push(@errors,&mt('error: could not store unique six character URLs'));
- }
- }
- }
- }
- }
- return ($numnew,\@errors);
-}
-
-sub shorten_symbs {
- my ($cdom,$init,$su,$coursetiny,$tocreate,$newunique,$addcourse,$courseonly,$failed) = @_;
- return unless ((ref($su)) && (ref($coursetiny) eq 'HASH') && (ref($tocreate) eq 'HASH') &&
- (ref($newunique) eq 'HASH') && (ref($addcourse) eq 'HASH') &&
- (ref($courseonly) eq 'HASH') && (ref($failed) eq 'HASH'));
- my (%possibles,%collisions);
- foreach my $key (keys(%{$tocreate})) {
- my $num = String::CRC32::crc32($key);
- my $tiny = $su->encode($num,$init);
- if ($tiny) {
- $possibles{$tiny} = $key;
- }
- }
- if (!$init) {
- $init = 1;
- } else {
- $init ++;
- }
- if (keys(%possibles)) {
- my @posstiny = keys(%possibles);
- my $configuname = &Apache::lonnet::get_domainconfiguser($cdom);
- my %currtiny = &Apache::lonnet::get('tiny',\@posstiny,$cdom,$configuname);
- if (keys(%currtiny)) {
- foreach my $key (keys(%currtiny)) {
- next if ($currtiny{$key} eq '');
- if ($currtiny{$key} eq $possibles{$key}) {
- my ($tcnum,$tsymb) = split(/\&/,$currtiny{$key});
- unless (($coursetiny->{$tsymb} eq $key) || ($addcourse->{$tsymb} eq $key) || ($courseonly->{$tsymb} eq $key)) {
- $courseonly->{$tsymb} = $key;
- }
- } else {
- $collisions{$possibles{$key}} = 1;
- }
- delete($possibles{$key});
- }
- }
- foreach my $key (keys(%possibles)) {
- $newunique->{$key} = $possibles{$key};
- my ($tcnum,$tsymb) = split(/\&/,$possibles{$key});
- unless (($coursetiny->{$tsymb} eq $key) || ($addcourse->{$tsymb} eq $key) || ($courseonly->{$tsymb} eq $key)) {
- $addcourse->{$tsymb} = $key;
- }
- }
- }
- if (keys(%collisions)) {
- if ($init <5) {
- if (!$init) {
- $init = 1;
- } else {
- $init ++;
- }
- $init = &shorten_symbs($cdom,$init,$su,$coursetiny,\%collisions,
- $newunique,$addcourse,$courseonly,$failed);
- } else {
- foreach my $key (keys(%collisions)) {
- $failed->{$key} = 1;
- $failed->{$key} = 1;
- }
- }
- }
- return $init;
-}
-
sub is_nonframeable {
my ($url,$absolute,$hostname,$ip,$nocache) = @_;
my ($remprotocol,$remhost) = ($url =~ m{^(https?)\://(([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,})}i);