--- loncom/interface/lontiny.pm 2023/01/21 21:16:25 1.8.2.4
+++ loncom/interface/lontiny.pm 2024/11/17 04:48:15 1.23
@@ -2,7 +2,7 @@
# Extract domain, courseID, and symb from a shortened URL,
# and switch role to a role in designated course.
#
-# $Id: lontiny.pm,v 1.8.2.4 2023/01/21 21:16:25 raeburn Exp $
+# $Id: lontiny.pm,v 1.23 2024/11/17 04:48:15 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -68,7 +68,7 @@ sub handler {
my $chome = &Apache::lonnet::homeserver($cnum,$cdom);
if ($chome ne 'no_host') {
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['ttoken']);
- my ($linkprot,$linkprotuser,$linkprotexit,$ltoken);
+ my ($linkprot,$linkprotuser,$linkprotexit,$ltoken,$linkprotpbid,$linkprotpburl);
if ($env{'form.ttoken'}) {
my %link_info = &Apache::lonnet::tmpget($env{'form.ttoken'});
if ($link_info{'origurl'} eq $r->uri) {
@@ -78,6 +78,8 @@ sub handler {
$linkprot = $ltoken_info{'linkprot'};
$linkprotuser = $ltoken_info{'linkprotuser'};
$linkprotexit = $ltoken_info{'linkprotexit'};
+ $linkprotpbid = $ltoken_info{'linkprotpbid'};
+ $linkprotpburl = $ltoken_info{'linkprotpburl'};
} elsif ($link_info{'linkprot'}) {
$linkprot = $link_info{'linkprot'};
if ($link_info{'linkprotuser'}) {
@@ -86,12 +88,18 @@ sub handler {
if ($link_info{'linkprotexit'}) {
$linkprotexit = $link_info{'linkprotexit'};
}
+ if ($link_info{'linkprotpbid'}) {
+ $linkprotpbid = $link_info{'linkprotpbid'};
+ }
+ if ($link_info{'linkprotpburl'}) {
+ $linkprotpburl = $link_info{'linkprotpburl'};
+ }
}
}
}
if ($env{'request.course.id'} eq $cdom.'_'.$cnum) {
# Check for ttoken
- my $newlauncher = &launch_check($r->uri,$symb);
+ my $newlauncher = &launch_check($r->uri,$symb,$cdom,$cnum);
my ($map,$resid,$url) = &Apache::lonnet::decode_symb($symb);
if (&Apache::lonnet::is_on_map($url)) {
my $realuri;
@@ -220,13 +228,40 @@ sub handler {
}
}
my @allposs = keys(%active);
+ if ($env{'request.lti.login'}) {
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
+ if ($env{'request.lti.target'} eq '') {
+ if ($env{'form.ltitarget'} eq 'iframe') {
+ &Apache::lonnet::appenv({'request.lti.target' => 'iframe'});
+ delete($env{'form.ltitarget'});
+ }
+ }
+ if ($env{'form.selectrole'}) {
+ foreach my $role (@allposs) {
+ my $newrole = "$role./$cdom/$cnum";
+ if ($possroles{$allposs[0]} ne '') {
+ $newrole .= "/$possroles{$role}";
+ }
+ if ($env{"form.$newrole"}) {
+ my $destination .= '/adm/roles?selectrole=1&'.$newrole.'=1'.
+ '&destinationurl='.&HTML::Entities::encode($r->uri,'&<>"');
+ if ($env{'form.ltitarget'} eq 'iframe') {
+ $destination .= '<itarget=iframe';
+ }
+ &do_redirect($r,$destination);
+ return OK;
+ }
+ }
+ }
+ }
if (@allposs == 0) {
- &show_roles($r,\%crsenv,\%active,'','',\%future,\%expired,$linkprot,$linkprotuser,$linkprotexit,$ltoken);
+ &show_roles($r,\%crsenv,\%active,'','',\%future,\%expired,$linkprot,$linkprotuser,
+ $linkprotexit,$linkprotpbid,$linkprotpburl,$ltoken);
} elsif (@allposs == 1) {
my $newrole = "$allposs[0]./$cdom/$cnum";
$newrole = "$allposs[0]./$cdom/$cnum";
if ($possroles{$allposs[0]} ne '') {
- $newrole .= "/$possroles{$allposs[0]}";
+ $newrole .= "/$possroles{$allposs[0]}";
}
my $destination .= '/adm/roles?selectrole=1&'.$newrole.'=1'.
'&destinationurl='.&HTML::Entities::encode($r->uri,'&<>"');
@@ -272,8 +307,9 @@ sub handler {
}
sub launch_check {
- my ($linkuri,$symb) = @_;
- my ($linkprotector,$linkproturi,$linkprotexit,$linkkey,$newlauncher);
+ my ($linkuri,$symb,$cdom,$cnum) = @_;
+ my ($linkprotector,$linkproturi,$linkprotexit,$linkprotpbid,$linkprotpburl,
+ $linkkey,$newlauncher,$prevlaunch);
if ($env{'form.ttoken'}) {
my %link_info = &Apache::lonnet::tmpget($env{'form.ttoken'});
&Apache::lonnet::tmpdel($env{'form.ttoken'});
@@ -314,6 +350,12 @@ sub launch_check {
if ($link_info{'linkprotexit'}) {
$linkprotexit = $link_info{'linkprotexit'};
}
+ if ($link_info{'linkprotpbid'}) {
+ $linkprotpbid = $link_info{'linkprotpbid'};
+ }
+ if ($link_info{'linkprotpburl'}) {
+ $linkprotpburl = $link_info{'linkprotpburl'};
+ }
} elsif ($link_info{'linkkey'} ne '') {
$linkkey = $link_info{'linkkey'};
my $keyedlinkuri = $linkuri;
@@ -339,6 +381,9 @@ sub launch_check {
if ($link_info{'checklaunch'}) {
$newlauncher = 1;
}
+ if ($link_info{'prevlaunch'} ne '') {
+ $prevlaunch = $link_info{'prevlaunch'};
+ }
}
my $currdeeplinklogin = $env{'request.deeplink.login'};
my $deeplink;
@@ -387,26 +432,61 @@ sub launch_check {
if ($env{'request.linkprotexit'} ne '') {
&Apache::lonnet::delenv('request.linkprotexit');
}
+ if ($env{'request.linkprotpbid'} ne '') {
+ &Apache::lonnet::delenv('request.linkprotpbid');
+ }
+ if ($env{'request.linkprotpburl'} ne '') {
+ &Apache::lonnet::delenv('request.linkprotpburl');
+ }
}
} else {
unless ($currdeeplinklogin eq $linkuri) {
if (($linkprotector) || ($linkkey ne '')) {
- if ($linkprotector) {
- &Apache::lonnet::appenv({'request.linkprot' => $linkprotector.':'.$linkproturi});
- } elsif ($env{'request.linkprot'}) {
- &Apache::lonnet::delenv('request.linkprot');
- }
+ $newlauncher = 1;
+ }
+ }
+ if ($linkprotector) {
+ &Apache::lonnet::appenv({'request.linkprot' => $linkprotector.':'.$linkproturi});
+ if ($linkprotpburl && $linkprotpbid) {
+ my ($res,$error) = &store_passback_info($cdom,$cnum,$linkuri,$linkprotector,
+ $scope,$symb,$linkprotpbid,$linkprotpburl,
+ $currdeeplinklogin);
+ }
+ } elsif ($env{'request.linkprot'}) {
+ &Apache::lonnet::delenv('request.linkprot');
+ }
+ if ($linkkey ne '') {
+ &Apache::lonnet::appenv({'request.linkkey' => $linkkey});
+ } elsif ($env{'request.linkkey'} ne '') {
+ &Apache::lonnet::delenv('request.linkkey');
+ }
+ if (($linkprotector) || ($linkkey ne '')) {
+ if ($linkprotexit ne $env{'request.linkprotexit'}) {
if ($linkprotexit) {
&Apache::lonnet::appenv({'request.linkprotexit' => $linkprotexit});
} elsif ($env{'request.linkprotexit'}) {
&Apache::lonnet::delenv('request.linkprotexit');
}
- if ($linkkey ne '') {
- &Apache::lonnet::appenv({'request.linkkey' => $linkkey});
- } elsif ($env{'request.linkkey'} ne '') {
- &Apache::lonnet::delenv('request.linkkey');
+ }
+ if ($linkprotpbid ne $env{'request.linkprotpbid'}) {
+ if ($linkprotpbid) {
+ &Apache::lonnet::appenv({'request.linkprotpbid' => $linkprotpbid});
+ } elsif ($env{'request.linkprotpbid'}) {
+ &Apache::lonnet::delenv('request.linkprotpbid');
+ }
+ }
+ if ($linkprotpburl ne $env{'request.linkprotpburl'}) {
+ if ($linkprotpburl) {
+ &Apache::lonnet::appenv({'request.linkprotpburl' => $linkprotpburl});
+ } elsif ($env{'request.linkprotpburl'}) {
+ &Apache::lonnet::delenv('request.linkprotpburl');
+ }
+ }
+ } elsif ($prevlaunch) {
+ foreach my $requestkey ('linkprotpbid','linkprotpburl','linkprotexit') {
+ if ($env{"request.$requestkey"}) {
+ &Apache::lonnet::delenv("request.$requestkey");
}
- $newlauncher = 1;
}
}
&Apache::lonnet::appenv({'request.deeplink.login' => $linkuri});
@@ -427,6 +507,16 @@ sub launch_check {
} elsif ($env{'request.linkprotexit'}) {
&Apache::lonnet::delenv('request.linkprotexit');
}
+ if ($linkprotpbid) {
+ &Apache::lonnet::appenv({'request.linkprotpbid' => $linkprotpbid});
+ } elsif ($env{'request.linkprotpbid'}) {
+ &Apache::lonnet::delenv('request.linkprotpbid');
+ }
+ if ($linkprotpburl) {
+ &Apache::lonnet::appenv({'request.linkprotpburl' => $linkprotpburl});
+ } elsif ($env{'request.linkprotpburl'}) {
+ &Apache::lonnet::delenv('request.linkprotpburl');
+ }
if ($linkkey ne '') {
&Apache::lonnet::appenv({'request.linkkey' => $linkkey});
} else {
@@ -440,9 +530,74 @@ sub launch_check {
return $newlauncher;
}
+#
+# Store linkprotpburl and linkprotpbid in user's nohist_$cid_linkprot_pb.db
+# $linkuri\0$linkprotector\0$scope = [$linkprotpbid,$linkprotpburl]
+# Separately store $symb in course's nohist_linkprot_passback.db
+# which should trigger passback:
+# $symb => {$linkuri\0$linkprotector\0$scope => 1};
+#
+
+sub store_passback_info {
+ my ($cdom,$cnum,$linkuri,$linkprotector,$scope,$symb,
+ $linkprotpbid,$linkprotpburl,$currdeeplinklogin) = @_;
+ my $key = join("\0",($linkuri,$linkprotector,$scope));
+ my $namespace = 'nohist_'.$cdom.'_'.$cnum.'_linkprot_pb';
+ if ($linkuri eq $currdeeplinklogin) {
+ my %pbinfo = &Apache::lonnet::get($namespace,[$key]);
+ if (ref($pbinfo{$key}) eq 'ARRAY') {
+ if (($pbinfo{$key}[0] eq $linkprotpbid) &&
+ ($pbinfo{$key}[1] eq $linkprotpburl)) {
+ return ('ok');
+ }
+ }
+ }
+ my $now = time;
+ my $result = &Apache::lonnet::cput($namespace,{$key => [$linkprotpbid,$linkprotpburl]});
+ my $error;
+ if (($result eq 'ok') || ($result eq 'con_delayed')) {
+ $namespace = 'nohist_linkprot_passback';
+ my %triggers = &Apache::lonnet::get($namespace,[$symb],$cdom,$cnum);
+ my $newtrigger;
+ if ((exists($triggers{$symb})) && (ref($triggers{$symb}) eq 'HASH')) {
+ unless (exists($triggers{$symb}{$key})) {
+ $newtrigger = 1;
+ }
+ } else {
+ $newtrigger = 1;
+ }
+ if ($newtrigger) {
+ my ($lockhash,$tries,$gotlock);
+ $lockhash = {
+ lock => $env{'user.name'}.
+ ':'.$env{'user.domain'},
+ };
+ $tries = 0;
+ $gotlock = &Apache::lonnet::newput($namespace,$lockhash,$cdom,$cnum);
+ while (($gotlock ne 'ok') && ($tries<10)) {
+ $tries ++;
+ sleep (0.1);
+ $gotlock = &Apache::lonnet::newput($namespace,$lockhash,$cdom,$cnum);
+ }
+ if ($gotlock eq 'ok') {
+ %triggers = &Apache::lonnet::get($namespace,[$symb],$cdom,$cnum);
+ $triggers{$symb}{$key} = 1;
+ $result = &Apache::lonnet::cput($namespace,{$symb => $triggers{$symb}},$cdom,$cnum);
+ my $dellockoutcome = &Apache::lonnet::del($namespace,['lock'],$cdom,$cnum);
+ } else {
+ $error = 'nolock';
+ }
+ }
+ }
+ return ($result,$error);
+}
+
sub do_redirect {
my ($r,$destination,$linkprot) = @_;
my $windowname = 'loncapaclient';
+ if ($env{'request.lti.login'}) {
+ $windowname .= 'lti';
+ }
my $header = '';
my $args = {'bread_crumbs' => [{'href' => '','text' => 'Role initialization'},],};
if ($linkprot) {
@@ -466,7 +621,8 @@ sub do_redirect {
}
sub show_roles {
- my ($r,$crsenv,$possroles,$hassection,$hascustom,$futureroles,$expiredroles,$linkprot,$linkprotuser,$linkprotexit,$ltoken) = @_;
+ my ($r,$crsenv,$possroles,$hassection,$hascustom,$futureroles,$expiredroles,
+ $linkprot,$linkprotuser,$linkprotexit,$linkprotpbid,$linkprotpburl,$ltoken) = @_;
my ($crsdesc,$crstype,$cdom,$cnum,$header,$title,$preamble,$datatable,$js,$args);
if (ref($crsenv) eq 'HASH') {
$crsdesc = $crsenv->{'description'};
@@ -607,6 +763,8 @@ ENDJS
origurl => $r->uri,
linkprot => $linkprot,
linkprotexit => $linkprotexit,
+ linkprotpbid => $linkprotpbid,
+ linkprotpburl => $linkprotpburl,
);
my $token =
&Apache::lonnet::tmpput(\%data,$r->dir_config('lonHostID'),'retry');
@@ -643,13 +801,15 @@ ENDJS
sub generic_error {
my ($r) = @_;
my $continuelink;
- my $linktext;
- if ($env{'user.adv'}) {
- $linktext = &mt('Continue to your roles page');
- } else {
- $linktext = &mt('Continue to your courses page');
+ unless ($env{'request.lti.login'}) {
+ my $linktext;
+ if ($env{'user.adv'}) {
+ $linktext = &mt('Continue to your roles page');
+ } else {
+ $linktext = &mt('Continue to your courses page');
+ }
+ $continuelink=''.$linktext.'';
}
- $continuelink=''.$linktext.'';
my $msg = &mt('The page you requested does not exist.');
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;