--- loncom/lonnet/perl/lonnet.pm 2024/05/21 02:57:16 1.1527 +++ loncom/lonnet/perl/lonnet.pm 2025/01/13 01:00:58 1.1534 @@ -1,7 +1,7 @@ # The LearningOnline Network # TCP networking package # -# $Id: lonnet.pm,v 1.1527 2024/05/21 02:57:16 raeburn Exp $ +# $Id: lonnet.pm,v 1.1534 2025/01/13 01:00:58 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -188,7 +188,11 @@ sub create_connection { Type => SOCK_STREAM, Timeout => 10); return 0 if (!$client); - print $client (join(':',$hostname,$lonid,&machine_ids($hostname),$loncaparevs{$lonid})."\n"); + if ($loncaparevs{$lonid} =~ /^(\d+\.\d+\.[\w.]+)-\d+$/) { + print $client (join(':',$hostname,$lonid,$1,&machine_ids($hostname))."\n"); + } else { + print $client (join(':',$hostname,$lonid,&machine_ids($hostname))."\n"); + } my $result = <$client>; chomp($result); return 1 if ($result eq 'done'); @@ -224,7 +228,7 @@ sub get_server_distarch { } } my $rep = &reply('serverdistarch',$lonhost); - unless ($rep eq 'unknown_command' || $rep eq 'no_such_host' || + unless ($rep eq 'unknown_cmd' || $rep eq 'no_such_host' || $rep eq 'con_lost' || $rep eq 'rejected' || $rep eq 'refused' || $rep eq '') { return &do_cache_new('serverdistarch',$lonhost,$rep,$cachetime); @@ -2825,6 +2829,9 @@ sub get_domain_defaults { if (ref($domconfig{'coursedefaults'}{'postsubmit'}) eq 'HASH') { $domdefaults{'postsubmit'} = $domconfig{'coursedefaults'}{'postsubmit'}{'client'}; } + if (ref($domconfig{'coursedefaults'}{'crseditors'}) eq 'ARRAY') { + $domdefaults{'crseditors'}=join(',',@{$domconfig{'coursedefaults'}{'crseditors'}}); + } foreach my $type (@coursetypes) { if (ref($domconfig{'coursedefaults'}{'coursecredits'}) eq 'HASH') { unless ($type eq 'community') { @@ -2858,9 +2865,6 @@ sub get_domain_defaults { } else { $domdefaults{$type.'crsauthor'} = 1; } - if (ref($domconfig{'coursedefaults'}{'crseditors'}) eq 'ARRAY') { - $domdefaults{'crseditors'}=join(',',@{$domconfig{'coursedefaults'}{'crseditors'}}); - } } if (ref($domconfig{'coursedefaults'}{'canclone'}) eq 'HASH') { if (ref($domconfig{'coursedefaults'}{'canclone'}{'instcode'}) eq 'ARRAY') { @@ -3015,6 +3019,9 @@ sub get_domain_defaults { last if ($domdefaults{'userapprovals'}); } } + if (ref($domconfig{'privacy'}{'othdom'}) eq 'HASH') { + $domdefaults{'privacyothdom'} = $domconfig{'privacy'}{'othdom'}; + } } &do_cache_new('domdefaults',$domain,\%domdefaults,$cachetime); return %domdefaults; @@ -6163,7 +6170,7 @@ sub courselastaccess { sub extract_lastaccess { my ($returnhash,$rep) = @_; if (ref($returnhash) eq 'HASH') { - unless ($rep eq 'unknown_command' || $rep eq 'no_such_host' || + unless ($rep eq 'unknown_cmd' || $rep eq 'no_such_host' || $rep eq 'con_lost' || $rep eq 'rejected' || $rep eq 'refused' || $rep eq '') { my @pairs=split(/\&/,$rep); @@ -6750,13 +6757,17 @@ sub cstore { if ($stuname) { $home=&homeserver($stuname,$domain); } - $symb=&symbclean($symb); + unless (($symb eq '_feedback') || ($symb eq '_discussion')) { + $symb=&symbclean($symb); + } if (!$symb) { unless ($symb=&symbread()) { return ''; } } if (!$domain) { $domain=$env{'user.domain'}; } if (!$stuname) { $stuname=$env{'user.name'}; } - &devalidate($symb,$stuname,$domain); + unless (($symb eq '_feedback') || ($symb eq '_discussion')) { + &devalidate($symb,$stuname,$domain); + } $symb=escape($symb); if (!$namespace) { @@ -6766,7 +6777,7 @@ sub cstore { } if (!$home) { $home=$env{'user.home'}; } - $$storehash{'ip'}=&get_requestor_ip(); + $$storehash{'ip'} = &get_requestor_ip(); $$storehash{'host'}=$perlvar{'lonHostID'}; my $namevalue=''; @@ -10401,7 +10412,7 @@ sub auto_instsec_reformat { my $info = &freeze_escape($instsecref); my $response=&reply('autoinstsecreformat:'.$cdom.':'. $action.':'.$info,$server); - next if ($response =~ /(con_lost|error|no_such_host|refused|unknown_command)/); + next if ($response =~ /(con_lost|error|no_such_host|refused|unknown_cmd)/); my @items = split(/&/,$response); foreach my $item (@items) { my ($key,$value) = split(/=/,$item); @@ -10483,7 +10494,7 @@ sub auto_export_grades { my $grades = &freeze_escape($gradesref); my $response=&reply('encrypt:autoexportgrades:'.$cdom.':'.$cnum.':'. $info.':'.$grades,$homeserver); - unless ($response =~ /(con_lost|error|no_such_host|refused|unknown_command)/) { + unless ($response =~ /(con_lost|error|no_such_host|refused|unknown_cmd)/) { my @items = split(/&/,$response); foreach my $item (@items) { my ($key,$value) = split('=',$item); @@ -11676,7 +11687,7 @@ sub is_course { } sub store_userdata { - my ($storehash,$datakey,$namespace,$udom,$uname) = @_; + my ($storehash,$datakey,$namespace,$udom,$uname,$ip) = @_; my $result; if ($datakey ne '') { if (ref($storehash) eq 'HASH') { @@ -11688,7 +11699,11 @@ sub store_userdata { if (($uhome eq '') || ($uhome eq 'no_host')) { $result = 'error: no_host'; } else { - $storehash->{'ip'} = &get_requestor_ip(); + if ($ip ne '') { + $storehash->{'ip'} = $ip; + } else { + $storehash->{'ip'} = &get_requestor_ip(); + } $storehash->{'host'} = $perlvar{'lonHostID'}; my $namevalue=''; @@ -12543,6 +12558,8 @@ sub stat_file { # $relpath - Current path (relative to top level). # $dirhashref - reference to hash to populate with URLs of directories (Required) # $filehashref - reference to hash to populate with URLs of files (Optional) +# $getlastmod - if true, will set value for each key in innerhash in $filehashref +# to last modification time of file; value set to 1 otherwise. # # Returns: nothing # @@ -12555,7 +12572,8 @@ sub stat_file { # sub recursedirs { - my ($is_home,$recurse,$include,$exclude,$nonemptydir,$addtopdir,$toppath,$relpath,$dirhashref,$filehashref) = @_; + my ($is_home,$recurse,$include,$exclude,$nonemptydir,$addtopdir,$toppath, + $relpath,$dirhashref,$filehashref,$getlastmod) = @_; return unless (ref($dirhashref) eq 'HASH'); my $docroot = $perlvar{'lonDocRoot'}; my $currpath = $docroot.$toppath; @@ -12563,7 +12581,7 @@ sub recursedirs { $currpath .= "/$relpath"; } my ($savefile,$checkinc,$checkexc); - if (ref($filehashref)) { + if (ref($filehashref) eq 'HASH') { $savefile = 1; } if (ref($include) eq 'HASH') { @@ -12586,7 +12604,8 @@ sub recursedirs { } $dirhashref->{&Apache::lonlocal::js_escape($newpath)} = 1; if ($recurse) { - &recursedirs($is_home,$recurse,$include,$exclude,$nonemptydir,$addtopdir,$toppath,$newpath,$dirhashref,$filehashref); + &recursedirs($is_home,$recurse,$include,$exclude,$nonemptydir,$addtopdir, + $toppath,$newpath,$dirhashref,$filehashref,$getlastmod); } } elsif (($savefile) || ($relpath eq '')) { next if ($nonemptydir && $filecount); @@ -12603,10 +12622,16 @@ sub recursedirs { $dirhashref->{'/'} = 1; } if ($savefile) { + my $value; + if ($getlastmod) { + ($value) = (stat("$currpath/$item"))[9]; + } else { + $value = 1; + } if ($relpath eq '') { - $filehashref->{'/'}{$item} = 1; + $filehashref->{'/'}{$item} = $value } else { - $filehashref->{&Apache::lonlocal::js_escape($relpath)}{$item} = 1; + $filehashref->{&Apache::lonlocal::js_escape($relpath)}{$item} = $value; } } $filecount ++; @@ -12615,8 +12640,11 @@ sub recursedirs { closedir($dirh); } } else { - my ($dirlistref,$listerror) = - &dirlist($toppath.$relpath); + my $url = $toppath; + if ($relpath ne '') { + $url = $toppath.'/'.$relpath; + } + my ($dirlistref,$listerror) = &dirlist($url); my @dir_lines; my $dirptr=16384; if (ref($dirlistref) eq 'ARRAY') { @@ -12640,12 +12668,13 @@ sub recursedirs { } $dirhashref->{&Apache::lonlocal::js_escape($newpath)} = 1; if ($recurse) { - &recursedirs($is_home,$recurse,$include,$exclude,$nonemptydir,$addtopdir,$toppath,$newpath,$dirhashref,$filehashref); + &recursedirs($is_home,$recurse,$include,$exclude,$nonemptydir,$addtopdir, + $toppath,$newpath,$dirhashref,$filehashref,$getlastmod); } } elsif (($savefile) || ($relpath eq '')) { next if ($nonemptydir && $filecount); if ($checkinc || $checkexc) { - my $extension; + my ($extension) = ($item =~ /\.(\w+)$/); if ($checkinc) { next unless ($extension && $include->{$extension}); } @@ -12657,10 +12686,16 @@ sub recursedirs { $dirhashref->{'/'} = 1; } if ($savefile) { + my $value; + if ($getlastmod) { + $value = $mtime; + } else { + $value = 1; + } if ($relpath eq '') { - $filehashref->{'/'}{$item} = 1; + $filehashref->{'/'}{$item} = $value; } else { - $filehashref->{&Apache::lonlocal::js_escape($relpath)}{$item} = 1; + $filehashref->{&Apache::lonlocal::js_escape($relpath)}{$item} = $value; } } $filecount ++; @@ -12687,6 +12722,14 @@ sub priv_exclude { }; } +sub res_exclude { + return { + meta => 1, + subscription => 1, + rights => 1, + }; +} + # -------------------------------------------------------- Value of a Condition # gets the value of a specific preevaluated condition @@ -15156,6 +15199,49 @@ sub repcopy_userfile { return 'ok'; } +sub repcopy_crsprivfile { + my ($src,$dest) = @_; + my $result; + if ($src =~ m{^/priv/($match_domain)/($match_courseid)/(.+)$}) { + my ($cdom,$cnum,$filepath) = ($1,$2,$3); + $filepath =~ s/\.{2,}//g; + my $chome = &homeserver($cnum,$cdom); + unless ($chome eq 'no_host') { + my @ids=¤t_machine_ids(); + unless (grep(/^\Q$chome\E$/,@ids)) { + if (&is_course($cdom,$cnum)) { + my $londocroot = $perlvar{'lonDocRoot'}; + if ($dest =~ m{^\Q$londocroot/priv/\E$match_domain/$match_username/.*\Q$filepath\E$}) { + my $cmd = 'crsfilefrompriv:'.&escape($filepath).':'.&escape($cnum).':'.&escape($cdom); + $result = &reply($cmd,$chome); + unless (($result eq 'unknown_cmd') || ($result =~ /^error:/)) { + my $url = &unescape($result); + if ($url =~ m{^https?://[^/]+\Q/userfiles/$cdom/$cnum/priv/$filepath\E$}) { + my $request=new HTTP::Request('GET',$url); + my $response=&LONCAPA::LWPReq::makerequest($chome,$request,'',\%perlvar,1200,1); + if ($response->is_error()) { + $result = 'error: '.$response->status_line; + } else { + if (open(my $fh,'>',$dest)) { + print $fh $response->content; + close($fh); + $result = 'ok'; + } else { + $result = 'error: nowrite'; + } + } + } else { + $result = 'error: invalidurl'; + } + } + } + } + } + } + } + return $result; +} + sub tokenwrapper { my $uri=shift; $uri=~s|^https?\://([^/]+)||;