--- loncom/lonnet/perl/lonnet.pm	2023/07/09 00:49:22	1.1172.2.146.2.13
+++ loncom/lonnet/perl/lonnet.pm	2024/02/28 05:40:11	1.1172.2.146.2.19
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1172.2.146.2.13 2023/07/09 00:49:22 raeburn Exp $
+# $Id: lonnet.pm,v 1.1172.2.146.2.19 2024/02/28 05:40:11 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2510,11 +2510,11 @@ sub get_domain_defaults {
          &Apache::lonnet::get_dom('configuration',['defaults','quotas',
                                   'requestcourses','inststatus',
                                   'coursedefaults','usersessions',
-                                  'requestauthor','selfenrollment',
-                                  'coursecategories','autoenroll',
-                                  'helpsettings','wafproxy','ltisec',
-                                  'toolsec','domexttool','exttool'],
-                                  $domain);
+                                  'requestauthor','authordefaults',
+                                  'selfenrollment','coursecategories',
+                                  'autoenroll','helpsettings',
+                                  'wafproxy','ltisec','toolsec',
+                                  'domexttool','exttool'],$domain);
     my @coursetypes = ('official','unofficial','community','textbook');
     if (ref($domconfig{'defaults'}) eq 'HASH') {
         $domdefaults{'lang_def'} = $domconfig{'defaults'}{'lang_def'}; 
@@ -2555,6 +2555,17 @@ sub get_domain_defaults {
             $domdefaults{$item} = $domconfig{'requestcourses'}{$item};
         }
     }
+    if (ref($domconfig{'authordefaults'}) eq 'HASH') {
+        foreach my $item ('nocodemirror','copyright','sourceavail','domcoordacc','editors') {
+            if ($item eq 'editors') {
+                if (ref($domconfig{'authordefaults'}{'editors'}) eq 'ARRAY') {
+                    $domdefaults{$item} = join(',',@{$domconfig{'authordefaults'}{'editors'}});
+                }
+            } else {
+                $domdefaults{$item} = $domconfig{'authordefaults'}{$item};
+            }
+        }
+    }
     if (ref($domconfig{'requestauthor'}) eq 'HASH') {
         $domdefaults{'requestauthor'} = $domconfig{'requestauthor'};
     }
@@ -2579,6 +2590,9 @@ sub get_domain_defaults {
             if (ref($domconfig{'coursedefaults'}{'uploadquota'}) eq 'HASH') {
                 $domdefaults{$type.'quota'} = $domconfig{'coursedefaults'}{'uploadquota'}{$type};
             }
+            if (ref($domconfig{'coursedefaults'}{'coursequota'}) eq 'HASH') {
+                $domdefaults{$type.'coursequota'} = $domconfig{'coursedefaults'}{'coursequota'}{$type};
+            }
             if ($domdefaults{'postsubmit'} eq 'on') {
                 if (ref($domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {
                     $domdefaults{$type.'postsubtimeout'} =
@@ -2693,6 +2707,17 @@ sub get_domain_defaults {
                 $domdefaults{'ltiprivhosts'} = $domconfig{'ltisec'}{'private'}{'keys'};
             }
         }
+        if (ref($domconfig{'ltisec'}{'suggested'}) eq 'HASH') {
+            my %suggestions = %{$domconfig{'ltisec'}{'suggested'}};
+            foreach my $item (keys(%{$domconfig{'ltisec'}{'suggested'}})) {
+                unless (ref($domconfig{'ltisec'}{'suggested'}{$item}) eq 'HASH') {
+                    delete($suggestions{$item});
+                }
+            }
+            if (keys(%suggestions)) {
+                $domdefaults{'linkprotsuggested'} = \%suggestions;
+            }
+        }
     }
     if (ref($domconfig{'toolsec'}) eq 'HASH') {
         if (ref($domconfig{'toolsec'}{'encrypt'}) eq 'HASH') {
@@ -5175,6 +5200,36 @@ sub courserolelog {
             $storehash{'group'} = $sec;
         } else {
             $storehash{'section'} = $sec;
+            my ($curruserdomstr,$newuserdomstr);
+            if (exists($env{'course.'.$cdom.'_'.$cnum.'.internal.userdomains'})) {
+                $curruserdomstr = $env{'course.'.$env{'request.course.id'}.'.internal.userdomains'};
+            } else {
+                my %courseinfo = &coursedescription($cdom.'/'.$cnum);
+                $curruserdomstr = $courseinfo{'internal.userdomains'};
+            }
+            if ($curruserdomstr ne '') {
+                my @udoms = split(/,/,$curruserdomstr);
+                unless (grep(/^\Q$domain\E/,@udoms)) {
+                    push(@udoms,$domain);
+                    $newuserdomstr = join(',',sort(@udoms));
+                }
+            } else {
+                $newuserdomstr = $domain;
+            }
+            if ($newuserdomstr ne '') {
+                my $putresult = &put('environment',{ 'internal.userdomains' => $newuserdomstr },
+                                     $cdom,$cnum);
+                if ($putresult eq 'ok') {
+                    unless (($selfenroll) || ($context eq 'selfenroll')) {
+                        if (($context eq 'createcourse') || ($context eq 'requestcourses') ||
+                            ($context eq 'automated') || ($context eq 'domain')) {
+                            $env{'course.'.$cdom.'_'.$cnum.'.internal.userdomains'} = $newuserdomstr;
+                        } elsif ($env{'request.course.id'} eq $cdom.'_'.$cnum) {
+                            &appenv({'course.'.$cdom.'_'.$cnum.'.internal.userdomains' => $newuserdomstr});
+                        }
+                    }
+                }
+            }
         }
         &write_log('course',$namespace,\%storehash,$delflag,$username,
                    $domain,$cnum,$cdom);
@@ -6683,7 +6738,7 @@ sub rolesinit {
     my %firstaccess = &dump('firstaccesstimes', $domain, $username);
     my %timerinterval = &dump('timerinterval', $domain, $username);
     my (%coursetimerstarts, %firstaccchk, %firstaccenv, %coursetimerintervals,
-        %timerintchk, %timerintenv);
+        %timerintchk, %timerintenv,%coauthorenv);
 
     foreach my $key (keys(%firstaccess)) {
         my ($cid, $rest) = split(/\0/, $key);
@@ -6697,6 +6752,7 @@ sub rolesinit {
 
     my %allroles=();
     my %allgroups=();
+    my %gotcoauconfig=();
 
     for my $area (grep { ! /^rolesdef_/ } keys(%rolesdump)) {
         my $role = $rolesdump{$area};
@@ -6748,6 +6804,23 @@ sub rolesinit {
         } else {
         # Normal role, defined in roles.tab
             &standard_roleprivs(\%allroles,$trole,$tdomain,$spec,$trest,$area);
+            if (($trole eq 'ca') || ($trole eq 'aa')) {
+                (undef,my ($audom,$auname)) = split(/\//,$area);
+                unless ($gotcoauconfig{$area}) {
+                    my @ca_settings = ('authoreditors');
+                    my %info = &userenvironment($audom,$auname,@ca_settings);
+                    $gotcoauconfig{$area} = 1;
+                    foreach my $item (@ca_settings) {
+                        if (exists($info{$item})) {
+                            my $name = $item;
+                            if ($item eq 'authoreditors') {
+                                $name = 'editors';
+                            }
+                            $coauthorenv{"environment.internal.$name.$area"} = $info{$item};
+                        }
+                    }
+                }
+            }
         }
 
         my $cid = $tdomain.'_'.$trest;
@@ -6776,7 +6849,7 @@ sub rolesinit {
     $env{'user.adv'} = $userroles{'user.adv'};
     $env{'user.rar'} = $userroles{'user.rar'};
 
-    return (\%userroles,\%firstaccenv,\%timerintenv);
+    return (\%userroles,\%firstaccenv,\%timerintenv,\%coauthorenv);
 }
 
 sub set_arearole {
@@ -7924,11 +7997,14 @@ sub usertools_access {
         %tools = (
                       requestauthor => 1,
                  );
+    } elsif ($context eq 'authordefaults') {
+        %tools = (
+                      webdav    => 1,
+                 );
     } else {
         %tools = (
                       aboutme   => 1,
                       blog      => 1,
-                      webdav    => 1,
                       portfolio => 1,
                       timezone  => 1,
                  );
@@ -7946,6 +8022,10 @@ sub usertools_access {
                 return $env{'environment.canrequest.'.$tool};
             } elsif ($context eq 'requestauthor') {
                 return $env{'environment.canrequest.author'};
+            } elsif ($context eq 'authordefaults') {
+                if ($tool eq 'webdav') {
+                    return $env{'environment.availabletools.'.$tool};
+                }
             } else {
                 return $env{'environment.availabletools.'.$tool};
             }
@@ -7955,6 +8035,10 @@ sub usertools_access {
     my ($toolstatus,$inststatus,$envkey);
     if ($context eq 'requestauthor') {
         $envkey = $context;
+    } elsif ($context eq 'authordefaults') {
+        if ($tool eq 'webdav') {
+            $envkey = 'tools.'.$tool;
+        }
     } else {
         $envkey = $context.'.'.$tool;
     }
@@ -8839,7 +8923,7 @@ sub constructaccess {
     my ($ownername,$ownerdomain,$ownerhome);
 
     ($ownerdomain,$ownername) =
-        ($url=~ m{^(?:\Q$perlvar{'lonDocRoot'}\E|)/priv/($match_domain)/($match_username)(?:/|$)});
+        ($url=~ m{^(?:\Q$perlvar{'lonDocRoot'}\E|)(?:/daxepage|/daxeopen)?/priv/($match_domain)/($match_username)(?:/|$)});
 
 # The URL does not really point to any authorspace, forget it
     unless (($ownername) && ($ownerdomain)) { return ''; }
@@ -12092,6 +12176,73 @@ sub domainlti_itemid {
     return $itemid;
 }
 
+sub get_ltitools_id {
+    my ($context,$cdom,$cnum,$title) = @_;
+    my ($lockhash,$tries,$gotlock,$id,$error);
+
+    # get lock on ltitools db
+    $lockhash = {
+                   lock => $env{'user.name'}.
+                           ':'.$env{'user.domain'},
+                };
+    $tries = 0;
+    if ($context eq 'domain') {
+        $gotlock = &newput_dom('ltitools',$lockhash,$cdom);
+    } else {
+        $gotlock = &newput('ltitools',$lockhash,$cdom,$cnum);
+    }
+    while (($gotlock ne 'ok') && ($tries<10)) {
+        $tries ++;
+        sleep (0.1);
+        if ($context eq 'domain') {
+            $gotlock = &newput_dom('ltitools',$lockhash,$cdom);
+        } else {
+            $gotlock = &newput('ltitools',$lockhash,$cdom,$cnum);
+        }
+    }
+    if ($gotlock eq 'ok') {
+        my %currids;
+        if ($context eq 'domain') {
+            %currids = &dump_dom('ltitools',$cdom);
+        } else {
+            %currids = &dump('ltitools',$cdom,$cnum);
+        }
+        if ($currids{'lock'}) {
+            delete($currids{'lock'});
+            if (keys(%currids)) {
+                my @curr = sort { $a <=> $b } keys(%currids);
+                if ($curr[-1] =~ /^\d+$/) {
+                    $id = 1 + $curr[-1];
+                }
+            } else {
+                $id = 1;
+            }
+            if ($id) {
+                if ($context eq 'domain') {
+                    unless (&newput_dom('ltitools',{ $id => $title },$cdom) eq 'ok') {
+                        $error = 'nostore';
+                    }
+                } else {
+                    unless (&newput('ltitools',{ $id => $title },$cdom,$cnum) eq 'ok') {
+                        $error = 'nostore';
+                    }
+                }
+            } else {
+                $error = 'nonumber';
+            }
+        }
+        my $dellockoutcome;
+        if ($context eq 'domain') {
+            $dellockoutcome = &del_dom('ltitools',['lock'],$cdom);
+        } else {
+            $dellockoutcome = &del('ltitools',['lock'],$cdom,$cnum);
+        }
+    } else {
+        $error = 'nolock';
+    }
+    return ($id,$error);
+}
+
 sub count_supptools {
     my ($cnum,$cdom,$ignorecache,$reload)=@_;
     my $hashid=$cnum.':'.$cdom;