--- loncom/lond 2007/10/03 19:57:23 1.383 +++ loncom/lond 2007/10/06 04:32:23 1.384 @@ -2,7 +2,7 @@ # The LearningOnline Network # lond "LON Daemon" Server (port "LOND" 5663) # -# $Id: lond,v 1.383 2007/10/03 19:57:23 raeburn Exp $ +# $Id: lond,v 1.384 2007/10/06 04:32:23 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -60,7 +60,7 @@ my $DEBUG = 0; # Non zero to ena my $status=''; my $lastlog=''; -my $VERSION='$Revision: 1.383 $'; #' stupid emacs +my $VERSION='$Revision: 1.384 $'; #' stupid emacs my $remoteVERSION; my $currenthostid="default"; my $currentdomainid; @@ -3305,32 +3305,39 @@ sub put_course_id_handler { foreach my $pair (@pairs) { my ($key,$courseinfo) = split(/=/,$pair,2); $courseinfo =~ s/=/:/g; - if (ref($hashref) eq 'HASH') { - my @items = ('description','inst_code','owner','type'); - my @new_items = split(/:/,$courseinfo,-1); - for (my $i=0; $i<@new_items; $i++) { - $hashref->{$key}{$items[$i]} = $new_items[$i]; - } - $hashref->{$key}{'lasttime'} = $now; - } else { - my @current_items = split(/:/,$hashref->{$key},-1); - shift(@current_items); # remove description - pop(@current_items); # remove last access - my $numcurrent = scalar(@current_items); - if ($numcurrent > 3) { - $numcurrent = 3; + 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]} = $new_items[$i]; + } + $hashref->{$key} = + &Apache::lonnet::freeze_escape(\%storehash); + my $unesc_key = &unescape($key); + $hashref->{&escape('lasttime:'.$unesc_key)} = $now; + next; } - my @new_items = split(/:/,$courseinfo,-1); - my $numnew = scalar(@new_items); - if ($numcurrent > 0) { - if ($numnew <= $numcurrent) { # flushcourselogs() from pre 2.2 - for (my $j=$numcurrent-$numnew; $j>=0; $j--) { - $courseinfo .= ':'.$current_items[$numcurrent-$j-1]; - } + } + my @current_items = split(/:/,$hashref->{$key},-1); + shift(@current_items); # remove description + pop(@current_items); # remove last access + my $numcurrent = scalar(@current_items); + if ($numcurrent > 3) { + $numcurrent = 3; + } + my @new_items = split(/:/,$courseinfo,-1); + my $numnew = scalar(@new_items); + if ($numcurrent > 0) { + if ($numnew <= $numcurrent) { # flushcourselogs() from pre 2.2 + for (my $j=$numcurrent-$numnew; $j>=0; $j--) { + $courseinfo .= ':'.$current_items[$numcurrent-$j-1]; } } - $hashref->{$key}=$courseinfo.':'.$now; } + $hashref->{$key}=$courseinfo.':'.$now; } if (&untie_domain_hash($hashref)) { &Reply( $client, "ok\n", $userinput); @@ -3352,16 +3359,31 @@ sub put_course_id_handler { sub put_course_id_hash_handler { my ($cmd, $tail, $client) = @_; my $userinput = "$cmd:$tail"; - my ($udom, $what) = split(/:/, $tail,2); + 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(), - "P", $what); + my $hashref = &tie_domain_hash($udom, "nohist_courseids", &GDBM_WRCREAT()); if ($hashref) { foreach my $pair (@pairs) { my ($key,$value)=split(/=/,$pair); - $hashref->{$key} = $value; + 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); @@ -3403,6 +3425,15 @@ sub put_course_id_hash_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. @@ -3410,11 +3441,10 @@ sub put_course_id_hash_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,$as_hash) =split(/:/,$tail); + $typefilter,$regexp_ok,$rtn_as_hash) =split(/:/,$tail); if (defined($description)) { $description=&unescape($description); } else { @@ -3454,71 +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,$rawvalue) = each(%$hashref)) { - my ($descr,$lasttime,$inst_code,$owner,$type); - my $value = &Apache::lonnet::thaw_unescape($rawvalue); - if (ref($value) eq 'HASH') { - $descr = $value->{'description'}; - $inst_code = $value->{'inst_code'}; - $owner = $value->{'owner'}; - $type = $value->{'type'}; - $lasttime = $value->{'lasttime'}; + while (my ($key,$value) = each(%$hashref)) { + 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 { - my @courseitems = split(/:/,$rawvalue); + $is_hash = 0; + my @courseitems = split(/:/,&unescape($value)); $lasttime = pop(@courseitems); - ($descr,$inst_code,$owner,$type)=@courseitems; + next if ($lasttime<$since); + ($val{'descr'},$val{'inst_code'},$val{'owner'},$val{'type'}) = @courseitems; } - if ($lasttime<$since) { next; } 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 { @@ -3528,30 +3581,47 @@ sub dump_course_id_handler { } } } - my $unescapeCourse = &unescape($key); - 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$/')) { + if (eval{$unesc_val{'type'} !~ /^\Q$typefilter\E$/}) { $match = 0; } } } if ($match == 1) { - if ($as_hash) { - $qresult.=$key.'='.$rawvalue.'&'; + if ($rtn_as_hash) { + if ($is_hash) { + $qresult.=$key.'='.$value.'&'; + } else { + my %rtnhash = ( 'description' => &escape($val{'descr'}), + 'inst_code' => &escape($val{'inst_code'}), + 'owner' => &escape($val{'owner'}), + 'type' => &escape($val{'type'}), + ); + my $items = &Apache::lonnet::freeze_escape(\%rtnhash); + $qresult.=$key.'='.$items.'&'; + } } else { - $qresult.=$key.'='.$descr.':'.$inst_code.':'.$owner.'&'; + 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'}.'&'; + } } } } @@ -4385,7 +4455,6 @@ sub validate_class_access_handler { my ($cmd, $tail, $client) = @_; my $userinput = "$cmd:$tail"; my ($inst_class,$ownerlist,$cdom) = split(/:/, $tail); - $ownerlist = &unescape($ownerlist); my @owners = split(/,/,&unescape($ownerlist)); my $outcome; eval {