--- loncom/interface/loncommon.pm 2020/02/15 03:57:54 1.1338
+++ loncom/interface/loncommon.pm 2021/06/12 20:51:38 1.1360
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1338 2020/02/15 03:57:54 raeburn Exp $
+# $Id: loncommon.pm,v 1.1360 2021/06/12 20:51:38 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -4893,6 +4893,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()
@@ -5148,13 +5201,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 {
@@ -5172,7 +5225,8 @@ sub blockcheck {
if (($activity eq 'boards' || $activity eq 'chat' ||
$activity eq 'groups' || $activity eq 'printout' ||
- $activity eq 'reinit' || $activity eq 'alert') &&
+ $activity eq 'search' || $activity eq 'reinit' ||
+ $activity eq 'alert') &&
($env{'request.course.id'})) {
foreach my $key (keys(%live_courses)) {
if ($key ne $env{'request.course.id'}) {
@@ -5282,7 +5336,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;
@@ -5302,7 +5356,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 = '';
@@ -5315,7 +5369,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;
@@ -5443,12 +5503,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;
@@ -5459,12 +5519,17 @@ sub blocking_status {
# build a link to a popup window containing the details
my $querystring = "?activity=$activity";
-# $uname and $udom decide whose portfolio the user is trying to look at
- if (($activity eq 'port') || ($activity eq 'passwd')) {
+# $uname and $udom decide whose portfolio (or information page) the user is trying to look at
+ if (($activity eq 'port') || ($activity eq 'about') || ($activity eq 'passwd')) {
$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';
@@ -5489,10 +5554,16 @@ END_MYBLOCK
$text = &mt('Printing Blocked');
} elsif ($activity eq 'passwd') {
$text = &mt('Password Changing Blocked');
+ } elsif ($activity eq 'grades') {
+ $text = &mt('Gradebook Blocked');
+ } elsif ($activity eq 'search') {
+ $text = &mt('Search Blocked');
} elsif ($activity eq 'alert') {
$text = &mt('Checking Critical Messages Blocked');
} elsif ($activity eq 'reinit') {
$text = &mt('Checking Course Update Blocked');
+ } elsif ($activity eq 'about') {
+ $text = &mt('Access to User Information Pages Blocked');
}
$output .= <<"END_BLOCK";
@@ -5516,8 +5587,14 @@ 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 ($ip,$allowed);
+ 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 {
+ my $remote_ip = &Apache::lonnet::get_requestor_ip();
+ $ip = $remote_ip || $env{'request.host'} || $clientip;
+ }
my $name;
my %access = (
@@ -6038,7 +6115,8 @@ other decorations will be returned.
sub bodytag {
my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,
- $no_nav_bar,$bgcolor,$args,$advtoolsref,$ltiscope,$ltiuri,$ltimenu)=@_;
+ $no_nav_bar,$bgcolor,$args,$advtoolsref,$ltiscope,$ltiuri,
+ $ltimenu,$menucoll,$menuref)=@_;
my $public;
if ((($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public'))
@@ -6067,12 +6145,24 @@ sub bodytag {
if ($realm) {
$realm = '/'.$realm;
}
- if ($role eq 'ca') {
+ if ($role eq 'ca') {
my ($rdom,$rname) = ($realm =~ m{^/($match_domain)/($match_username)$});
$realm = &plainname($rname,$rdom);
}
# realm
+ my ($cid,$sec);
if ($env{'request.course.id'}) {
+ $cid = $env{'request.course.id'};
+ if ($env{'request.course.sec'}) {
+ $sec = $env{'request.course.sec'};
+ }
+ } elsif ($realm =~ m{^/($match_domain)/($match_courseid)(?:|/(\w+))$}) {
+ if (&Apache::lonnet::is_course($1,$2)) {
+ $cid = $1.'_'.$2;
+ $sec = $3;
+ }
+ }
+ if ($cid) {
if ($env{'request.role'} !~ /^cr/) {
$role = &Apache::lonnet::plaintext($role,&course_type());
} elsif ($role =~ m{^cr/($match_domain)/\1-domainconfig/(\w+)$}) {
@@ -6084,10 +6174,10 @@ sub bodytag {
} else {
$role = (split(/\//,$role,4))[-1];
}
- if ($env{'request.course.sec'}) {
- $role .= (' 'x2).'- '.&mt('section:').' '.$env{'request.course.sec'};
+ if ($sec) {
+ $role .= (' 'x2).'- '.&mt('section:').' '.$sec;
}
- $realm = $env{'course.'.$env{'request.course.id'}.'.description'};
+ $realm = $env{'course.'.$cid.'.description'};
} else {
$role = &Apache::lonnet::plaintext($role);
}
@@ -6110,13 +6200,25 @@ sub bodytag {
undef($role);
}
- if (($env{'request.course.id'}) && ($env{'request.lti.login'})) {
+ my $showcrstitle = 1;
+ if (($cid) && ($env{'request.lti.login'})) {
if (ref($ltimenu) eq 'HASH') {
unless ($ltimenu->{'role'}) {
undef($role);
}
unless ($ltimenu->{'coursetitle'}) {
$realm=' ';
+ $showcrstitle = 0;
+ }
+ }
+ } elsif (($cid) && ($menucoll)) {
+ if (ref($menuref) eq 'HASH') {
+ unless ($menuref->{'role'}) {
+ undef($role);
+ }
+ unless ($menuref->{'crs'}) {
+ $realm=' ';
+ $showcrstitle = 0;
}
}
}
@@ -6125,17 +6227,15 @@ sub bodytag {
#
# Extra info if you are the DC
my $dc_info = '';
- if ($env{'user.adv'} && exists($env{'user.role.dc./'.
- $env{'course.'.$env{'request.course.id'}.
- '.domain'}.'/'})) {
- my $cid = $env{'request.course.id'};
+ if (($env{'user.adv'}) && ($env{'request.course.id'}) && $showcrstitle &&
+ (exists($env{'user.role.dc./'.$env{'course.'.$cid.'.domain'}.'/'}))) {
$dc_info = $cid.' '.$env{'course.'.$cid.'.internal.coursecode'};
$dc_info =~ s/\s+$//;
}
my $crstype;
- if ($env{'request.course.id'}) {
- $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
+ if ($cid) {
+ $crstype = $env{'course.'.$cid.'.type'};
} elsif ($args->{'crstype'}) {
$crstype = $args->{'crstype'};
}
@@ -6155,7 +6255,7 @@ sub bodytag {
Apache::lonmenu::utilityfunctions($httphost), 'start');
unless ($args->{'no_primary_menu'}) {
- my ($left,$right) = Apache::lonmenu::primary_menu($crstype,$ltimenu);
+ my ($left,$right) = Apache::lonmenu::primary_menu($crstype,$ltimenu,$menucoll,$menuref);
if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
if ($dc_info) {
@@ -6186,7 +6286,8 @@ sub bodytag {
if (!$public){
unless ($args->{'no_inline_menu'}) {
$bodytag .= Apache::lonmenu::secondary_menu($httphost,$ltiscope,$ltimenu,
- $args->{'no_primary_menu'});
+ $args->{'no_primary_menu'},
+ $menucoll,$menuref);
}
$bodytag .= Apache::lonmenu::serverform();
$bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
@@ -8521,43 +8622,99 @@ 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,$offloadoth);
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();
+ $offload = 1;
+ 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'})) {
+ $offloadoth = 1;
+ $dom_in_use = $env{'user.domain'};
}
- my $disable_submit = 0;
- if ($requrl =~ /$LONCAPA::assess_re/) {
- $disable_submit = 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;
+ $offloadoth = 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(undef,30000,undef,1,$dom_in_use);
+ if (($newserver eq '') && ($offloadoth)) {
+ my @domains = &Apache::lonnet::current_machine_domains();
+ if (($dom_in_use ne '') && (!grep(/^\Q$dom_in_use\E$/,@domains))) {
+ ($newserver) = &Apache::lonnet::choose_server($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
- }
}
}
}
@@ -8808,7 +8964,7 @@ sub start_page {
#&Apache::lonnet::logthis("start_page ".join(':',caller(0)));
$env{'internal.start_page'}++;
- my ($result,@advtools,$ltiscope,$ltiuri,%ltimenu);
+ my ($result,@advtools,$ltiscope,$ltiuri,%ltimenu,$menucoll,%menu);
if (! exists($args->{'skip_phases'}{'head'}) ) {
$result .= &xml_begin($args->{'frameset'}) . &headtag($title, $head_extra, $args);
@@ -8843,8 +8999,47 @@ sub start_page {
($ltiscope,$ltiuri) = &LONCAPA::ltiutils::lti_provider_scope($env{'request.lti.uri'},
$env{'course.'.$env{'request.course.id'}.'.domain'},
$env{'course.'.$env{'request.course.id'}.'.num'});
+ } elsif ($env{'request.course.id'}) {
+ my $expiretime=600;
+ if ((time-$env{'course.'.$env{'request.course.id'}.'.last_cache'}) > $expiretime) {
+ &Apache::lonnet::coursedescription($env{'request.course.id'},{'freshen_cache' => 1});
+ }
+ my ($deeplinkmenu,$menuref);
+ ($menucoll,$deeplinkmenu,$menuref) = &menucoll_in_effect();
+ if ($menucoll) {
+ if (ref($menuref) eq 'HASH') {
+ %menu = %{$menuref};
+ }
+ if ($menu{'top'} eq 'n') {
+ $args->{'no_primary_menu'} = 1;
+ }
+ if ($menu{'inline'} eq 'n') {
+ unless (&Apache::lonnet::allowed('opa')) {
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ my $crstype = &course_type();
+ my $now = time;
+ my $ccrole;
+ if ($crstype eq 'Community') {
+ $ccrole = 'co';
+ } else {
+ $ccrole = 'cc';
+ }
+ if ($env{'user.role.'.$ccrole.'./'.$cdom.'/'.$cnum}) {
+ my ($start,$end) = split(/\./,$env{'user.role.'.$ccrole.'./'.$cdom.'/'.$cnum});
+ if ((($start) && ($start<0)) ||
+ (($end) && ($end<$now)) ||
+ (($start) && ($now<$start))) {
+ $args->{'no_inline_menu'} = 1;
+ }
+ } else {
+ $args->{'no_inline_menu'} = 1;
+ }
+ }
+ }
+ }
}
-
+
if (! exists($args->{'skip_phases'}{'body'}) ) {
if ($args->{'frameset'}) {
my $attr_string = &make_attr_string($args->{'force_register'},
@@ -8857,7 +9052,7 @@ sub start_page {
$args->{'only_body'}, $args->{'domain'},
$args->{'force_register'}, $args->{'no_nav_bar'},
$args->{'bgcolor'}, $args,
- \@advtools,$ltiscope,$ltiuri,\%ltimenu);
+ \@advtools,$ltiscope,$ltiuri,\%ltimenu,$menucoll,\%menu);
}
}
@@ -8943,6 +9138,28 @@ sub end_page {
return $result;
}
+sub menucoll_in_effect {
+ my ($menucoll,$deeplinkmenu,%menu);
+ if ($env{'request.course.id'}) {
+ $menucoll = $env{'course.'.$env{'request.course.id'}.'.menudefault'};
+ if (($env{'request.deeplink.login'}) &&
+ ($env{'request.noversionuri'} =~ m{^/(res|uploaded)/})) {
+ my $deeplink = &Apache::lonnet::EXT('resource.0.deeplink');
+ if ($deeplink ne '') {
+ my ($listed,$scope,$access,$display) = split(/,/,$deeplink);
+ if ($display =~ /^\d+$/) {
+ $deeplinkmenu = 1;
+ $menucoll = $display;
+ }
+ }
+ }
+ if ($menucoll) {
+ %menu = &page_menu($env{'course.'.$env{'request.course.id'}.'.menucollections'},$menucoll);
+ }
+ }
+ return ($menucoll,$deeplinkmenu,\%menu);
+}
+
sub wishlist_window {
return(<<'ENDWISHLIST');