--- loncom/lond 2007/04/04 00:03:40 1.370 +++ loncom/lond 2008/01/07 02:21:35 1.393 @@ -2,7 +2,7 @@ # The LearningOnline Network # lond "LON Daemon" Server (port "LOND" 5663) # -# $Id: lond,v 1.370 2007/04/04 00:03:40 albertel Exp $ +# $Id: lond,v 1.393 2008/01/07 02:21:35 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -33,7 +33,6 @@ use strict; use lib '/home/httpd/lib/perl/'; use LONCAPA; use LONCAPA::Configuration; -use Apache::lonnet; use IO::Socket; use IO::File; @@ -53,13 +52,14 @@ use File::Find; use LONCAPA::lonlocal; use LONCAPA::lonssl; use Fcntl qw(:flock); +use Apache::lonnet; my $DEBUG = 0; # Non zero to enable debug log entries. my $status=''; my $lastlog=''; -my $VERSION='$Revision: 1.370 $'; #' stupid emacs +my $VERSION='$Revision: 1.393 $'; #' stupid emacs my $remoteVERSION; my $currenthostid="default"; my $currentdomainid; @@ -69,7 +69,6 @@ my $clientip; # IP address of client. my $clientname; # LonCAPA name of client. my $server; -my $thisserver; # DNS of us. my $keymode; @@ -136,7 +135,7 @@ my @adderrors = ("ok", "lcuseradd Unable to make www member of users's group", "lcuseradd Unable to su to root", "lcuseradd Unable to set password", - "lcuseradd Usrname has invalid characters", + "lcuseradd Username has invalid characters", "lcuseradd Password has an invalid character", "lcuseradd User already exists", "lcuseradd Could not add user.", @@ -172,19 +171,16 @@ sub ResetStatistics { # $Socket - Socket open on client. # $initcmd - The full text of the init command. # -# Implicit inputs: -# $thisserver - Our DNS name. -# # Returns: # IDEA session key on success. # undef on failure. # sub LocalConnection { my ($Socket, $initcmd) = @_; - Debug("Attempting local connection: $initcmd client: $clientip me: $thisserver"); + Debug("Attempting local connection: $initcmd client: $clientip"); if($clientip ne "127.0.0.1") { &logthis(' LocalConnection rejecting non local: ' - ."$clientip ne $thisserver "); + ."$clientip ne 127.0.0.1 "); close $Socket; return undef; } else { @@ -1000,7 +996,7 @@ sub ping_handler { my ($cmd, $tail, $client) = @_; Debug("$cmd $tail $client .. $currenthostid:"); - Reply( $client,"$currenthostid\n","$cmd:$tail"); + Reply( $client,\$currenthostid,"$cmd:$tail"); return 1; } @@ -1070,7 +1066,7 @@ sub establish_key_handler { $key=substr($key,0,32); my $cipherkey=pack("H32",$key); $cipher=new IDEA $cipherkey; - &Reply($replyfd, "$buildkey\n", "$cmd:$tail"); + &Reply($replyfd, \$buildkey, "$cmd:$tail"); return 1; @@ -1107,7 +1103,7 @@ sub load_handler { my $loadpercent=100*$loadavg/$perlvar{'lonLoadLim'}; - &Reply( $replyfd, "$loadpercent\n", "$cmd:$tail"); + &Reply( $replyfd, \$loadpercent, "$cmd:$tail"); return 1; } @@ -1137,7 +1133,7 @@ sub user_load_handler { my ($cmd, $tail, $replyfd) = @_; my $userloadpercent=&Apache::lonnet::userload(); - &Reply($replyfd, "$userloadpercent\n", "$cmd:$tail"); + &Reply($replyfd, \$userloadpercent, "$cmd:$tail"); return 1; } @@ -1180,7 +1176,7 @@ sub user_authorization_type { } else { $type .= ':'; } - &Reply( $replyfd, "$type\n", $userinput); + &Reply( $replyfd, \$type, $userinput); } return 1; @@ -1216,7 +1212,7 @@ sub push_file_handler { # process making the request. my $reply = &PushFile($userinput); - &Reply($client, "$reply\n", $userinput); + &Reply($client, \$reply, $userinput); } else { &Failure( $client, "refused\n", $userinput); @@ -1268,7 +1264,7 @@ sub du_handler { chdir($ududir); find($code,$ududir); $total_size=int($total_size/1024); - &Reply($client,"$total_size\n","$cmd:$ududir"); + &Reply($client,\$total_size,"$cmd:$ududir"); } else { &Failure($client, "bad_directory:$ududir\n","$cmd:$ududir"); } @@ -1337,7 +1333,7 @@ sub ls_handler { $ulsout='no_such_dir'; } if ($ulsout eq '') { $ulsout='empty'; } - &Reply($client, "$ulsout\n", $userinput); # This supports debug logging. + &Reply($client, \$ulsout, $userinput); # This supports debug logging. return 1; @@ -1406,7 +1402,7 @@ sub ls2_handler { $ulsout='no_such_dir'; } if ($ulsout eq '') { $ulsout='empty'; } - &Reply($client, "$ulsout\n", $userinput); # This supports debug logging. + &Reply($client, \$ulsout, $userinput); # This supports debug logging. return 1; } ®ister_handler("ls2", \&ls2_handler, 0, 1, 0); @@ -1434,7 +1430,7 @@ sub reinit_process_handler { if(&ValidManager($cert)) { chomp($userinput); my $reply = &ReinitProcess($userinput); - &Reply( $client, "$reply\n", $userinput); + &Reply( $client, \$reply, $userinput); } else { &Failure( $client, "refused\n", $userinput); } @@ -1609,7 +1605,7 @@ sub change_password_handler { my $result = &change_unix_password($uname, $npass); &logthis("Result of password change for $uname: ". $result); - &Reply($client, "$result\n", $userinput); + &Reply($client, \$result, $userinput); } else { # this just means that the current password mode is not # one we know how to change (e.g the kerberos auth modes or @@ -1670,9 +1666,9 @@ sub add_user_handler { } unless ($fperror) { my $result=&make_passwd_file($uname, $umode,$npass, $passfilename); - &Reply($client, $result, $userinput); #BUGBUG - could be fail + &Reply($client,\$result, $userinput); #BUGBUG - could be fail } else { - &Failure($client, "$fperror\n", $userinput); + &Failure($client, \$fperror, $userinput); } } umask($oldumask); @@ -1739,9 +1735,9 @@ sub change_authentication_handler { my $result = &change_unix_password($uname, $npass); &logthis("Result of password change for $uname: ".$result); if ($result eq "ok") { - &Reply($client, "$result\n") + &Reply($client, \$result); } else { - &Failure($client, "$result\n"); + &Failure($client, \$result); } } else { my $result=&make_passwd_file($uname, $umode,$npass,$passfilename); @@ -1760,7 +1756,7 @@ sub change_authentication_handler { &manage_permissions("/$udom/_au", $udom, $uname, "$umode:"); } } - &Reply($client, $result, $userinput); + &Reply($client, \$result, $userinput); } @@ -2099,6 +2095,37 @@ sub rename_user_file_handler { ®ister_handler("renameuserfile", \&rename_user_file_handler, 0,1,0); # +# Checks if the specified user has an active session on the server +# return ok if so, not_found if not +# +# Parameters: +# cmd - The request keyword that dispatched to tus. +# tail - The tail of the request (colon separated parameters). +# client - Filehandle open on the client. +# Return: +# 1. +sub user_has_session_handler { + my ($cmd, $tail, $client) = @_; + + my ($udom, $uname) = map { &unescape($_) } (split(/:/, $tail)); + + &logthis("Looking for $udom $uname"); + opendir(DIR,$perlvar{'lonIDsDir'}); + my $filename; + while ($filename=readdir(DIR)) { + last if ($filename=~/^\Q$uname\E_\d+_\Q$udom\E_/); + } + if ($filename) { + &Reply($client, "ok\n", "$cmd:$tail"); + } else { + &Failure($client, "not_found\n", "$cmd:$tail"); + } + return 1; + +} +®ister_handler("userhassession", \&user_has_session_handler, 0,1,0); + +# # Authenticate access to a user file by checking that the token the user's # passed also exists in their session file # @@ -2114,24 +2141,24 @@ sub token_auth_user_file_handler { my ($fname, $session) = split(/:/, $tail); chomp($session); - my $reply="non_auth\n"; + my $reply="non_auth"; my $file = $perlvar{'lonIDsDir'}.'/'.$session.'.id'; if (open(ENVIN,"$file")) { flock(ENVIN,LOCK_SH); tie(my %disk_env,'GDBM_File',"$file",&GDBM_READER(),0640); if (exists($disk_env{"userfile.$fname"})) { - $reply="ok\n"; + $reply="ok"; } else { foreach my $envname (keys(%disk_env)) { if ($envname=~ m|^userfile\.\Q$fname\E|) { - $reply="ok\n"; + $reply="ok"; last; } } } untie(%disk_env); close(ENVIN); - &Reply($client, $reply, "$cmd:$tail"); + &Reply($client, \$reply, "$cmd:$tail"); } else { &Failure($client, "invalid_token\n", "$cmd:$tail"); } @@ -2191,13 +2218,13 @@ sub subscribe_handler { ®ister_handler("sub", \&subscribe_handler, 0, 1, 0); # -# Determine the version of a resource (?) Or is it return -# the top version of the resource? Not yet clear from the -# code in currentversion. +# Determine the latest version of a resource (it looks for the highest +# past version and then returns that +1) # # Parameters: # $cmd - The command that got us here. # $tail - Tail of the command (remaining parameters). +# (Should consist of an absolute path to a file) # $client - File descriptor connected to client. # Returns # 0 - Requested to exit, caller should shut down. @@ -2555,10 +2582,11 @@ sub get_profile_entry { my ($udom,$uname,$namespace,$what) = split(/:/,$tail); chomp($what); + my $replystring = read_profile($udom, $uname, $namespace, $what); my ($first) = split(/:/,$replystring); if($first ne "error") { - &Reply($client, "$replystring\n", $userinput); + &Reply($client, \$replystring, $userinput); } else { &Failure($client, $replystring." while attempting get\n", $userinput); } @@ -2698,7 +2726,7 @@ sub get_profile_keys { } if (&untie_user_hash($hashref)) { $qresult=~s/\&$//; - &Reply($client, "$qresult\n", $userinput); + &Reply($client, \$qresult, $userinput); } else { &Failure($client, "error: ".($!+0)." untie(GDBM) Failed ". "while attempting keys\n", $userinput); @@ -2768,7 +2796,7 @@ sub dump_profile_database { } } chop($qresult); - &Reply($client , "$qresult\n", $userinput); + &Reply($client , \$qresult, $userinput); } else { &Failure( $client, "error: ".($!+0)." untie(GDBM) Failed ". "while attempting currentdump\n", $userinput); @@ -2851,7 +2879,7 @@ sub dump_with_regexp { } if (&untie_user_hash($hashref)) { chop($qresult); - &Reply($client, "$qresult\n", $userinput); + &Reply($client, \$qresult, $userinput); } else { &Failure( $client, "error: ".($!+0)." untie(GDBM) Failed ". "while attempting dump\n", $userinput); @@ -3059,7 +3087,7 @@ sub restore_handler { } if (&untie_user_hash($hashref)) { $qresult=~s/\&$//; - &Reply( $client, "$qresult\n", $userinput); + &Reply( $client, \$qresult, $userinput); } else { &Failure($client, "error: ".($!+0)." untie(GDBM) Failed ". "while attempting restore\n", $userinput); @@ -3140,7 +3168,7 @@ sub retrieve_chat_handler { $reply.=&escape($_).':'; } $reply=~s/\:$//; - &Reply($client, $reply."\n", $userinput); + &Reply($client, \$reply, $userinput); return 1; @@ -3277,6 +3305,22 @@ sub put_course_id_handler { foreach my $pair (@pairs) { my ($key,$courseinfo) = split(/=/,$pair,2); $courseinfo =~ s/=/:/g; + if (defined($hashref->{$key})) { + my $value = &Apache::lonnet::thaw_unescape($hashref->{$key}); + if (ref($value) eq 'HASH') { + my @items = ('description','inst_code','owner','type'); + my @new_items = split(/:/,$courseinfo,-1); + my %storehash; + for (my $i=0; $i<@new_items; $i++) { + $storehash{$items[$i]} = &unescape($new_items[$i]); + } + $hashref->{$key} = + &Apache::lonnet::freeze_escape(\%storehash); + my $unesc_key = &unescape($key); + $hashref->{&escape('lasttime:'.$unesc_key)} = $now; + next; + } + } my @current_items = split(/:/,$hashref->{$key},-1); shift(@current_items); # remove description pop(@current_items); # remove last access @@ -3293,7 +3337,7 @@ sub put_course_id_handler { } } } - $hashref->{$key}=$courseinfo.':'.$now; + $hashref->{$key}=$courseinfo.':'.$now; } if (&untie_domain_hash($hashref)) { &Reply( $client, "ok\n", $userinput); @@ -3307,12 +3351,54 @@ sub put_course_id_handler { ." tie(GDBM) Failed ". "while attempting courseidput\n", $userinput); } - return 1; } ®ister_handler("courseidput", \&put_course_id_handler, 0, 1, 0); +sub put_course_id_hash_handler { + my ($cmd, $tail, $client) = @_; + my $userinput = "$cmd:$tail"; + my ($udom,$mode,$what) = split(/:/, $tail,3); + chomp($what); + my $now=time; + my @pairs=split(/\&/,$what); + my $hashref = &tie_domain_hash($udom, "nohist_courseids", &GDBM_WRCREAT()); + if ($hashref) { + foreach my $pair (@pairs) { + my ($key,$value)=split(/=/,$pair); + my $unesc_key = &unescape($key); + if ($mode ne 'timeonly') { + if (!defined($hashref->{&escape('lasttime:'.$unesc_key)})) { + my $curritems = &Apache::lonnet::thaw_unescape($key); + if (ref($curritems) ne 'HASH') { + my @current_items = split(/:/,$hashref->{$key},-1); + my $lasttime = pop(@current_items); + $hashref->{&escape('lasttime:'.$unesc_key)} = $lasttime; + } else { + $hashref->{&escape('lasttime:'.$unesc_key)} = ''; + } + } + $hashref->{$key} = $value; + } + if ($mode ne 'notime') { + $hashref->{&escape('lasttime:'.$unesc_key)} = $now; + } + } + if (&untie_domain_hash($hashref)) { + &Reply($client, "ok\n", $userinput); + } else { + &Failure($client, "error: ".($!+0)." untie(GDBM) Failed ". + "while attempting courseidputhash\n", $userinput); + } + } else { + &Failure( $client, "error: ".($!+0)." tie(GDBM) Failed ". + "while attempting courseidputhash\n", $userinput); + } + return 1; +} +®ister_handler("courseidputhash", \&put_course_id_hash_handler, 0, 1, 0); + # Retrieves the value of a course id resource keyword pattern # defined since a starting date. Both the starting date and the # keyword pattern are optional. If the starting date is not supplied it @@ -3339,6 +3425,15 @@ sub put_course_id_handler { # owner matches the supplied username and/or domain # will be returned. Pre-2.2.0 legacy entries from # nohist_courseiddump will only contain usernames. +# type - optional parameter for selection +# regexp_ok - if true, allow the supplied institutional code +# filter to behave as a regular expression. +# rtn_as_hash - whether to return the information available for +# each matched item as a frozen hash of all +# key, value pairs in the item's hash, or as a +# colon-separated list of (in order) description, +# institutional code, and course owner. +# # $client - The socket open on the client. # Returns: # 1 - Continue processing. @@ -3346,11 +3441,10 @@ sub put_course_id_handler { # a reply is written to $client. sub dump_course_id_handler { my ($cmd, $tail, $client) = @_; - my $userinput = "$cmd:$tail"; my ($udom,$since,$description,$instcodefilter,$ownerfilter,$coursefilter, - $typefilter,$regexp_ok) =split(/:/,$tail); + $typefilter,$regexp_ok,$rtn_as_hash) =split(/:/,$tail); if (defined($description)) { $description=&unescape($description); } else { @@ -3390,62 +3484,94 @@ sub dump_course_id_handler { if (defined($regexp_ok)) { $regexp_ok=&unescape($regexp_ok); } - - unless (defined($since)) { $since=0; } + my $unpack = 1; + if ($description eq '.' && $instcodefilter eq '.' && $coursefilter eq '.' && + $typefilter eq '.') { + $unpack = 0; + } + if (!defined($since)) { $since=0; } my $qresult=''; my $hashref = &tie_domain_hash($udom, "nohist_courseids", &GDBM_WRCREAT()); if ($hashref) { while (my ($key,$value) = each(%$hashref)) { - my ($descr,$lasttime,$inst_code,$owner,$type); - my @courseitems = split(/:/,$value); - $lasttime = pop(@courseitems); - ($descr,$inst_code,$owner,$type)=@courseitems; - if ($lasttime<$since) { next; } + my ($unesc_key,$lasttime_key,$lasttime,$is_hash,%val,%unesc_val); + $unesc_key = &unescape($key); + if ($unesc_key =~ /^lasttime:/) { + next; + } else { + $lasttime_key = &escape('lasttime:'.$unesc_key); + } + if ($hashref->{$lasttime_key} ne '') { + $lasttime = $hashref->{$lasttime_key}; + next if ($lasttime<$since); + } + my $items = &Apache::lonnet::thaw_unescape($value); + if (ref($items) eq 'HASH') { + $is_hash = 1; + if ($unpack || !$rtn_as_hash) { + $unesc_val{'descr'} = $items->{'description'}; + $unesc_val{'inst_code'} = $items->{'inst_code'}; + $unesc_val{'owner'} = $items->{'owner'}; + $unesc_val{'type'} = $items->{'type'}; + } + } else { + $is_hash = 0; + my @courseitems = split(/:/,$value); + $lasttime = pop(@courseitems); + next if ($lasttime<$since); + ($val{'descr'},$val{'inst_code'},$val{'owner'},$val{'type'}) = @courseitems; + } my $match = 1; - unless ($description eq '.') { - my $unescapeDescr = &unescape($descr); - unless (eval('$unescapeDescr=~/\Q$description\E/i')) { + if ($description ne '.') { + if (!$is_hash) { + $unesc_val{'descr'} = &unescape($val{'descr'}); + } + if (eval{$unesc_val{'descr'} !~ /\Q$description\E/i}) { $match = 0; - } + } } - unless ($instcodefilter eq '.' || !defined($instcodefilter)) { - my $unescapeInstcode = &unescape($inst_code); + if ($instcodefilter ne '.') { + if (!$is_hash) { + $unesc_val{'inst_code'} = &unescape($val{'inst_code'}); + } if ($regexp_ok) { - unless (eval('$unescapeInstcode=~/$instcodefilter/')) { + if (eval{$unesc_val{'inst_code'} !~ /$instcodefilter/}) { $match = 0; } } else { - unless (eval('$unescapeInstcode=~/\Q$instcodefilter\E/i')) { + if (eval{$unesc_val{'inst_code'} !~ /\Q$instcodefilter\E/i}) { $match = 0; } } } - unless ($ownerfilter eq '.' || !defined($ownerfilter)) { - my $unescapeOwner = &unescape($owner); + if ($ownerfilter ne '.') { + if (!$is_hash) { + $unesc_val{'owner'} = &unescape($val{'owner'}); + } if (($ownerunamefilter ne '') && ($ownerdomfilter ne '')) { - if ($unescapeOwner =~ /:/) { - if (eval('$unescapeOwner !~ - /\Q$ownerunamefilter\E:\Q$ownerdomfilter\E$/i')) { + if ($unesc_val{'owner'} =~ /:/) { + if (eval{$unesc_val{'owner'} !~ + /\Q$ownerunamefilter\E:\Q$ownerdomfilter\E$/i}) { $match = 0; } } else { - if (eval('$unescapeOwner!~/\Q$ownerunamefilter\E/i')) { + if (eval{$unesc_val{'owner'} !~ /\Q$ownerunamefilter\E/i}) { $match = 0; } } } elsif ($ownerunamefilter ne '') { - if ($unescapeOwner =~ /:/) { - if (eval('$unescapeOwner!~/\Q$ownerunamefilter\E:[^:]+$/i')) { + if ($unesc_val{'owner'} =~ /:/) { + if (eval{$unesc_val{'owner'} !~ /\Q$ownerunamefilter\E:[^:]+$/i}) { $match = 0; } } else { - if (eval('$unescapeOwner!~/\Q$ownerunamefilter\E/i')) { + if (eval{$unesc_val{'owner'} !~ /\Q$ownerunamefilter\E/i}) { $match = 0; } } } elsif ($ownerdomfilter ne '') { - if ($unescapeOwner =~ /:/) { - if (eval('$unescapeOwner!~/^[^:]+:\Q$ownerdomfilter\E/')) { + if ($unesc_val{'owner'} =~ /:/) { + if (eval{$unesc_val{'owner'} !~ /^[^:]+:\Q$ownerdomfilter\E/}) { $match = 0; } } else { @@ -3455,31 +3581,53 @@ sub dump_course_id_handler { } } } - unless ($coursefilter eq '.' || !defined($coursefilter)) { - my $unescapeCourse = &unescape($key); - unless (eval('$unescapeCourse=~/^$udom(_)\Q$coursefilter\E$/')) { + if ($coursefilter ne '.') { + if (eval{$unesc_key !~ /^$udom(_)\Q$coursefilter\E$/}) { $match = 0; } } - unless ($typefilter eq '.' || !defined($typefilter)) { - my $unescapeType = &unescape($type); - if ($type eq '') { + if ($typefilter ne '.') { + if (!$is_hash) { + $unesc_val{'type'} = &unescape($val{'type'}); + } + if ($unesc_val{'type'} eq '') { if ($typefilter ne 'Course') { $match = 0; } - } else { - unless (eval('$unescapeType=~/^\Q$typefilter\E$/')) { + } else { + if (eval{$unesc_val{'type'} !~ /^\Q$typefilter\E$/}) { $match = 0; } } } if ($match == 1) { - $qresult.=$key.'='.$descr.':'.$inst_code.':'.$owner.'&'; + if ($rtn_as_hash) { + if ($is_hash) { + $qresult.=$key.'='.$value.'&'; + } else { + my %rtnhash = ( 'description' => &unescape($val{'descr'}), + 'inst_code' => &unescape($val{'inst_code'}), + 'owner' => &unescape($val{'owner'}), + 'type' => &unescape($val{'type'}), + ); + my $items = &Apache::lonnet::freeze_escape(\%rtnhash); + $qresult.=$key.'='.$items.'&'; + } + } else { + if ($is_hash) { + $qresult .= $key.'='.&escape($unesc_val{'descr'}).':'. + &escape($unesc_val{'inst_code'}).':'. + &escape($unesc_val{'owner'}).'&'; + } else { + $qresult .= $key.'='.$val{'descr'}.':'.$val{'inst_code'}. + ':'.$val{'owner'}.'&'; + } + } } } if (&untie_domain_hash($hashref)) { chop($qresult); - &Reply($client, "$qresult\n", $userinput); + &Reply($client, \$qresult, $userinput); } else { &Failure($client, "error: ".($!+0)." untie(GDBM) Failed ". "while attempting courseiddump\n", $userinput); @@ -3488,8 +3636,6 @@ sub dump_course_id_handler { &Failure($client, "error: ".($!+0)." tie(GDBM) Failed ". "while attempting courseiddump\n", $userinput); } - - return 1; } ®ister_handler("courseiddump", \&dump_course_id_handler, 0, 1, 0); @@ -3572,7 +3718,7 @@ sub get_domain_handler { } if (&untie_domain_hash($hashref)) { $qresult=~s/\&$//; - &Reply($client, "$qresult\n", $userinput); + &Reply($client, \$qresult, $userinput); } else { &Failure( $client, "error: ".($!+0)." untie(GDBM) Failed ". "while attempting getdom\n",$userinput); @@ -3670,7 +3816,7 @@ sub get_id_handler { } if (&untie_domain_hash($hashref)) { $qresult=~s/\&$//; - &Reply($client, "$qresult\n", $userinput); + &Reply($client, \$qresult, $userinput); } else { &Failure( $client, "error: ".($!+0)." untie(GDBM) Failed ". "while attempting idget\n",$userinput); @@ -3794,7 +3940,7 @@ sub dump_dcmail_handler { } if (&untie_domain_hash($hashref)) { chop($qresult); - &Reply($client, "$qresult\n", $userinput); + &Reply($client, \$qresult, $userinput); } else { &Failure($client, "error: ".($!+0)." untie(GDBM) Failed ". "while attempting dcmaildump\n", $userinput); @@ -3912,7 +4058,7 @@ sub dump_domainroles_handler { } } unless (@roles < 1) { - unless (grep/^$trole$/,@roles) { + unless (grep/^\Q$trole\E$/,@roles) { $match = 0; } } @@ -3922,7 +4068,7 @@ sub dump_domainroles_handler { } if (&untie_domain_hash($hashref)) { chop($qresult); - &Reply($client, "$qresult\n", $userinput); + &Reply($client, \$qresult, $userinput); } else { &Failure($client, "error: ".($!+0)." untie(GDBM) Failed ". "while attempting domrolesdump\n", $userinput); @@ -3976,7 +4122,7 @@ sub tmp_put_handler { if ($store=IO::File->new(">$execdir/tmp/$id.tmp")) { print $store $record; close $store; - &Reply($client, "$id\n", $userinput); + &Reply($client, \$id, $userinput); } else { &Failure( $client, "error: ".($!+0)."IO::File->new Failed ". "while attempting tmpput\n", $userinput); @@ -4010,7 +4156,7 @@ sub tmp_get_handler { my $execdir=$perlvar{'lonDaemons'}; if ($store=IO::File->new("$execdir/tmp/$id.tmp")) { my $reply=<$store>; - &Reply( $client, "$reply\n", $userinput); + &Reply( $client, \$reply, $userinput); close $store; } else { &Failure( $client, "error: ".($!+0)."IO::File->new Failed ". @@ -4194,7 +4340,7 @@ sub enrollment_enabled_handler { my ($cdom) = split(/:/, $tail, 2); # Domain we're asking about. my $outcome = &localenroll::run($cdom); - &Reply($client, "$outcome\n", $userinput); + &Reply($client, \$outcome, $userinput); return 1; } @@ -4221,7 +4367,7 @@ sub get_sections_handler { my @secs = &localenroll::get_sections($coursecode,$cdom); my $seclist = &escape(join(':',@secs)); - &Reply($client, "$seclist\n", $userinput); + &Reply($client, \$seclist, $userinput); return 1; @@ -4250,7 +4396,7 @@ sub validate_course_owner_handler { $owner = &unescape($owner); my $outcome = &localenroll::new_course($inst_course_id,$owner,$cdom); - &Reply($client, "$outcome\n", $userinput); + &Reply($client, \$outcome, $userinput); @@ -4281,7 +4427,7 @@ sub validate_course_section_handler { my ($inst_course_id, $cdom) = split(/:/, $tail); my $outcome=&localenroll::validate_courseID($inst_course_id,$cdom); - &Reply($client, "$outcome\n", $userinput); + &Reply($client, \$outcome, $userinput); return 1; @@ -4308,14 +4454,14 @@ sub validate_course_section_handler { sub validate_class_access_handler { my ($cmd, $tail, $client) = @_; my $userinput = "$cmd:$tail"; - my ($inst_class,$courseowner,$cdom) = split(/:/, $tail); - $courseowner = &unescape($courseowner); + my ($inst_class,$ownerlist,$cdom) = split(/:/, $tail); + my $owners = &unescape($ownerlist); my $outcome; eval { local($SIG{__DIE__})='DEFAULT'; - $outcome=&localenroll::check_section($inst_class,$courseowner,$cdom); + $outcome=&localenroll::check_section($inst_class,$owners,$cdom); }; - &Reply($client,"$outcome\n", $userinput); + &Reply($client,\$outcome, $userinput); return 1; } @@ -4476,7 +4622,7 @@ sub get_institutional_defaults_handler { $result.=&escape($key).'='.&escape($value).'&'; } $result .= 'code_order='.&escape(join('&',@code_order)); - &Reply($client,$result."\n",$userinput); + &Reply($client,\$result,$userinput); } else { &Reply($client,"error\n", $userinput); } @@ -4487,6 +4633,132 @@ sub get_institutional_defaults_handler { ®ister_handler("autoinstcodedefaults", \&get_institutional_defaults_handler,0,1,0); +sub get_institutional_user_rules { + my ($cmd, $tail, $client) = @_; + my $userinput = "$cmd:$tail"; + my $dom = &unescape($tail); + my (%rules_hash,@rules_order); + my $outcome; + eval { + local($SIG{__DIE__})='DEFAULT'; + $outcome = &localenroll::username_rules($dom,\%rules_hash,\@rules_order); + }; + if (!$@) { + if ($outcome eq 'ok') { + my $result; + foreach my $key (keys(%rules_hash)) { + $result .= &escape($key).'='.&Apache::lonnet::freeze_escape($rules_hash{$key}).'&'; + } + $result =~ s/\&$//; + $result .= ':'; + if (@rules_order > 0) { + foreach my $item (@rules_order) { + $result .= &escape($item).'&'; + } + } + $result =~ s/\&$//; + &Reply($client,\$result,$userinput); + } else { + &Reply($client,"error\n", $userinput); + } + } else { + &Failure($client,"unknown_cmd\n",$userinput); + } +} +®ister_handler("instuserrules",\&get_institutional_user_rules,0,1,0); + +sub get_institutional_id_rules { + my ($cmd, $tail, $client) = @_; + my $userinput = "$cmd:$tail"; + my $dom = &unescape($tail); + my (%rules_hash,@rules_order); + my $outcome; + eval { + local($SIG{__DIE__})='DEFAULT'; + $outcome = &localenroll::id_rules($dom,\%rules_hash,\@rules_order); + }; + if (!$@) { + if ($outcome eq 'ok') { + my $result; + foreach my $key (keys(%rules_hash)) { + $result .= &escape($key).'='.&Apache::lonnet::freeze_escape($rules_hash{$key}).'&'; + } + $result =~ s/\&$//; + $result .= ':'; + if (@rules_order > 0) { + foreach my $item (@rules_order) { + $result .= &escape($item).'&'; + } + } + $result =~ s/\&$//; + &Reply($client,\$result,$userinput); + } else { + &Reply($client,"error\n", $userinput); + } + } else { + &Failure($client,"unknown_cmd\n",$userinput); + } +} +®ister_handler("instidrules",\&get_institutional_id_rules,0,1,0); + + +sub institutional_username_check { + my ($cmd, $tail, $client) = @_; + my $userinput = "$cmd:$tail"; + my %rulecheck; + my $outcome; + my ($udom,$uname,@rules) = split(/:/,$tail); + $udom = &unescape($udom); + $uname = &unescape($uname); + @rules = map {&unescape($_);} (@rules); + eval { + local($SIG{__DIE__})='DEFAULT'; + $outcome = &localenroll::username_check($udom,$uname,\@rules,\%rulecheck); + }; + if (!$@) { + if ($outcome eq 'ok') { + my $result=''; + foreach my $key (keys(%rulecheck)) { + $result.=&escape($key).'='.&Apache::lonnet::freeze_escape($rulecheck{$key}).'&'; + } + &Reply($client,\$result,$userinput); + } else { + &Reply($client,"error\n", $userinput); + } + } else { + &Failure($client,"unknown_cmd\n",$userinput); + } +} +®ister_handler("instrulecheck",\&institutional_username_check,0,1,0); + +sub institutional_id_check { + my ($cmd, $tail, $client) = @_; + my $userinput = "$cmd:$tail"; + my %rulecheck; + my $outcome; + my ($udom,$id,@rules) = split(/:/,$tail); + $udom = &unescape($udom); + $id = &unescape($id); + @rules = map {&unescape($_);} (@rules); + eval { + local($SIG{__DIE__})='DEFAULT'; + $outcome = &localenroll::id_check($udom,$id,\@rules,\%rulecheck); + }; + if (!$@) { + if ($outcome eq 'ok') { + my $result=''; + foreach my $key (keys(%rulecheck)) { + $result.=&escape($key).'='.&Apache::lonnet::freeze_escape($rulecheck{$key}).'&'; + } + &Reply($client,\$result,$userinput); + } else { + &Reply($client,"error\n", $userinput); + } + } else { + &Failure($client,"unknown_cmd\n",$userinput); + } +} +®ister_handler("instidrulecheck",\&institutional_id_check,0,1,0); # Get domain specific conditions for import of student photographs to a course # @@ -4639,7 +4911,7 @@ sub inst_usertypes_handler { } $res=~s/\&$//; } - &Reply($client, "$res\n", $userinput); + &Reply($client, \$res, $userinput); return 1; } ®ister_handler("inst_usertypes", \&inst_usertypes_handler, 0, 1, 0); @@ -4907,7 +5179,7 @@ sub catchexception { $SIG{__DIE__}='DEFAULT'; &status("Catching exception"); &logthis("CRITICAL: " - ."ABNORMAL EXIT. Child $$ for server $thisserver died through " + ."ABNORMAL EXIT. Child $$ for server ".$perlvar{'lonHostID'}." died through " ."a crash with this error msg->[$error]"); &logthis('Famous last words: '.$status.' - '.$lastlog); if ($client) { print $client "error: $error\n"; } @@ -5048,12 +5320,12 @@ sub UpdateHosts { # either dropped or changed hosts. Note that the re-read of the table # will take care of new and changed hosts as connections come into being. - #FIXME need a way to tell lonnet that it needs to reset host - #cached host info + &Apache::lonnet::reset_hosts_info(); foreach my $child (keys(%children)) { my $childip = $children{$child}; - if (defined(&Apache::lonnet::get_hosts_from_ip($childip))) { + if ($childip ne '127.0.0.1' + && !defined(&Apache::lonnet::get_hosts_from_ip($childip))) { logthis(' UpdateHosts killing child ' ." $child for ip $childip "); kill('INT', $child); @@ -5138,9 +5410,14 @@ sub Debug { # sub Reply { my ($fd, $reply, $request) = @_; - print $fd $reply; - Debug("Request was $request Reply was $reply"); - + if (ref($reply)) { + print $fd $$reply; + print $fd "\n"; + if ($DEBUG) { Debug("Request was $request Reply was $$reply"); } + } else { + print $fd $reply; + if ($DEBUG) { Debug("Request was $request Reply was $reply"); } + } $Transactions++; } @@ -5371,8 +5648,6 @@ sub make_new_child { # ----------------------------------------------------------------------------- # see if we know client and 'check' for spoof IP by ineffective challenge - ReadManagerTable; # May also be a manager!! - my $outsideip=$clientip; if ($clientip eq '127.0.0.1') { $outsideip=&Apache::lonnet::get_host_ip($perlvar{'lonHostID'}); @@ -5492,7 +5767,7 @@ sub make_new_child { # ---------------- New known client connecting, could mean machine online again if (&Apache::lonnet::get_host_ip($currenthostid) ne $clientip && $clientip ne '127.0.0.1') { - &Apache::lonnet::reconlonc(); + &Apache::lonnet::reconlonc($clientname); } &logthis("Established connection: $clientname"); &status('Will listen to '.$clientname); @@ -5776,6 +6051,10 @@ sub validate_user { $password, $credentials); $validated = ($krbreturn == 1); + if (!$validated) { + &logthis('krb5: '.$user.', '.$contentpwd.', '. + &Authen::Krb5::error()); + } } else { $validated = 0; } @@ -6021,7 +6300,7 @@ sub subscribe { # the metadata unless ($fname=~/\.meta$/) { &unsub("$fname.meta",$clientip); } $fname=~s/\/home\/httpd\/html\/res/raw/; - $fname="http://$thisserver/".$fname; + $fname="http://".&Apache::lonnet::hostname($perlvar{'lonHostID'})."/".$fname; $result="$fname\n"; } } else { @@ -6064,7 +6343,7 @@ sub change_unix_password { sub make_passwd_file { my ($uname, $umode,$npass,$passfilename)=@_; - my $result="ok\n"; + my $result="ok"; if ($umode eq 'krb4' or $umode eq 'krb5') { { my $pf = IO::File->new(">$passfilename"); @@ -6132,7 +6411,7 @@ sub make_passwd_file { if($useraddok > 0) { my $error_text = &lcuseraddstrerror($useraddok); &logthis("Failed lcuseradd: $error_text"); - $result = "lcuseradd_failed:$error_text\n"; + $result = "lcuseradd_failed:$error_text"; } else { my $pf = IO::File->new(">$passfilename"); if($pf) { @@ -6156,7 +6435,7 @@ sub make_passwd_file { } } } else { - $result="auth_mode_error\n"; + $result="auth_mode_error"; } return $result; }