--- loncom/interface/londocs.pm	2020/01/16 18:14:29	1.484.2.85
+++ loncom/interface/londocs.pm	2024/07/01 18:29:41	1.484.2.94
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Documents
 #
-# $Id: londocs.pm,v 1.484.2.85 2020/01/16 18:14:29 raeburn Exp $
+# $Id: londocs.pm,v 1.484.2.94 2024/07/01 18:29:41 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -177,6 +177,45 @@ sub default_folderpath {
     }
 }
 
+sub validate_folderpath {
+    my ($supplementalflag) = @_;
+    if ($env{'form.folderpath'} ne '') {
+        my @items = split(/\&/,$env{'form.folderpath'});
+        my $badpath;
+        for (my $i=0; $i<@items; $i++) {
+            my $odd = $i%2;
+            if (($odd) && (!$supplementalflag) && ($items[$i] !~ /^[^:]*:(|\d+):(|1):(|1):(|1):(|1)$/)) {
+                $badpath = 1;
+            } elsif ((!$odd) && ($items[$i] !~ /^(default|supplemental)(|_\d+)$/)) {
+                $badpath = 1;
+            }
+            last if ($badpath);
+        }
+        if ($badpath) {
+            delete($env{'form.folderpath'});
+        }
+    }
+    return;
+}
+
+sub validate_suppath {
+    if ($env{'form.supppath'} ne '') {
+        my @items = split(/\&/,$env{'form.supppath'});
+        my $badpath;
+        for (my $i=0; $i<@items; $i++) {
+            my $odd = $i%2;
+            if ((!$odd) && ($items[$i] !~ /^supplemental(|_\d+)$/)) {
+                $badpath = 1;
+            }
+            last if ($badpath);
+        }
+        if ($badpath) {
+            delete($env{'form.supppath'});
+        }
+    }
+    return;
+}
+
 sub dumpcourse {
     my ($r) = @_;
     my $crstype = &Apache::loncommon::course_type();
@@ -676,26 +715,27 @@ sub group_import {
 	    }
 	    my $ext = 'false';
 	    if ($url=~m{^http://} || $url=~m{^https://}) { $ext = 'true'; }
-	    $name = &LONCAPA::map::qtunescape($name);
-            if ($name eq '') {
-                $name = &LONCAPA::map::qtunescape(&mt('Web Page'));
-            }
             if ($url =~ m{^/uploaded/$coursedom/$coursenum/((?:docs|supplemental)/(?:default|\d+))/new\.html$}) {
                 my $filepath = $1;
-                my $fname = $name;
-                if ($fname =~ /^\W+$/) {
+                my $fname;
+                if ($name eq '') {
+                    $name = &mt('Web Page');
                     $fname = 'web';
                 } else {
-                    $fname =~ s/\W/_/g;
-                }
-                if (length($fname) > 15) {
-                    $fname = substr($fname,0,14);
+                    $fname = $name;
+                    $fname=&Apache::lonnet::clean_filename($fname);
+                    if ($fname eq '') {
+                        $fname = 'web';
+                    } elsif (length($fname) > 15) {
+                        $fname = substr($fname,0,14);
+                    }
                 }
+                my $title = &Apache::loncommon::cleanup_html($name);
                 my $initialtext = &mt('Replace with your own content.');
                 my $newhtml = <<END;
 <html>
 <head>
-<title>$name</title>
+<title>$title</title>
 </head>
 <body bgcolor="#ffffff">
 $initialtext
@@ -717,6 +757,7 @@ END
                     return (&mt('Failed to save new web page.'),1);
                 }
             }
+            $name = &LONCAPA::map::qtunescape($name);
             $url  = &LONCAPA::map::qtunescape($url);
 	    $LONCAPA::map::resources[$residx] =
 		join(':', ($name, $url, $ext, 'normal', 'res'));
@@ -1059,13 +1100,19 @@ sub update_paste_buffer {
 # Construct identifiers for current contents of user's paste buffer
     if (@currpaste) {
         foreach my $suffix (@currpaste) {
-             my $cid = $env{'docs.markedcopy_crs_'.$suffix};
-             my $url = $env{'docs.markedcopy_url_'.$suffix};
-             my $mapidx = $env{'docs.markedcopy_map_'.$suffix};
-             if (($cid =~ /^$match_domain(?:_)$match_courseid$/) &&
-                 ($url ne '')) {
-                 $pasteurls{$cid.'_'.$url.'_'.$mapidx} = 1;
-             }
+            my $cid = $env{'docs.markedcopy_crs_'.$suffix};
+            my $url = $env{'docs.markedcopy_url_'.$suffix};
+            my $mapidx = $env{'docs.markedcopy_map_'.$suffix};
+            if (($cid =~ /^$match_domain(?:_)$match_courseid$/) &&
+                ($url ne '')) {
+                if ($url eq '/res/lib/templates/simpleproblem.problem') {
+                    $pasteurls{$cid.'_'.$mapidx} = 1;
+                } elsif ($url =~ m{^/res/$match_domain/$match_username/}) {
+                    $pasteurls{$url} = 1;
+                } else {
+                    $pasteurls{$cid.'_'.$url} = 1;
+                }
+            }
         }
     }
 
@@ -1074,7 +1121,7 @@ sub update_paste_buffer {
 
     my @pathitems = split(/\&/,$env{'form.folderpath'});
     my @folderconf = split(/\:/,$pathitems[-1]);
-    my $ispage = $folderconf[4];
+    my $ispage = $folderconf[5];
 
     foreach my $item (@possibles) {
         my ($orderidx,$cmd) = split(/:/,$item);
@@ -1087,7 +1134,13 @@ sub update_paste_buffer {
                                           $env{'form.folderpath'},\%curr_groups);
         next if ($denied{'copy'});
         $url=~s{http(&colon;|:)//https(&colon;|:)//}{https$2//};
-        next if (exists($pasteurls{$coursedom.'_'.$coursenum.'_'.$mapidx}));
+        if ($url eq '/res/lib/templates/simpleproblem.problem') {
+            next if (exists($pasteurls{$coursedom.'_'.$coursenum.'_'.$mapidx}));
+        } elsif ($url =~ m{^/res/$match_domain/$match_username/}) {
+            next if (exists($pasteurls{$url}));
+        } else {
+            next if (exists($pasteurls{$coursedom.'_'.$coursenum.'_'.$url}));
+        }
         my ($suffix,$errortxt,$locknotfreed) =
             &new_timebased_suffix($env{'user.domain'},$env{'user.name'},'paste');
         if ($suffix ne '') {
@@ -2792,7 +2845,7 @@ sub update_parameter {
             my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]);
             $name=&LONCAPA::map::qtescape($name);
             $url=&LONCAPA::map::qtescape($url);
-            next unless ($name && $url);
+            next unless ($url);
             my $is_map;
             if ($url =~ m{/uploaded/.+\.(page|sequence)$}) {
                 $is_map = 1;
@@ -3874,11 +3927,19 @@ END
     my ($editlink,$extresform,$anchor,$hiddenres,$nomodal);
     my $orig_url = $url;
     $orig_url=~s{http(&colon;|:)//https(&colon;|:)//}{https$2//};
-    $url=~s{^http(|s)(&colon;|:)//}{/adm/wrapper/ext/};
+    if ($container eq 'page') {
+        $url=~s{^http(|s)(&colon;|:)//}{/ext/};
+    } else {
+        $url=~s{^http(|s)(&colon;|:)//}{/adm/wrapper/ext/};
+    }
     if (!$supplementalflag && $residx && $symb) {
         if ((!$isfolder) && (!$ispage)) {
 	    (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
-	    $url=&Apache::lonnet::clutter($url);
+            if (($url =~ m{^ext/}) && ($container eq 'page')) {
+                $url=&Apache::lonnet::clutter_with_no_wrapper($url);
+            } else {
+                $url=&Apache::lonnet::clutter($url);
+            }
 	    if ($url=~/^\/*uploaded\//) {
 	        $url=~/\.(\w+)$/;
 	        my $embstyle=&Apache::loncommon::fileembstyle($1);
@@ -3892,7 +3953,7 @@ END
             } elsif ($url=~m{^(|/adm/wrapper)/ext/([^#]+)}) {
                 my $wrapped = $1;
                 my $exturl = $2;
-                if ($wrapped eq '') {
+                if (($wrapped eq '') && ($container ne 'page')) {
                     $url='/adm/wrapper'.$url;
                 }
                 if (($ENV{'SERVER_PORT'} == 443) && ($exturl !~ /^https:/)) {
@@ -3901,7 +3962,7 @@ END
             } elsif ($url eq "/public/$coursedom/$coursenum/syllabus") {
                 if (($ENV{'SERVER_PORT'} == 443) &&
                     ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {
-                    unless (&Apache::lonnet::uses_sts()) {
+                    unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) {
                         $url .= '?usehttp=1';
                     }
                     $nomodal = 1;
@@ -3910,11 +3971,9 @@ END
             if (&Apache::lonnet::symbverify($symb,$url)) {
                 my $shownsymb = $symb;
                 if ($isexternal) {
-                    if ($url =~ /^([^#]+)#([^#]+)$/) {
-                        $url = $1;
-                        $anchor = $2;
-                        my $escan = &escape('#');
-                        $shownsymb =~ s/^([^\#]+)#([^\#]+)$/$1$escan$2/;
+                    $url =~ s/\#[^#]+$//;
+                    if ($container eq 'page') {
+                        $url = &Apache::lonnet::clutter($url);
                     }
                 }
                 unless ($env{'request.role.adv'}) {
@@ -3968,7 +4027,7 @@ END
                 $url = $1;
                 $anchor = $2;
                 if (($url =~ m{^(|/adm/wrapper)/ext/(?!https:)}) && ($ENV{'SERVER_PORT'} == 443)) {
-                    unless (&Apache::lonnet::uses_sts()) {
+                    unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) {
                         if ($hostname ne '') {
                             $url = 'http://'.$hostname.$url;
                         }
@@ -3980,7 +4039,7 @@ END
         } elsif ($url =~ m{^\Q/public/$coursedom/$coursenum/syllabus\E}) {
             if (($ENV{'SERVER_PORT'} == 443) &&
                 ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {
-                unless (&Apache::lonnet::uses_sts()) {
+                unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) {
                     if ($hostname ne '') {
                         $url = 'http://'.$hostname.$url;
                     }
@@ -4531,7 +4590,7 @@ sub contentverifyform {
               &mt('No').'</label>'.('&nbsp;'x2).
               '<label><input type="radio" name="checkstale" value="1" />'.
               &mt('Yes').'</label></span></p><p>'.
-              '<input type="submit" value="'.&mt('Verify content').' "/>'.
+              '<input type="submit" value="'.&mt('Verify Content').' "/>'.
               '<input type="hidden" value="1" name="tools" />'.
               '<input type="hidden" value="1" name="verify" /></p></form>');
     $r->print(&endContentScreen());
@@ -5119,35 +5178,11 @@ sub handler {
     if ($env{'form.tools'}) { $toolsflag=1; }
 
     if ($env{'form.folderpath'} ne '') {
-        my @items = split(/\&/,$env{'form.folderpath'});
-        my $badpath;
-        for (my $i=0; $i<@items; $i++) {
-            my $odd = $i%2;
-            if (($odd) && (!$supplementalflag) && ($items[$i] !~ /^[^:]*:(|\d+):(|1):(|1):(|1):(|1)$/)) {
-                $badpath = 1;
-            } elsif ((!$odd) && ($items[$i] !~ /^(default|supplemental)(|_\d+)$/)) {
-                $badpath = 1;
-            }
-            last if ($badpath);
-        }
-        if ($badpath) {
-            delete($env{'form.folderpath'});
-        }
+        &validate_folderpath($supplementalflag);
     }
 
     if ($env{'form.supppath'} ne '') {
-        my @items = split(/\&/,$env{'form.supppath'});
-        my $badpath;
-        for (my $i=0; $i<@items; $i++) {
-            my $odd = $i%2;
-            if ((!$odd) && ($items[$i] !~ /^supplemental(|_\d+)$/)) {
-                $badpath = 1;
-            }
-            last if ($badpath);
-        }
-        if ($badpath) {
-            delete($env{'form.supppath'});
-        }
+        &validate_suppath();
     }
 
     my $script='';
@@ -5205,6 +5240,9 @@ sub handler {
         } else {
             undef($env{'form.folderpath'});
         }
+        if ($env{'form.folderpath'} ne '') {
+            &validate_folderpath($supplementalflag);
+        }
     }
    
 # If we are not allowed to make changes, all we can see are supplemental docs
@@ -5229,7 +5267,7 @@ sub handler {
             undef($env{'form.folderpath'});
         } else {
             $folderurl = "uploaded/$coursedom/$coursenum/$folder";
-            if ((split(/\:/,$pathitems[-1]))[4]) {
+            if ((split(/\:/,$pathitems[-1]))[5]) {
                 $folderurl .= '.page';
             } else {
                 $folderurl .= '.sequence';
@@ -5690,6 +5728,7 @@ HIDDENFORM
 #
 
     my $savefolderpath;
+    my $hostname = $r->hostname();
 
     if ($allowed) {
        my $folder=$env{'form.folder'};
@@ -5881,13 +5920,19 @@ NSYLFORM
 	$help{'Group Portfolio'}
 	</form>
 NGFFORM
-	@specialdocumentsforma=(
+        if ($container eq 'page') {
+            @specialdocumentsforma=(
+        {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/webpage.png" alt="'.$lt{webp}.'" onclick="javascript:makewebpage();" />'=>$newwebpageform},
+            );
+        } else {
+	    @specialdocumentsforma=(
 	{'<img class="LC_noBorder LC_middle" src="/res/adm/pages/page.png" alt="'.$lt{newp}.'"  onclick="javascript:makenewpage(document.newpage,\''.$pageseq.'\');" />'=>$newpageform},
 	{'<img class="LC_noBorder LC_middle" src="/res/adm/pages/syllabus.png" alt="'.$lt{syll}.'" onclick="javascript:makenew(document.newsyl);" />'=>$newsylform},
 	{'<img class="LC_noBorder LC_middle" src="/res/adm/pages/navigation.png" alt="'.$lt{navc}.'" onclick="javascript:makenew(document.newnav);" />'=>$newnavform},
         {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simple.png" alt="'.$lt{sipa}.'" onclick="javascript:makesmppage();" />'=>$newsmppageform},
         {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/webpage.png" alt="'.$lt{webp}.'" onclick="javascript:makewebpage();" />'=>$newwebpageform},
-        );
+            );
+        }
         $specialdocumentsform = &create_form_ul(&create_list_elements(@specialdocumentsforma));
 
 
@@ -5925,11 +5970,11 @@ my %orderhash = (
                 'aa' => ['Upload',$fileuploadform],
                 'bb' => ['Import',$importpubform],
                 'cc' => ['Grading',$gradingform],
+                'ee' => ['Other',$specialdocumentsform],
                 );
 unless ($container eq 'page') {
     $orderhash{'00'} = ['Newfolder',$newfolderform];
     $orderhash{'dd'} = ['Collaboration',$communityform];
-    $orderhash{'ee'} = ['Other',$specialdocumentsform];
 }
 
  $hadchanges=0;
@@ -6557,7 +6602,7 @@ sub editing_js {
                 if ($backtourl =~ m{^\Q/public/$coursedom/$coursenum/syllabus\E}) {
                     if (($ENV{'SERVER_PORT'} == 443) &&
                         ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {
-                        unless (&Apache::lonnet::uses_sts()) {
+                        unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) {
                             if ($hostname ne '') {
                                 $backtourl = 'http://'.$hostname.$backtourl;
                             }
@@ -6566,7 +6611,7 @@ sub editing_js {
                     }
                 } elsif ($backtourl =~ m{^/adm/wrapper/ext/(?!https:)}) {
                     if (($ENV{'SERVER_PORT'} == 443) && ($hostname ne '')) {
-                        unless (&Apache::lonnet::uses_sts()) {
+                        unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) {
                             if ($hostname ne '') {
                                 $backtourl = 'http://'.$hostname.$backtourl;
                             }
@@ -6604,7 +6649,7 @@ sub editing_js {
 function makenewfolder(targetform,folderseq) {
     var foldername=prompt('$js_lt{"p_mnf"}','$js_lt{"t_mnf"}');
     if (foldername) {
-       targetform.importdetail.value=escape(foldername)+"="+folderseq;
+       targetform.importdetail.value=encodeURIComponent(foldername)+"="+folderseq;
         targetform.submit();
     }
 }
@@ -6612,7 +6657,7 @@ function makenewfolder(targetform,folder
 function makenewpage(targetform,folderseq) {
     var pagename=prompt('$js_lt{"p_mnp"}','$js_lt{"t_mnp"}');
     if (pagename) {
-        targetform.importdetail.value=escape(pagename)+"="+folderseq;
+        targetform.importdetail.value=encodeURIComponent(pagename)+"="+folderseq;
         targetform.submit();
     }
 }
@@ -6621,7 +6666,7 @@ function makeexamupload() {
    var title=prompt('$js_lt{"p_mxu"}');
    if (title) {
     this.document.forms.newexamupload.importdetail.value=
-	escape(title)+'=/res/lib/templates/examupload.problem';
+	encodeURIComponent(title)+'=/res/lib/templates/examupload.problem';
     this.document.forms.newexamupload.submit();
    }
 }
@@ -6630,7 +6675,7 @@ function makesmppage() {
    var title=prompt('$js_lt{"p_msp"}');
    if (title) {
     this.document.forms.newsmppg.importdetail.value=
-	escape(title)+'=/adm/$udom/$uname/new/smppg';
+	encodeURIComponent(title)+'=/adm/$udom/$uname/new/smppg';
     this.document.forms.newsmppg.submit();
    }
 }
@@ -6645,7 +6690,7 @@ function makewebpage(type) {
    }
    if (title) {
        var webpage = formname.importdetail.value;
-       formname.importdetail.value = escape(title)+'='+webpage;
+       formname.importdetail.value = encodeURIComponent(title)+'='+webpage;
        formname.submit();
    }
 }
@@ -6654,7 +6699,7 @@ function makesmpproblem() {
    var title=prompt('$js_lt{"p_msb"}');
    if (title) {
     this.document.forms.newsmpproblem.importdetail.value=
-	escape(title)+'=/res/lib/templates/simpleproblem.problem';
+	encodeURIComponent(title)+'=/res/lib/templates/simpleproblem.problem';
     this.document.forms.newsmpproblem.submit();
    }
 }
@@ -6663,7 +6708,7 @@ function makedropbox() {
    var title=prompt('$js_lt{"p_mdb"}');
    if (title) {
     this.document.forms.newdropbox.importdetail.value=
-        escape(title)+'=/res/lib/templates/DropBox.problem';
+        encodeURIComponent(title)+'=/res/lib/templates/DropBox.problem';
     this.document.forms.newdropbox.submit();
    }
 }
@@ -6672,7 +6717,7 @@ function makebulboard() {
    var title=prompt('$js_lt{"p_mbb"}');
    if (title) {
     this.document.forms.newbul.importdetail.value=
-	escape(title)+'=/adm/$udom/$uname/new/bulletinboard';
+	encodeURIComponent(title)+'=/adm/$udom/$uname/new/bulletinboard';
     this.document.forms.newbul.submit();
    }
 }