--- loncom/interface/lontiny.pm 2024/02/09 20:08:16 1.21 +++ 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.21 2024/02/09 20:08:16 raeburn Exp $ +# $Id: lontiny.pm,v 1.23 2024/11/17 04:48:15 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -99,7 +99,7 @@ sub handler { } 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; @@ -307,7 +307,7 @@ sub handler { } sub launch_check { - my ($linkuri,$symb) = @_; + my ($linkuri,$symb,$cdom,$cnum) = @_; my ($linkprotector,$linkproturi,$linkprotexit,$linkprotpbid,$linkprotpburl, $linkkey,$newlauncher,$prevlaunch); if ($env{'form.ttoken'}) { @@ -440,35 +440,53 @@ sub launch_check { } } } else { - if (($currdeeplinklogin ne $linkuri) || - (($prevlaunch ne '') && ($currdeeplinklogin ne $prevlaunch))) { + 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 ($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'); } - if ($linkkey ne '') { - &Apache::lonnet::appenv({'request.linkkey' => $linkkey}); - } elsif ($env{'request.linkkey'} ne '') { - &Apache::lonnet::delenv('request.linkkey'); + } + } 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}); @@ -512,6 +530,68 @@ 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';