--- loncom/lond 2011/11/17 18:22:36 1.485 +++ loncom/lond 2012/07/17 14:49:39 1.494 @@ -2,7 +2,7 @@ # The LearningOnline Network # lond "LON Daemon" Server (port "LOND" 5663) # -# $Id: lond,v 1.485 2011/11/17 18:22:36 raeburn Exp $ +# $Id: lond,v 1.494 2012/07/17 14:49:39 droeschl Exp $ # # Copyright Michigan State University Board of Trustees # @@ -34,6 +34,7 @@ use strict; use lib '/home/httpd/lib/perl/'; use LONCAPA; use LONCAPA::Configuration; +use LONCAPA::Lond; use IO::Socket; use IO::File; @@ -60,7 +61,7 @@ my $DEBUG = 0; # Non zero to ena my $status=''; my $lastlog=''; -my $VERSION='$Revision: 1.485 $'; #' stupid emacs +my $VERSION='$Revision: 1.494 $'; #' stupid emacs my $remoteVERSION; my $currenthostid="default"; my $currentdomainid; @@ -1906,12 +1907,8 @@ sub authenticate_handler { if (ref($hostedsession) eq 'HASH') { $hosted = $hostedsession->{'hosted'}; } - my $loncaparev = $clientversion; - if ($loncaparev eq '') { - $loncaparev = $Apache::lonnet::loncaparevs{$clientname}; - } $canhost = &Apache::lonnet::can_host_session($udom,$clientname, - $loncaparev, + $clientversion, $remote,$hosted); } } @@ -2350,7 +2347,8 @@ sub fetch_user_file_handler { my $transname=$udir.'/'.$ufile.'.in.transit'; my $clientprotocol=$Apache::lonnet::protocol{$clientname}; $clientprotocol = 'http' if ($clientprotocol ne 'https'); - my $remoteurl=$clientprotocol.'://'.$clientip.'/userfiles/'.$fname; + my $clienthost = &Apache::lonnet::hostname($clientname); + my $remoteurl=$clientprotocol.'://'.$clienthost.'/userfiles/'.$fname; my $response; Debug("Remote URL : $remoteurl Transfername $transname Destname: $destname"); alarm(120); @@ -3178,6 +3176,17 @@ sub get_profile_keys { sub dump_profile_database { my ($cmd, $tail, $client) = @_; + my $res = LONCAPA::Lond::dump_profile_database($tail); + + if ($res =~ /^error:/) { + Failure($client, \$res, "$cmd:$tail"); + } else { + Reply($client, \$res, "$cmd:$tail"); + } + + return 1; + + #TODO remove my $userinput = "$cmd:$tail"; my ($udom,$uname,$namespace) = split(/:/,$tail); @@ -3244,6 +3253,9 @@ sub dump_profile_database { # that is matched against # database keywords to do # selective dumps. +# range - optional range of entries +# e.g., 10-20 would return the +# 10th to 19th items, etc. # $client - Channel open on the client. # Returns: # 1 - Continue processing. @@ -3253,93 +3265,12 @@ sub dump_profile_database { sub dump_with_regexp { my ($cmd, $tail, $client) = @_; - - my $userinput = "$cmd:$tail"; - - my ($udom,$uname,$namespace,$regexp,$range,$extra)=split(/:/,$tail); - if (defined($regexp)) { - $regexp=&unescape($regexp); - } else { - $regexp='.'; - } - my ($start,$end); - if (defined($range)) { - if ($range =~/^(\d+)\-(\d+)$/) { - ($start,$end) = ($1,$2); - } elsif ($range =~/^(\d+)$/) { - ($start,$end) = (0,$1); - } else { - undef($range); - } - } - my $hashref = &tie_user_hash($udom, $uname, $namespace, - &GDBM_READER()); - my $skipcheck; - if ($hashref) { - my $qresult=''; - my $count=0; - if ($extra ne '') { - $extra = &Apache::lonnet::thaw_unescape($extra); - $skipcheck = $extra->{'skipcheck'}; - } - my @ids = &Apache::lonnet::current_machine_ids(); - my (%homecourses,$major,$minor,$now); - if (($namespace eq 'roles') && (!$skipcheck)) { - my $loncaparev = $clientversion; - if ($loncaparev eq '') { - $loncaparev = $Apache::lonnet::loncaparevs{$clientname}; - } - if ($loncaparev =~ /^\'?(\d+)\.(\d+)\.[\w.\-]+\'?/) { - $major = $1; - $minor = $2; - } - $now = time; - } - while (my ($key,$value) = each(%$hashref)) { - if ($namespace eq 'roles') { - if ($key =~ m{^/($LONCAPA::match_domain)/($LONCAPA::match_courseid)(/?[^_]*)_(cc|co|in|ta|ep|ad|st|cr)$}) { - my $cdom = $1; - my $cnum = $2; - unless ($skipcheck) { - my ($role,$end,$start) = split(/\_/,$value); - if (!$end || $end > $now) { - next unless (&releasereqd_check($cnum,$cdom,$key,$value,$major, - $minor,\%homecourses,\@ids)); - } - } - } - } - if ($regexp eq '.') { - $count++; - if (defined($range) && $count >= $end) { last; } - if (defined($range) && $count < $start) { next; } - $qresult.=$key.'='.$value.'&'; - } else { - my $unescapeKey = &unescape($key); - if (eval('$unescapeKey=~/$regexp/')) { - $count++; - if (defined($range) && $count >= $end) { last; } - if (defined($range) && $count < $start) { next; } - $qresult.="$key=$value&"; - } - } - } - if (&untie_user_hash($hashref)) { - if (($namespace eq 'roles') && (!$skipcheck)) { - if (keys(%homecourses) > 0) { - $qresult .= &check_homecourses(\%homecourses,$udom,$regexp,$count, - $range,$start,$end,$major,$minor); - } - } - chop($qresult); - &Reply($client, \$qresult, $userinput); - } else { - &Failure( $client, "error: ".($!+0)." untie(GDBM) Failed ". - "while attempting dump\n", $userinput); - } + my $res = LONCAPA::Lond::dump_with_regexp($tail, $clientversion); + + if ($res =~ /^error:/) { + Failure($client, \$res, "$cmd:$tail"); } else { - &Failure($client, "error: ".($!+0)." tie(GDBM) Failed ". - "while attempting dump\n", $userinput); + Reply($client, \$res, "$cmd:$tail"); } return 1; @@ -3918,6 +3849,17 @@ sub put_course_id_hash_handler { # a reply is written to $client. sub dump_course_id_handler { my ($cmd, $tail, $client) = @_; + + my $res = LONCAPA::Lond::dump_course_id_handler($tail); + if ($res =~ /^error:/) { + Failure($client, \$res, "$cmd:$tail"); + } else { + Reply($client, \$res, "$cmd:$tail"); + } + + return 1; + + #TODO remove my $userinput = "$cmd:$tail"; my ($udom,$since,$description,$instcodefilter,$ownerfilter,$coursefilter, @@ -6281,6 +6223,9 @@ sub Debug { # reply - Text to send to client. # request - Original request from client. # +#NOTE $reply must be terminated by exactly *one* \n. If $reply is a reference +#this is done automatically ($$reply must not contain any \n in this case). +#If $reply is a string the caller has to ensure this. sub Reply { my ($fd, $reply, $request) = @_; if (ref($reply)) { @@ -6572,7 +6517,14 @@ sub make_new_child { # # If the remote is attempting a local init... give that a try: # + logthis("remotereq: $remotereq"); (my $i, my $inittype, $clientversion) = split(/:/, $remotereq); + # For LON-CAPA 2.9, the client session will have sent its LON-CAPA + # version when initiating the connection. For LON-CAPA 2.8 and older, + # the version is retrieved from the global %loncaparevs in lonnet.pm. + # $clientversion contains path to keyfile if $inittype eq 'local' + # it's overridden below in this case + $clientversion ||= $Apache::lonnet::loncaparevs{$clientname}; # If the connection type is ssl, but I didn't get my # certificate files yet, then I'll drop back to @@ -6716,14 +6668,22 @@ sub is_author { # Author role should show up as a key /domain/_au - my $key = "/$domain/_au"; my $value; - if (defined($hashref)) { - $value = $hashref->{$key}; - } + if ($hashref) { - if(defined($value)) { - &Debug("$user @ $domain is an author"); + my $key = "/$domain/_au"; + if (defined($hashref)) { + $value = $hashref->{$key}; + if(!untie_user_hash($hashref)) { + return 'error: ' . ($!+0)." untie (GDBM) Failed"; + } + } + + if(defined($value)) { + &Debug("$user @ $domain is an author"); + } + } else { + return 'error: '.($!+0)." tie (GDBM) Failed"; } return defined($value); @@ -7428,167 +7388,8 @@ sub get_usersession_config { return; } -sub releasereqd_check { - my ($cnum,$cdom,$key,$value,$major,$minor,$homecourses,$ids) = @_; - my $home = &Apache::lonnet::homeserver($cnum,$cdom); - return if ($home eq 'no_host'); - my ($reqdmajor,$reqdminor,$displayrole); - if ($cnum =~ /$LONCAPA::match_community/) { - if ($major eq '' && $minor eq '') { - return unless ((ref($ids) eq 'ARRAY') && - (grep(/^\Q$home\E$/,@{$ids}))); - } else { - $reqdmajor = 2; - $reqdminor = 9; - return unless (&useable_role($reqdmajor,$reqdminor,$major,$minor)); - } - } - my $hashid = $cdom.':'.$cnum; - my ($courseinfo,$cached) = - &Apache::lonnet::is_cached_new('courseinfo',$hashid); - if (defined($cached)) { - if (ref($courseinfo) eq 'HASH') { - if (exists($courseinfo->{'releaserequired'})) { - my ($reqdmajor,$reqdminor) = split(/\./,$courseinfo->{'releaserequired'}); - return unless (&useable_role($reqdmajor,$reqdminor,$major,$minor)); - } - } - } else { - if (ref($ids) eq 'ARRAY') { - if (grep(/^\Q$home\E$/,@{$ids})) { - if (ref($homecourses) eq 'HASH') { - if (ref($homecourses->{$hashid}) eq 'ARRAY') { - push(@{$homecourses->{$hashid}},{$key=>$value}); - } else { - $homecourses->{$hashid} = [{$key=>$value}]; - } - } - return; - } - } - my $courseinfo = &get_courseinfo_hash($cnum,$cdom,$home); - if (ref($courseinfo) eq 'HASH') { - if (exists($courseinfo->{'releaserequired'})) { - my ($reqdmajor,$reqdminor) = split(/\./,$courseinfo->{'releaserequired'}); - return unless (&useable_role($reqdmajor,$reqdminor,$major,$minor)); - } - } else { - return; - } - } - return 1; -} - -sub get_courseinfo_hash { - my ($cnum,$cdom,$home) = @_; - my %info; - eval { - local($SIG{ALRM}) = sub { die "timeout\n"; }; - local($SIG{__DIE__})='DEFAULT'; - alarm(3); - %info = &Apache::lonnet::courseiddump($cdom,'.',1,'.','.',$cnum,1,[$home],'.'); - alarm(0); - }; - if ($@) { - if ($@ eq "timeout\n") { - &logthis("<font color='blue'>WARNING courseiddump for $cnum:$cdom from $home timedout</font>"); - } else { - &logthis("<font color='yellow'>WARNING unexpected error during eval of call for courseiddump from $home</font>"); - } - } else { - if (ref($info{$cdom.'_'.$cnum}) eq 'HASH') { - my $hashid = $cdom.':'.$cnum; - return &Apache::lonnet::do_cache_new('courseinfo',$hashid,$info{$cdom.'_'.$cnum},600); - } - } - return; -} -sub check_homecourses { - my ($homecourses,$udom,$regexp,$count,$range,$start,$end,$major,$minor) = @_; - my ($result,%addtocache); - my $yesterday = time - 24*3600; - if (ref($homecourses) eq 'HASH') { - my (%okcourses,%courseinfo,%recent); - my $hashref = &tie_domain_hash($udom, "nohist_courseids", &GDBM_WRCREAT()); - if ($hashref) { - while (my ($key,$value) = each(%$hashref)) { - my $unesc_key = &unescape($key); - if ($unesc_key =~ /^lasttime:(\w+)$/) { - my $cid = $1; - $cid =~ s/_/:/; - if ($value > $yesterday ) { - $recent{$cid} = 1; - } - next; - } - my $items = &Apache::lonnet::thaw_unescape($value); - if (ref($items) eq 'HASH') { - my $hashid = $unesc_key; - $hashid =~ s/_/:/; - $courseinfo{$hashid} = $items; - if (ref($homecourses->{$hashid}) eq 'ARRAY') { - my ($reqdmajor,$reqdminor) = split(/\./,$items->{'releaserequired'}); - if (&useable_role($reqdmajor,$reqdminor,$major,$minor)) { - $okcourses{$hashid} = 1; - } - } - } - } - unless (&untie_domain_hash($hashref)) { - &logthis('Failed to untie tied hash for nohist_courseids.db'); - } - } else { - &logthis('Failed to tie hash for nohist_courseids.db'); - return; - } - foreach my $hashid (keys(%recent)) { - my ($result,$cached)=&Apache::lonnet::is_cached_new('courseinfo',$hashid); - unless ($cached) { - &Apache::lonnet::do_cache_new('courseinfo',$hashid,$courseinfo{$hashid},600); - } - } - foreach my $hashid (keys(%{$homecourses})) { - next if ($recent{$hashid}); - &Apache::lonnet::do_cache_new('courseinfo',$hashid,$courseinfo{$hashid},600); - } - foreach my $hashid (keys(%okcourses)) { - if (ref($homecourses->{$hashid}) eq 'ARRAY') { - foreach my $role (@{$homecourses->{$hashid}}) { - if (ref($role) eq 'HASH') { - while (my ($key,$value) = each(%{$role})) { - if ($regexp eq '.') { - $count++; - if (defined($range) && $count >= $end) { last; } - if (defined($range) && $count < $start) { next; } - $result.=$key.'='.$value.'&'; - } else { - my $unescapeKey = &unescape($key); - if (eval('$unescapeKey=~/$regexp/')) { - $count++; - if (defined($range) && $count >= $end) { last; } - if (defined($range) && $count < $start) { next; } - $result.="$key=$value&"; - } - } - } - } - } - } - } - } - return $result; -} -sub useable_role { - my ($reqdmajor,$reqdminor,$major,$minor) = @_; - if ($reqdmajor ne '' && $reqdminor ne '') { - return if (($major eq '' && $minor eq '') || - ($major < $reqdmajor) || - (($major == $reqdmajor) && ($minor < $reqdminor))); - } - return 1; -} sub distro_and_arch { return $dist.':'.$arch; @@ -7918,6 +7719,8 @@ Authen::Krb5 =head1 COREQUISITES +none + =head1 OSNAMES linux @@ -8005,9 +7808,9 @@ or the CA's certificate in the call to l <error> is the textual reason this failed. Usual reasons: =over 2 - + =item Apache config file for loncapa incorrect: - + one of the variables lonCertificateDirectory, lonnetCertificateAuthority, or lonnetCertificate undefined or incorrect @@ -8126,7 +7929,7 @@ Could not rewrite the internal password file for a user =item Result of password change for <user> : <result> - + A unix password change for <user> was attempted and the pipe returned <result> @@ -8155,7 +7958,7 @@ lond has been asked to exit by its clien client systemand <input> is the full exit command sent to the server. =item Red CRITICAL: ABNORMAL EXIT. child <pid> for server <hostname> died through a crass with this error->[<message>]. - + A lond child terminated. NOte that this termination can also occur when the child receives the QUIT or DIE signals. <pid> is the process id of the child, <hostname> the host lond is working for, and <message> the reason the child died @@ -8239,7 +8042,7 @@ file when sent it's USR1 signal. That p assumed to be hung in some un-fixable way. =item Finished checking children - + Master processs's USR1 processing is cojmplete. =item (Red) CRITICAL: ------- Starting ------ @@ -8253,7 +8056,7 @@ Started a new child process for <client> connected to the child. This was as a result of a TCP/IP connection from a client. =item Unable to determine who caller was, getpeername returned nothing - + In child process initialization. either getpeername returned undef or a zero sized object was returned. Processing continues, but in my opinion, this should be cause for the child to exit. @@ -8264,7 +8067,7 @@ In child process initialization. The pe The client address is stored as "Unavailable" and processing continues. =item (Yellow) INFO: Connection <ip> <name> connection type = <type> - + In child initialization. A good connectionw as received from <ip>. =over 2 @@ -8314,7 +8117,7 @@ The client (<client> is the peer's name negotiated an SSL connection with this child process. =item (Green) Successful insecure authentication with <client> - + The client has successfully negotiated an insecure connection withthe child process.