--- loncom/lonnet/perl/lonnet.pm 2024/11/21 07:26:02 1.1530
+++ loncom/lonnet/perl/lonnet.pm 2025/03/19 14:44:04 1.1537
@@ -1,7 +1,7 @@
# The LearningOnline Network
# TCP networking package
#
-# $Id: lonnet.pm,v 1.1530 2024/11/21 07:26:02 raeburn Exp $
+# $Id: lonnet.pm,v 1.1537 2025/03/19 14:44:04 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -228,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);
@@ -3019,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;
@@ -3731,6 +3734,7 @@ sub ssi_body {
$output=~s|//(\s*)?\s||gs;
$output=~s/^.*?\
]*\>//si;
$output=~s/\<\/body\s*\>.*?$//si;
+ $output=~s{\Q\E}{
}gs;
if (wantarray) {
return ($output, $response);
} else {
@@ -6167,7 +6171,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);
@@ -6749,7 +6753,7 @@ sub store {
# -------------------------------------------------------------- Critical Store
sub cstore {
- my ($storehash,$symb,$namespace,$domain,$stuname,$laststore,$ip,$nolog) = @_;
+ my ($storehash,$symb,$namespace,$domain,$stuname,$laststore) = @_;
my $home='';
if ($stuname) { $home=&homeserver($stuname,$domain); }
@@ -6774,11 +6778,7 @@ sub cstore {
}
if (!$home) { $home=$env{'user.home'}; }
- if ($ip ne '') {
- $$storehash{'ip'} = $ip;
- } else {
- $$storehash{'ip'} = &get_requestor_ip();
- }
+ $$storehash{'ip'} = &get_requestor_ip();
$$storehash{'host'}=$perlvar{'lonHostID'};
my $namevalue='';
@@ -6786,9 +6786,7 @@ sub cstore {
$namevalue.=&escape($key).'='.&freeze_escape($$storehash{$key}).'&';
}
$namevalue=~s/\&$//;
- unless ($nolog) {
- &courselog($symb.':'.$stuname.':'.$domain.':CSTORE:'.$namevalue);
- }
+ &courselog($symb.':'.$stuname.':'.$domain.':CSTORE:'.$namevalue);
return critical
("store:$domain:$stuname:$namespace:$symb:$namevalue:$laststore","$home");
}
@@ -7530,6 +7528,27 @@ sub set_adhoc_privileges {
if (&allowed('adv') eq 'F') { $tadv=1; }
&appenv({'request.role.adv' => $tadv});
}
+ if ($role eq 'ca') {
+ my @ca_settings = ('authoreditors','coauthorlist');
+ my %info = &userenvironment($dcdom,$pickedcourse,@ca_settings);
+ foreach my $item (@ca_settings) {
+ if (exists($info{$item})) {
+ my $name = $item;
+ if ($item eq 'authoreditors') {
+ $name = 'editors';
+ unless ($info{'authoreditors'}) {
+ my %domdefs = &get_domain_defaults($dcdom);
+ if ($domdefs{$name} ne '') {
+ $info{'authoreditors'} = $domdefs{$name};
+ } else {
+ $info{'authoreditors'} = 'edit,xml';
+ }
+ }
+ }
+ &appenv({"environment.internal.$name./$dcdom/$pickedcourse" => $info{$item}});
+ }
+ }
+ }
}
# --------------------------------------------------------------- get interface
@@ -10415,7 +10434,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);
@@ -10497,7 +10516,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);
@@ -11690,7 +11709,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') {
@@ -11702,7 +11721,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='';
@@ -12557,6 +12580,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
#
@@ -12569,7 +12594,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;
@@ -12577,7 +12603,7 @@ sub recursedirs {
$currpath .= "/$relpath";
}
my ($savefile,$checkinc,$checkexc);
- if (ref($filehashref)) {
+ if (ref($filehashref) eq 'HASH') {
$savefile = 1;
}
if (ref($include) eq 'HASH') {
@@ -12600,7 +12626,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);
@@ -12617,10 +12644,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 ++;
@@ -12629,8 +12662,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') {
@@ -12654,12 +12690,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});
}
@@ -12671,10 +12708,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 ++;
@@ -12701,6 +12744,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
@@ -15066,6 +15117,9 @@ sub whichuser {
$courseid=$tmp_courseid;
($domain)=&get_env_multiple('form.grade_domain');
($name)=&get_env_multiple('form.grade_username');
+ if ($name eq 'public' && $domain eq 'public') {
+ $publicuser = 1;
+ }
return ($symb,$courseid,$domain,$name,$publicuser);
}
}
@@ -15082,6 +15136,7 @@ sub whichuser {
$env{'form.username'}.=time.rand(10000000);
}
$name.=$env{'form.username'};
+ $publicuser = 1;
}
return ($symb,$courseid,$domain,$name,$publicuser);
@@ -15170,6 +15225,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?\://([^/]+)||;