--- loncom/interface/loncommon.pm 2021/09/11 16:00:23 1.1075.2.157
+++ loncom/interface/loncommon.pm 2022/01/16 23:25:47 1.1075.2.161.2.2
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1075.2.157 2021/09/11 16:00:23 raeburn Exp $
+# $Id: loncommon.pm,v 1.1075.2.161.2.2 2022/01/16 23:25:47 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -83,6 +83,8 @@ 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);
@@ -1378,7 +1380,7 @@ sub help_open_menu {
}
sub top_nav_help {
- my ($text) = @_;
+ my ($text,$linkattr) = @_;
$text = &mt($text);
my $stay_on_page;
unless ($env{'environment.remote'} eq 'on') {
@@ -1394,7 +1396,7 @@ sub top_nav_help {
if ($link) {
return <<"END";
$banner_link
-$text
+$text
END
} else {
return ' '.$text.' ';
@@ -3127,14 +3129,11 @@ sub authform_filesystem {
$fsyscheck.' onchange="'.$jscall.'" onclick="'.
$jscall.'"'.$disabled.' />';
}
- $autharg = '';
$result = &mt
('[_1] Filesystem Authenticated (with initial password [_2])',
- '');
+ ''.$autharg);
return $result;
}
@@ -4731,8 +4730,77 @@ sub findallcourses {
###############################################
sub blockcheck {
- my ($setters,$activity,$uname,$udom,$url,$is_course,$symb,$caller) = @_;
+ my ($setters,$activity,$clientip,$uname,$udom,$url,$is_course,$symb,$caller) = @_;
+ unless ($activity eq 'docs') {
+ my ($has_evb,$check_ipaccess);
+ my $dom = $env{'user.domain'};
+ if ($env{'request.course.id'}) {
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ my $checkrole = "cm./$cdom/$cnum";
+ my $sec = $env{'request.course.sec'};
+ if ($sec ne '') {
+ $checkrole .= "/$sec";
+ }
+ if ((&Apache::lonnet::allowed('evb',undef,undef,$checkrole)) &&
+ ($env{'request.role'} !~ /^st/)) {
+ $has_evb = 1;
+ }
+ unless ($has_evb) {
+ if (($activity eq 'printout') || ($activity eq 'grades') || ($activity eq 'search') ||
+ ($activity eq 'boards') || ($activity eq 'groups') || ($activity eq 'chat')) {
+ if ($udom eq $cdom) {
+ $check_ipaccess = 1;
+ }
+ }
+ }
+ }
+ unless ($has_evb || $check_ipaccess) {
+ my @machinedoms = &Apache::lonnet::current_machine_domains();
+ if (($dom eq 'public') && ($activity eq 'port')) {
+ $dom = $udom;
+ }
+ if (($dom ne '') && (grep(/^\Q$dom\E$/,@machinedoms))) {
+ $check_ipaccess = 1;
+ } else {
+ my $lonhost = $Apache::lonnet::perlvar{'lonHostID'};
+ my $internet_names = &Apache::lonnet::get_internet_names($lonhost);
+ my $prim = &Apache::lonnet::domain($dom,'primary');
+ my $intdom = &Apache::lonnet::internet_dom($prim);
+ if (($intdom ne '') && (ref($internet_names) eq 'ARRAY')) {
+ if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
+ $check_ipaccess = 1;
+ }
+ }
+ }
+ }
+ if ($check_ipaccess) {
+ my ($ipaccessref,$cached)=&Apache::lonnet::is_cached_new('ipaccess',$dom);
+ unless (defined($cached)) {
+ my %domconfig =
+ &Apache::lonnet::get_dom('configuration',['ipaccess'],$dom);
+ $ipaccessref = &Apache::lonnet::do_cache_new('ipaccess',$dom,$domconfig{'ipaccess'},1800);
+ }
+ if ((ref($ipaccessref) eq 'HASH') && ($clientip)) {
+ foreach my $id (keys(%{$ipaccessref})) {
+ if (ref($ipaccessref->{$id}) eq 'HASH') {
+ my $range = $ipaccessref->{$id}->{'ip'};
+ if ($range) {
+ if (&Apache::lonnet::ip_match($clientip,$range)) {
+ if (ref($ipaccessref->{$id}->{'commblocks'}) eq 'HASH') {
+ if ($ipaccessref->{$id}->{'commblocks'}->{$activity} eq 'on') {
+ return ('','','',$id,$dom);
+ last;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
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))) {
@@ -4748,14 +4816,18 @@ sub blockcheck {
my $startblock = 0;
my $endblock = 0;
my $triggerblock = '';
- my %live_courses = &findallcourses(undef,$uname,$udom);
+ my %live_courses;
+ unless (($activity eq 'wishlist') || ($activity eq 'annotate')) {
+ %live_courses = &findallcourses(undef,$uname,$udom);
+ }
# If uname is for a user, and activity is course-specific, i.e.,
# boards, chat or groups, check for blocking in current course only.
if (($activity eq 'boards' || $activity eq 'chat' ||
- $activity eq 'groups' || $activity eq 'printout') &&
- ($env{'request.course.id'})) {
+ $activity eq 'groups' || $activity eq 'printout' ||
+ $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'}) {
delete($live_courses{$key});
@@ -4955,13 +5027,19 @@ sub get_blocks {
my $end = $start + $env{'course.'.$cdom.'_'.$cnum.'.timerinterval.'.$timersymb};
if ($start && $end) {
if (($start <= time) && ($end >= time)) {
- unless (grep(/^\Q$block\E$/,@blockers)) {
- push(@blockers,$block);
- $triggered{$block} = {
- start => $start,
- end => $end,
- type => $type,
- };
+ if (ref($commblocks{$block}) eq 'HASH') {
+ if (ref($commblocks{$block}{'blocks'}) eq 'HASH') {
+ if ($commblocks{$block}{'blocks'}{$activity} eq 'on') {
+ unless(grep(/^\Q$block\E$/,@blockers)) {
+ push(@blockers,$block);
+ $triggered{$block} = {
+ start => $start,
+ end => $end,
+ type => $type,
+ };
+ }
+ }
+ }
}
}
}
@@ -5025,14 +5103,17 @@ sub parse_block_record {
}
sub blocking_status {
- my ($activity,$uname,$udom,$url,$is_course,$symb,$caller) = @_;
+ my ($activity,$clientip,$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,$symb,$caller);
+ if ($clientip eq '') {
+ $clientip = &Apache::lonnet::get_requestor_ip();
+ }
+ my ($startblock,$endblock,$triggerblock,$by_ip,$blockdom) =
+ &blockcheck(\%setters,$activity,$clientip,$uname,$udom,$url,$is_course,$symb,$caller);
my $blocked = 0;
- if ($startblock && $endblock) {
+ if (($startblock && $endblock) || ($by_ip)) {
$blocked = 1;
}
@@ -5041,8 +5122,8 @@ 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') {
@@ -5076,6 +5157,20 @@ 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');
+ } elsif ($activity eq 'wishlist') {
+ $text = &mt('Access to Stored Links Blocked');
+ } elsif ($activity eq 'annotate') {
+ $text = &mt('Access to Annotations Blocked');
}
$output .= <<"END_BLOCK";
@@ -5110,13 +5205,34 @@ sub check_ip_acc {
}
my $name;
- foreach my $pattern (split(',',$acc)) {
- $pattern =~ s/^\s*//;
- $pattern =~ s/\s*$//;
+ 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';
+ }
if ($pattern =~ /\*$/) {
#35.8.*
$pattern=~s/\*//;
- if ($ip =~ /^\Q$pattern\E/) { $allowed=1; }
+ if ($ip =~ /^\Q$pattern\E/) { $allowed=$access{$acctype}; }
} elsif ($pattern =~ /(\d+\.\d+\.\d+)\.\[(\d+)-(\d+)\]$/) {
#35.8.3.[34-56]
my $low=$2;
@@ -5124,7 +5240,7 @@ sub check_ip_acc {
$pattern=$1;
if ($ip =~ /^\Q$pattern\E/) {
my $last=(split(/\./,$ip))[3];
- if ($last <=$high && $last >=$low) { $allowed=1; }
+ if ($last <=$high && $last >=$low) { $allowed=$access{$acctype}; }
}
} elsif ($pattern =~ /^\*/) {
#*.msu.edu
@@ -5134,10 +5250,10 @@ sub check_ip_acc {
my $netaddr=inet_aton($ip);
($name)=gethostbyaddr($netaddr,AF_INET);
}
- if ($name =~ /\Q$pattern\E$/i) { $allowed=1; }
+ if ($name =~ /\Q$pattern\E$/i) { $allowed=$access{$acctype}; }
} elsif ($pattern =~ /\d+\.\d+\.\d+\.\d+/) {
#127.0.0.1
- if ($ip =~ /^\Q$pattern\E/) { $allowed=1; }
+ if ($ip =~ /^\Q$pattern\E/) { $allowed=$access{$acctype}; }
} else {
#some.name.com
if (!defined($name)) {
@@ -5145,9 +5261,16 @@ sub check_ip_acc {
my $netaddr=inet_aton($ip);
($name)=gethostbyaddr($netaddr,AF_INET);
}
- if ($name =~ /\Q$pattern\E$/i) { $allowed=1; }
+ 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 ($allowed) { last; }
}
return $allowed;
}
@@ -5228,6 +5351,17 @@ sub get_domainconf {
}
}
}
+ } elsif ($key eq 'saml') {
+ if (ref($domconfig{'login'}{$key}) eq 'HASH') {
+ foreach my $host (keys(%{$domconfig{'login'}{$key}})) {
+ if (ref($domconfig{'login'}{$key}{$host}) eq 'HASH') {
+ $designhash{$udom.'.login.'.$key.'_'.$host} = 1;
+ foreach my $item ('text','img','alt','url','title','notsso') {
+ $designhash{$udom.'.login.'.$key.'_'.$item.'_'.$host} = $domconfig{'login'}{$key}{$host}{$item};
+ }
+ }
+ }
+ }
} else {
foreach my $img (keys(%{$domconfig{'login'}{$key}})) {
$designhash{$udom.'.login.'.$key.'_'.$img} =
@@ -5332,8 +5466,12 @@ sub domainlogo {
&Apache::lonnet::repcopy($local_name);
}
$imgsrc = &lonhttpdurl($imgsrc);
- }
- return '
';
+ }
+ my $alttext = $domain;
+ if ($designhash{$domain.'.login.alttext_domlogo'} ne '') {
+ $alttext = $designhash{$domain.'.login.alttext_domlogo'};
+ }
+ return '
';
} elsif (defined(&Apache::lonnet::domain($domain,'description'))) {
return &Apache::lonnet::domain($domain,'description');
} else {
@@ -5557,6 +5695,19 @@ Inputs:
inlineremote items to be added in "Functions" menu below
breadcrumbs.
+=item * $ltiscope, optional argument, will be one of: resource, map or
+ course, if LON-CAPA is in LTI Provider context. Value is
+ the scope of use, i.e., launch was for access to a single, a map
+ or the entire course.
+
+=item * $ltiuri, optional argument, if LON-CAPA is in LTI Provider
+ context, this will contain the URL for the landing item in
+ the course, after launch from an LTI Consumer
+
+=item * $ltimenu, optional argument, if LON-CAPA is in LTI Provider
+ context, this will contain a reference to hash of items
+ to be included in the page header and/or inline menu.
+
=back
Returns: A uniform header for LON-CAPA web pages.
@@ -5568,7 +5719,8 @@ other decorations will be returned.
sub bodytag {
my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,
- $no_nav_bar,$bgcolor,$no_inline_link,$args,$advtoolsref)=@_;
+ $no_nav_bar,$bgcolor,$no_inline_link,$args,$advtoolsref,
+ $ltiscope,$ltiuri,$ltimenu,$menucoll,$menuref)=@_;
my $public;
if ((($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public'))
@@ -5597,12 +5749,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+)$}) {
@@ -5614,10 +5778,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);
}
@@ -5639,19 +5803,47 @@ sub bodytag {
if ($public) {
undef($role);
}
-
+
+ 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;
+ }
+ }
+ }
+
my $titleinfo = '
'.$title.'
';
#
# 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 ($cid) {
+ $crstype = $env{'course.'.$cid.'.type'};
+ } elsif ($args->{'crstype'}) {
+ $crstype = $args->{'crstype'};
+ }
+
$role = '
('.$role.')' if ($role && !$env{'browser.mobile'});
if ($env{'request.state'} eq 'construct') { $forcereg=1; }
@@ -5679,27 +5871,29 @@ sub bodytag {
$bodytag .= Apache::lonhtmlcommon::scripttag(
Apache::lonmenu::utilityfunctions($httphost), 'start');
- my ($left,$right) = Apache::lonmenu::primary_menu();
+ unless ($args->{'no_primary_menu'}) {
+ my ($left,$right) = Apache::lonmenu::primary_menu($args->{'links_disabled'});
- if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
- if ($dc_info) {
- $dc_info = qq|
$dc_info|;
+ if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
+ if ($dc_info) {
+ $dc_info = qq|
$dc_info|;
+ }
+ $bodytag .= qq|
$left $role
+ $realm $dc_info
|;
+ return $bodytag;
}
- $bodytag .= qq|
$left $role
- $realm $dc_info
|;
- return $bodytag;
- }
- unless ($env{'request.symb'} =~ m/\.page___\d+___/) {
- $bodytag .= qq|
$left $role
|;
- }
+ unless ($env{'request.symb'} =~ m/\.page___\d+___/) {
+ $bodytag .= qq|
$left $role
|;
+ }
- $bodytag .= $right;
+ $bodytag .= $right;
- if ($dc_info) {
- $dc_info = &dc_courseid_toggle($dc_info);
+ if ($dc_info) {
+ $dc_info = &dc_courseid_toggle($dc_info);
+ }
+ $bodytag .= qq|
$realm $dc_info
|;
}
- $bodytag .= qq|
$realm $dc_info
|;
#if directed to not display the secondary menu, don't.
if ($args->{'no_secondary_menu'}) {
@@ -5707,17 +5901,22 @@ sub bodytag {
}
#don't show menus for public users
if (!$public){
- $bodytag .= Apache::lonmenu::secondary_menu($httphost);
+ unless ($args->{'no_inline_menu'}) {
+ $bodytag .= Apache::lonmenu::secondary_menu($httphost,$ltiscope,$ltimenu,
+ $args->{'no_primary_menu'},
+ $menucoll,$menuref,
+ $args->{'links_disabled'});
+ }
$bodytag .= Apache::lonmenu::serverform();
$bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
if ($env{'request.state'} eq 'construct') {
$bodytag .= &Apache::lonmenu::innerregister($forcereg,
- $args->{'bread_crumbs'},'','',$hostname);
+ $args->{'bread_crumbs'},'','',$hostname,$ltiscope,$ltiuri);
} elsif ($forcereg) {
$bodytag .= &Apache::lonmenu::innerregister($forcereg,undef,
$args->{'group'},
- $args->{'hide_buttons',
- $hostname});
+ $args->{'hide_buttons'},
+ $hostname,$ltiscope,$ltiuri);
} else {
my $forbodytag;
&Apache::lonmenu::prepare_functions($env{'request.noversionuri'},
@@ -7825,6 +8024,18 @@ ul.LC_funclist li {
cursor:pointer;
}
+.LCisDisabled {
+ cursor: not-allowed;
+ opacity: 0.5;
+}
+
+a[aria-disabled="true"] {
+ color: currentColor;
+ display: inline-block; /* For IE11/ MS Edge bug */
+ pointer-events: none;
+ text-decoration: none;
+}
+
pre.LC_wordwrap {
white-space: pre-wrap;
white-space: -moz-pre-wrap;
@@ -8021,10 +8232,10 @@ ADDMETA
}
}
if ($offload) {
- my $newserver = &Apache::lonnet::spareserver(30000,undef,1,$dom_in_use);
+ 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))) {
+ if (($dom_in_use ne '') && (!grep(/^\Q$dom_in_use\E$/,@domains))) {
($newserver) = &Apache::lonnet::choose_server($dom_in_use);
}
}
@@ -8203,7 +8414,8 @@ sub print_suppression {
}
my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
- my $blocked = &blocking_status('printout',$cnum,$cdom,undef,1);
+ my $clientip = &Apache::lonnet::get_requestor_ip();
+ my $blocked = &blocking_status('printout',$clientip,$cnum,$cdom,undef,1);
if ($blocked) {
my $checkrole = "cm./$cdom/$cnum";
if ($env{'request.course.sec'} ne '') {
@@ -8324,6 +8536,9 @@ $args - additional optional args support
will contain https://
if server uses
https (as per hosts.tab), but request is for http
hostname -> hostname, originally from $r->hostname(), (optional).
+ links_disabled -> Links in primary and secondary menus are disabled
+ (Can enable them once page has loaded - see lonroles.pm
+ for an example).
=back
@@ -8336,11 +8551,81 @@ sub start_page {
#&Apache::lonnet::logthis("start_page ".join(':',caller(0)));
$env{'internal.start_page'}++;
- my ($result,@advtools);
+ my ($result,@advtools,$ltiscope,$ltiuri,%ltimenu,$menucoll,%menu);
if (! exists($args->{'skip_phases'}{'head'}) ) {
$result .= &xml_begin($args->{'frameset'}) . &headtag($title, $head_extra, $args);
}
+
+ if (($env{'request.course.id'}) && ($env{'request.lti.login'})) {
+ if ($env{'course.'.$env{'request.course.id'}.'.lti.override'}) {
+ unless ($env{'course.'.$env{'request.course.id'}.'.lti.topmenu'}) {
+ $args->{'no_primary_menu'} = 1;
+ }
+ unless ($env{'course.'.$env{'request.course.id'}.'.lti.inlinemenu'}) {
+ $args->{'no_inline_menu'} = 1;
+ }
+ if ($env{'course.'.$env{'request.course.id'}.'.lti.lcmenu'}) {
+ map { $ltimenu{$_} = 1; } split(/,/,$env{'course.'.$env{'request.course.id'}.'.lti.lcmenu'});
+ }
+ } else {
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my %lti = &Apache::lonnet::get_domain_lti($cdom,'provider');
+ if (ref($lti{$env{'request.lti.login'}}) eq 'HASH') {
+ unless ($lti{$env{'request.lti.login'}}{'topmenu'}) {
+ $args->{'no_primary_menu'} = 1;
+ }
+ unless ($lti{$env{'request.lti.login'}}{'inlinemenu'}) {
+ $args->{'no_inline_menu'} = 1;
+ }
+ if (ref($lti{$env{'request.lti.login'}}{'lcmenu'}) eq 'ARRAY') {
+ map { $ltimenu{$_} = 1; } @{$lti{$env{'request.lti.login'}}{'lcmenu'}};
+ }
+ }
+ }
+ ($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'}) {
@@ -8354,7 +8639,8 @@ sub start_page {
$args->{'only_body'}, $args->{'domain'},
$args->{'force_register'}, $args->{'no_nav_bar'},
$args->{'bgcolor'}, $args->{'no_inline_link'},
- $args, \@advtools);
+ $args, \@advtools,
+ $ltiscope,$ltiuri,\%ltimenu,$menucoll,\%menu);
}
}
@@ -8389,7 +8675,8 @@ sub start_page {
}
my $menulink;
# if arg: bread_crumbs_nomenu is true pass 0 as $menulink item.
- if (exists($args->{'bread_crumbs_nomenu'})) {
+ if ((exists($args->{'bread_crumbs_nomenu'})) ||
+ ($ltiscope eq 'map') || ($ltiscope eq 'resource')) {
$menulink = 0;
} else {
undef($menulink);
@@ -8397,7 +8684,7 @@ sub start_page {
#if bread_crumbs_component exists show it as headline else show only the breadcrumbs
if(exists($args->{'bread_crumbs_component'})){
$result .= &Apache::lonhtmlcommon::breadcrumbs($args->{'bread_crumbs_component'},'',$menulink);
- }else{
+ } else {
$result .= &Apache::lonhtmlcommon::breadcrumbs('','',$menulink);
}
} elsif (($env{'environment.remote'} eq 'on') &&
@@ -8441,6 +8728,103 @@ 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'}) {
+ my ($deeplink_symb,$deeplink,$check_login_symb);
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ if ($env{'request.noversionuri'} =~ m{^/(res|uploaded)/}) {
+ if ($env{'request.noversionuri'} =~ /\.(page|sequence)$/) {
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (ref($navmap)) {
+ $deeplink = $navmap->get_mapparam(undef,
+ &Apache::lonnet::declutter($env{'request.noversionuri'}),
+ '0.deeplink');
+ } else {
+ $check_login_symb = 1;
+ }
+ } else {
+ my $symb=&Apache::lonnet::symbread();
+ if ($symb) {
+ $deeplink = &Apache::lonnet::EXT('resource.0.deeplink',$symb);
+ } else {
+ $check_login_symb = 1;
+ }
+ }
+ } else {
+ $check_login_symb = 1;
+ }
+ if ($check_login_symb) {
+ $deeplink_symb = &deeplink_login_symb($cnum,$cdom);
+ if ($deeplink_symb =~ /\.(page|sequence)$/) {
+ my $mapname = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($deeplink_symb))[2]);
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (ref($navmap)) {
+ $deeplink = $navmap->get_mapparam(undef,$mapname,'0.deeplink');
+ }
+ } else {
+ $deeplink = &Apache::lonnet::EXT('resource.0.deeplink',$deeplink_symb);
+ }
+ }
+ if ($deeplink ne '') {
+ my ($state,$others,$listed,$scope,$protect,$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 deeplink_login_symb {
+ my ($cnum,$cdom) = @_;
+ my $login_symb;
+ if ($env{'request.deeplink.login'}) {
+ $login_symb = &symb_from_tinyurl($env{'request.deeplink.login'},$cnum,$cdom);
+ }
+ return $login_symb;
+}
+
+sub symb_from_tinyurl {
+ my ($url,$cnum,$cdom) = @_;
+ if ($url =~ m{^\Q/tiny/$cdom/\E(\w+)$}) {
+ my $key = $1;
+ my ($tinyurl,$login);
+ my ($result,$cached)=&Apache::lonnet::is_cached_new('tiny',$cdom."\0".$key);
+ if (defined($cached)) {
+ $tinyurl = $result;
+ } else {
+ my $configuname = &Apache::lonnet::get_domainconfiguser($cdom);
+ my %currtiny = &Apache::lonnet::get('tiny',[$key],$cdom,$configuname);
+ if ($currtiny{$key} ne '') {
+ $tinyurl = $currtiny{$key};
+ &Apache::lonnet::do_cache_new('tiny',$cdom."\0".$key,$currtiny{$key},600);
+ }
+ }
+ if ($tinyurl ne '') {
+ my ($cnumreq,$symb) = split(/\&/,$tinyurl);
+ if (wantarray) {
+ return ($cnumreq,$symb);
+ } elsif ($cnumreq eq $cnum) {
+ return $symb;
+ }
+ }
+ }
+ if (wantarray) {
+ return ();
+ } else {
+ return;
+ }
+}
+
sub wishlist_window {
return(<<'ENDWISHLIST');