--- loncom/Lond.pm 2019/07/11 18:12:01 1.15 +++ loncom/Lond.pm 2022/02/14 02:48:49 1.19 @@ -1,6 +1,6 @@ # The LearningOnline Network # -# $Id: Lond.pm,v 1.15 2019/07/11 18:12:01 raeburn Exp $ +# $Id: Lond.pm,v 1.19 2022/02/14 02:48:49 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -41,6 +41,7 @@ use MIME::Base64; use Crypt::OpenSSL::X509; use Crypt::X509::CRL; use Crypt::PKCS10; +use Net::OAuth; sub dump_with_regexp { my ( $tail, $clientversion ) = @_; @@ -242,10 +243,10 @@ sub check_homecourses { } } unless (&untie_domain_hash($hashref)) { - &logthis("Failed to untie tied hash for nohist_courseids.db for $domain"); + &Apache::lonnet::logthis("Failed to untie tied hash for nohist_courseids.db for $domain"); } } else { - &logthis("Failed to tie hash for nohist_courseids.db for $domain"); + &Apache::lonnet::logthis("Failed to tie hash for nohist_courseids.db for $domain"); } } foreach my $hashid (keys(%recent)) { @@ -317,9 +318,9 @@ sub get_courseinfo_hash { }; if ($@) { if ($@ eq "timeout\n") { - &logthis("WARNING courseiddump for $cnum:$cdom from $home timedout"); + &Apache::lonnet::logthis("WARNING courseiddump for $cnum:$cdom from $home timedout"); } else { - &logthis("WARNING unexpected error during eval of call for courseiddump from $home"); + &Apache::lonnet::logthis("WARNING unexpected error during eval of call for courseiddump from $home"); } } else { if (ref($info{$cdom.'_'.$cnum}) eq 'HASH') { @@ -805,10 +806,10 @@ sub is_course { } &Apache::lonnet::do_cache_new('iscourse',$hashid,$iscourse,3600); unless (&untie_domain_hash($hashref)) { - &logthis("Failed to untie tied hash for nohist_courseids.db for $cdom"); + &Apache::lonnet::logthis("Failed to untie tied hash for nohist_courseids.db for $cdom"); } } else { - &logthis("Failed to tie hash for nohist_courseids.db for $cdom"); + &Apache::lonnet::logthis("Failed to tie hash for nohist_courseids.db for $cdom"); } } return $iscourse; @@ -1024,6 +1025,228 @@ sub server_certs { return $result; } +sub get_dom { + my ($userinput) = @_; + my ($cmd,$udom,$namespace,$what) =split(/:/,$userinput,4); + my $hashref = &tie_domain_hash($udom,$namespace,&GDBM_READER()) or + return "error: ".($!+0)." tie(GDBM) Failed while attempting $cmd"; + my $qresult=''; + if (ref($hashref)) { + chomp($what); + my @queries=split(/\&/,$what); + for (my $i=0;$i<=$#queries;$i++) { + $qresult.="$hashref->{$queries[$i]}&"; + } + $qresult=~s/\&$//; + } + &untie_user_hash($hashref) or + return "error: ".($!+0)." untie(GDBM) Failed while attempting $cmd"; + return $qresult; +} + +sub store_dom { + my ($userinput) = @_; + my ($cmd,$dom,$namespace,$rid,$what) =split(/:/,$userinput); + my $hashref = &tie_domain_hash($dom,$namespace,&GDBM_WRCREAT(),"S","$rid:$what") or + return "error: ".($!+0)." tie(GDBM) Failed while attempting $cmd"; + $hashref->{"version:$rid"}++; + my $version=$hashref->{"version:$rid"}; + my $allkeys=''; + my @pairs=split(/\&/,$what); + foreach my $pair (@pairs) { + my ($key,$value)=split(/=/,$pair); + $allkeys.=$key.':'; + $hashref->{"$version:$rid:$key"}=$value; + } + my $now = time; + $hashref->{"$version:$rid:timestamp"}=$now; + $allkeys.='timestamp'; + $hashref->{"$version:keys:$rid"}=$allkeys; + &untie_user_hash($hashref) or + return "error: ".($!+0)." untie(GDBM) Failed while attempting $cmd"; + return 'ok'; +} + +sub restore_dom { + my ($userinput) = @_; + my ($cmd,$dom,$namespace,$rid) = split(/:/,$userinput); + my $hashref = &tie_domain_hash($dom,$namespace,&GDBM_READER()) or + return "error: ".($!+0)." tie(GDBM) Failed while attempting $cmd"; + my $qresult=''; + if (ref($hashref)) { + chomp($rid); + my $version=$hashref->{"version:$rid"}; + $qresult.="version=$version&"; + my $scope; + for ($scope=1;$scope<=$version;$scope++) { + my $vkeys=$hashref->{"$scope:keys:$rid"}; + my @keys=split(/:/,$vkeys); + my $key; + $qresult.="$scope:keys=$vkeys&"; + foreach $key (@keys) { + $qresult.="$scope:$key=".$hashref->{"$scope:$rid:$key"}."&"; + } + } + $qresult=~s/\&$//; + } + &untie_user_hash($hashref) or + return "error: ".($!+0)." untie(GDBM) Failed while attempting $cmd"; + return $qresult; +} + +sub crslti_itemid { + my ($cdom,$cnum,$url,$method,$params,$loncaparev) = @_; + unless (ref($params) eq 'HASH') { + return; + } + if (($cdom eq '') || ($cnum eq '')) { + return; + } + my ($itemid,$consumer_key,$secret); + + if (exists($params->{'oauth_callback'})) { + $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A; + } else { + $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0; + } + + my $consumer_key = $params->{'oauth_consumer_key'}; + return if ($consumer_key eq ''); + + my (%crslti,%crslti_by_key); + my $hashid=$cdom.'_'.$cnum; + my ($result,$cached)=&Apache::lonnet::is_cached_new('courseltienc',$hashid); + if (defined($cached)) { + if (ref($result) eq 'HASH') { + %crslti = %{$result}; + } + } else { + my $reply = &dump_with_regexp(join(":",($cdom,$cnum,'nohist_ltienc','','')),$loncaparev); + %crslti = %{&Apache::lonnet::unserialize($reply)}; + my $cachetime = 24*60*60; + &Apache::lonnet::do_cache_new('courseltienc',$hashid,\%crslti,$cachetime); + } + + return if (!keys(%crslti)); + + foreach my $id (keys(%crslti)) { + if (ref($crslti{$id}) eq 'HASH') { + my $key = $crslti{$id}{'key'}; + if (($key ne '') && ($crslti{$id}{'secret'} ne '')) { + push(@{$crslti_by_key{$key}},$id); + } + } + } + + return if (!keys(%crslti_by_key)); + + if (ref($crslti_by_key{$consumer_key}) eq 'ARRAY') { + foreach my $id (@{$crslti_by_key{$consumer_key}}) { + my $secret = $crslti{$id}{'secret'}; + my $request = Net::OAuth->request('request token')->from_hash($params, + request_url => $url, + request_method => $method, + consumer_secret => $secret,); + if ($request->verify()) { + $itemid = $id; + last; + } + } + } + return $itemid; +} + +sub domlti_itemid { + my ($dom,$context,$url,$method,$params,$loncaparev) = @_; + unless (ref($params) eq 'HASH') { + return; + } + if ($dom eq '') { + return; + } + my ($itemid,$consumer_key,$secret); + + if (exists($params->{'oauth_callback'})) { + $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A; + } else { + $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0; + } + + my $consumer_key = $params->{'oauth_consumer_key'}; + return if ($consumer_key eq ''); + + my %ltienc; + my ($encresult,$enccached)=&Apache::lonnet::is_cached_new('ltienc',$dom); + if (defined($enccached)) { + if (ref($encresult) eq 'HASH') { + %ltienc = %{$encresult}; + } + } else { + my $reply = &get_dom("getdom:$dom:encconfig:lti"); + my $ltiencref = &Apache::lonnet::thaw_unescape($reply); + if (ref($ltiencref) eq 'HASH') { + %ltienc = %{$ltiencref}; + } + my $cachetime = 24*60*60; + &Apache::lonnet::do_cache_new('ltienc',$dom,\%ltienc,$cachetime); + } + + return if (!keys(%ltienc)); + + my %lti; + if ($context eq 'deeplink') { + my ($result,$cached)=&Apache::lonnet::is_cached_new('lti',$dom); + if (defined($cached)) { + if (ref($result) eq 'HASH') { + %lti = %{$result}; + } + } else { + my $reply = &get_dom("getdom:$dom:configuration:lti"); + my $ltiref = &Apache::lonnet::thaw_unescape($reply); + if (ref($ltiref) eq 'HASH') { + %lti = %{$ltiref}; + } + my $cachetime = 24*60*60; + &Apache::lonnet::do_cache_new('lti',$dom,\%lti,$cachetime); + } + } + return if (!keys(%lti)); + + my %lti_by_key; + foreach my $id (keys(%ltienc)) { + if (ref($ltienc{$id}) eq 'HASH') { + my $key = $ltienc{$id}{'key'}; + if (($key ne '') && ($ltienc{$id}{'secret'} ne '')) { + if ($context eq 'deeplink') { + if (ref($lti{$id}) eq 'HASH') { + if (!$lti{$id}{'requser'}) { + push(@{$lti_by_key{$key}},$id); + } + } + } else { + push(@{$lti_by_key{$key}},$id); + } + } + } + } + return if (!keys(%lti_by_key)); + + if (ref($lti_by_key{$consumer_key}) eq 'ARRAY') { + foreach my $id (@{$lti_by_key{$consumer_key}}) { + my $secret = $ltienc{$id}{'secret'}; + my $request = Net::OAuth->request('request token')->from_hash($params, + request_url => $url, + request_method => $method, + consumer_secret => $secret,); + if ($request->verify()) { + $itemid = $id; + last; + } + } + } + return $itemid; +} + 1; __END__ @@ -1146,7 +1369,18 @@ courseID -- for the course for which the The contents of the inner hash, for that single item in the outer hash are returned (and cached in memcache for 10 minutes). +=item get_dom ( $userinput ) +get_dom() will retrieve domain configuration information from a GDBM file +in /home/httpd/lonUsers/$dom on the primary library server in a domain. +The single argument passed is the string: $cmd:$udom:$namespace:$what +where $cmd is the command historically passed to lond - i.e., getdom +or egetdom, $udom is the domain, $namespace is the name of the GDBM file +(encconfig or configuration), and $what is a string containing names of +items to retrieve from the db file (each item name is escaped and separated +from the next item name with an ampersand). The return value is either: +error: followed by an error message, or a string containing the value (escaped) +for each item, again separated from the next item with an ampersand. =back