--- loncom/interface/lonexttool.pm 2016/06/06 17:40:48 1.4 +++ loncom/interface/lonexttool.pm 2021/12/31 15:12:52 1.22.2.1 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Launch External Tool Provider (LTI) # -# $Id: lonexttool.pm,v 1.4 2016/06/06 17:40:48 raeburn Exp $ +# $Id: lonexttool.pm,v 1.22.2.1 2021/12/31 15:12:52 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -43,13 +43,15 @@ package Apache::lonexttool; use strict; use Apache::Constants qw(:common :http); -use Net::OAuth; use Encode; use Digest::SHA; use HTML::Entities; use Apache::lonlocal; use Apache::lonnet; use Apache::loncommon; +use Apache::londatecheck; +use Apache::lonipcheck; +use LONCAPA::ltiutils; sub handler { my $r=shift; @@ -62,12 +64,15 @@ sub handler { # ------------------------------------------------------------ Print the screen if ($target eq 'tex') { $r->print(&Apache::lonprintout::print_latex_header($env{'form.latex_type'})); + } else { + $target = 'web'; } # Is this even in a course? unless ($env{'request.course.id'}) { if ($target ne 'tex') { - &Apache::loncommon::simple_error_page($r,'','Not in a course'); + &Apache::loncommon::simple_error_page($r,'','Not in a course', + {'only_body' => 1}); } else { $r->print('\textbf{Not in a course}\end{document}'); } @@ -89,34 +94,24 @@ sub handler { my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; my $chome = $env{'course.'.$env{'request.course.id'}.'.home'}; - my $is_tool; + my ($idx,$is_tool,%toolhash,%toolsettings); if ($r->uri eq "/adm/$cdom/$cnum/$marker/$exttool") { - my %toolsettings=&Apache::lonnet::dump('exttool_'.$marker,$cdom,$cnum); + %toolsettings=&Apache::lonnet::dump('exttool_'.$marker,$cdom,$cnum); if ($toolsettings{'id'}) { - my %ltitools = &Apache::lonnet::get_domain_ltitools($cdom); - if (ref($ltitools{$toolsettings{'id'}}) eq 'HASH') { - my %toolhash = %{$ltitools{$toolsettings{'id'}}}; + $idx = $toolsettings{'id'}; + my %ltitools = &Apache::lonnet::get_domain_lti($cdom,'consumer'); + if (ref($ltitools{$idx}) eq 'HASH') { + %toolhash = %{$ltitools{$idx}}; $toolhash{'display'} = { target => $toolsettings{'target'}, width => $toolsettings{'width'}, height => $toolsettings{'height'}, }; - $toolhash{'crslabel'} = $toolsettings{'crslabel'}; - $toolhash{'crstitle'} = $toolsettings{'crstitle'}; - $is_tool = 1; - if ($target eq 'tex') { - $r->print(&mt('External Tool')); - } else { - my $submittext = &mt('Launch [_1]',$toolhash{'title'}); - if (($toolhash{'key'} ne '') && ($toolhash{'secret'} ne '') && ($toolhash{'url'} ne '')) { - my %lti = <i_params($r,$cnum,$cdom,$submittext,\%toolhash); - $r->print(&launch_html($toolhash{'url'},$toolhash{'key'}, - $toolhash{'secret'},$submittext,\%lti)); - } else { - $r->print('
'.&mt('External Tool Unavailable').'
'); - } + foreach my $item (qw(crslabel crstitle crsappend)) { + $toolhash{$item} = $toolsettings{$item}; } + $is_tool = 1; } } } @@ -126,20 +121,67 @@ sub handler { } else { $r->print('\textbf{'.&mt(Invalid Call).'}\end{document}'); } + return OK; + } + + my ($symb,$status,$open,$close,$msg,$donebuttonresult,$donemsg); + if (($target eq 'tex') || ($toolhash{'gradable'})) { + ($symb) = &Apache::lonnet::whichuser(); + } + if ($target eq 'tex') { + my $title = &Apache::lonnet::gettitle($symb); + $r->print(&mt('External Tool: [_1]','\textit{'.$title.'}').'\\\\'); + } + my ($status,$open,$close,$msg)=&Apache::londatecheck::content_date_check(); + if ($status ne 'OPEN') { + if ($target eq 'tex') { + $r->print(&mt('Not open to be viewed').'\end{document}'); + } else { + $r->print($msg); + } + return OK; + } else { + ($status,$msg)=&Apache::lonipcheck::ip_access_check(); + if ($status ne 'OPEN') { + if ($target eq 'tex') { + $r->print(&mt('Not open to be viewed').'\end{document}'); + } else { + $r->print($msg); + } + return OK; + } + } + my $launchok = 1; + if ($target eq 'tex') { + $r->print('\end{document}'); + } else { + my $now = time; + my $submittext = &mt('Launch [_1]',$toolhash{'title'}); + if (($toolhash{'key'} ne '') && ($toolhash{'secret'} ne '') && + ($toolhash{'url'} ne '') && ($launchok)) { + my %lti = <i_params($r,$cnum,$cdom,$idx,$submittext,\%toolhash); + my $url = $toolhash{'url'}; + if ($toolhash{'crsappend'} ne '') { + $url .= $toolhash{'crsappend'}; + } + $r->print(&launch_html($url,$toolhash{'key'},$toolhash{'secret'}, + $toolhash{'sigmethod'},$submittext,\%lti)); + } else { + $r->print('
'.&mt('External Tool Unavailable').'
'); + } } return OK; } sub lti_params { - my ($r,$cnum,$cdom,$submittext,$toolsref) = @_; + my ($r,$cnum,$cdom,$idx,$submittext,$toolsref) = @_; my ($version,$context_type,$msgtype,$toolname,$passback,$roster,$locale, - $crslabel,$crstitle,%fields,%rolesmap,%display,%custom,@userlangs); + $crslabel,$crstitle,%fields,%rolesmap,%display,%custom,@userlangs,$incdom); if (ref($toolsref) eq 'HASH') { $version = $toolsref->{'version'}; $toolname = $toolsref->{'title'}; - $passback = $toolsref->{'passback'}; - $roster = $toolsref->{'roster'}; $msgtype = $toolsref->{'messagetype'}; + $incdom = $toolsref->{'incdom'}; if (ref($toolsref->{'fields'}) eq 'HASH') { %fields = %{$toolsref->{'fields'}}; } @@ -165,10 +207,10 @@ sub lti_params { $msgtype = 'basic-lti-launch-request'; } if ($crslabel eq '') { - $crslabel = $env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}, + $crslabel = $env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}; } if ($crstitle eq '') { - $crstitle = $env{'course.'.$env{'request.course.id'}.'.description'},; + $crstitle = $env{'course.'.$env{'request.course.id'}.'.description'}; } my $lonhost = $r->dir_config('lonHostID'); my $loncaparev = $r->dir_config('lonVersion'); @@ -180,8 +222,10 @@ sub lti_params { unless (grep(/^\Q$ltirole\E$/,@possroles)) { $ltirole = 'Learner'; } + my @possdigest; my $digest_user = &Encode::decode_utf8($uname.':'.$udom); $digest_user = &Digest::SHA::sha1_hex($digest_user); + push(@possdigest,$digest_user); if ($env{'course.'.$env{'request.course.id'}.'.languages'} ne '') { @userlangs=(@userlangs,split(/\s*(\,|\;|\:)\s*/, $env{'course.'.$env{'request.course.id'}.'.languages'})); @@ -204,6 +248,7 @@ sub lti_params { if ($symb) { $digest_symb = &Encode::decode_utf8($symb); $digest_symb = &Digest::SHA::sha1_hex($digest_symb); + push(@possdigest,$digest_symb); my $navmap = Apache::lonnavmaps::navmap->new(); if (ref($navmap)) { my $res = $navmap->getBySymb($symb); @@ -215,7 +260,7 @@ sub lti_params { my $domdesc = &Apache::lonnet::domain($cdom); my $primary_id = &Apache::lonnet::domain($cdom,'primary'); my $int_dom = &Apache::lonnet::internet_dom($primary_id); - my $portal_url = &Apache::lonnet::course_portal_url($cnum,$cdom); + my $portal_url = &Apache::lonnet::course_portal_url($cnum,$cdom,$r); my %ltiparams = ( lti_version => $version, @@ -225,7 +270,7 @@ sub lti_params { tool_consumer_instance_guid => $lonhost, tool_consumer_instance_description => $domdesc, tool_consumer_info_product_family_code => 'loncapa', - tool_consumer_instance_name => $int_dom, + tool_consumer_instance_name => $int_dom, tool_consumer_instance_url => $portal_url, tool_consumer_info_version => $loncaparev, user_id => $digest_user, @@ -242,19 +287,6 @@ sub lti_params { my $crsprotocol = $Apache::lonnet::protocol{$crshome}; unless ($crsprotocol eq 'https') { $crsprotocol = 'http'; - } - if ($passback) { - if ($ltirole eq 'Learner') { - $ltiparams{'lis_outcome_service_url'} = $crsprotocol.'//'.$crshostname.'/adm/ltipassback'; - $ltiparams{'ext_ims_lis_basic_outcome_url'} = $ltiparams{'lis_outcome_service_url'}; - $ltiparams{'lis_result_sourcedid'} = ''; #FIXME - } - } - if ($roster) { - if (&Apache::lonnet::allowed('opa',$env{'request.course.id'})) { - $ltiparams{'ext_ims_lis_memberships_url'} = $crsprotocol.'//'.$crshostname.'/adm/ltiroster'; - $ltiparams{'ext_ims_lis_memberships_id'} = ''; #FIXME - } } } if ($display{'target'}) { @@ -287,11 +319,22 @@ sub lti_params { $ltiparams{'lis_person_contact_email_primary'} = $contact_email; } if ($fields{'user'}) { - $ltiparams{'lis_person_sourcedid'} = $uname.':'.$udom; + if ($incdom) { + $ltiparams{'lis_person_sourcedid'} = $uname.':'.$udom; + } else { + $ltiparams{'lis_person_sourcedid'} = $uname; + } } if (keys(%custom)) { foreach my $key (keys(%custom)) { - $ltiparams{'custom_'.$key} = $custom{$key}; + my $value = $custom{$key}; + $value =~ s/^\s+|\s+\$//g; + if ($value =~ /^\QLONCAPA::env{\E([^\}]+)\}$/) { + if (exists($env{$1})) { + $value = $env{$1}; + } + } + $ltiparams{'custom_'.$key} = $value; } } foreach my $key (keys(%ltiparams)) { @@ -302,14 +345,15 @@ sub lti_params { } sub launch_html { - my ($url,$key,$secret,$submittext,$paramsref) = @_; - my $hashref = &sign_params($url,$key,$secret,$paramsref); + my ($url,$key,$secret,$sigmethod,$submittext,$paramsref) = @_; + my $hashref = &LONCAPA::ltiutils::sign_params($url,$key,$secret,$paramsref,$sigmethod); + my $action = &HTML::Entities::encode($url,'<>&"'); my $form = <<"END";
-
+ END if (ref($hashref) eq 'HASH') { foreach my $item (keys(%{$hashref})) { @@ -336,23 +380,4 @@ ENDJS return $form; } -sub sign_params { - my ($url,$key,$secret,$paramsref) = @_; - my $nonce = Digest::SHA::sha1_hex(sprintf("%06x%06x",rand(0xfffff0),rand(0xfffff0))); - my $request = Net::OAuth->request("request token")->new( - consumer_key => $key, - consumer_secret => $secret, - request_url => $url, - request_method => 'POST', - signature_method => 'HMAC-SHA1', - timestamp => time, - nonce => $nonce, - callback => 'about:blank', - extra_params => $paramsref, - version => '1.0', - ); - $request->sign; - return $request->to_hash(); -} - 1; 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.