--- loncom/interface/londocs.pm	2020/03/06 18:53:27	1.669
+++ loncom/interface/londocs.pm	2022/10/19 00:03:10	1.682
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Documents
 #
-# $Id: londocs.pm,v 1.669 2020/03/06 18:53:27 raeburn Exp $
+# $Id: londocs.pm,v 1.682 2022/10/19 00:03:10 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -91,7 +91,7 @@ sub storemap {
 
     if ($map =~ /^default/) {
         $hadchanges=1;
-    } else {
+    } elsif ($contentchg) {
         $suppchanges=1;
     }
     return ($errtext,0);
@@ -183,6 +183,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();
@@ -833,26 +872,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
@@ -874,6 +914,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'));
@@ -914,7 +955,6 @@ END
         &storemap($coursenum, $coursedom, $folder.'.'.$container,1);
     unless ($fatal) {
         if ($folder =~ /^supplemental/) {
-            &Apache::lonnet::get_numsuppfiles($coursenum,$coursedom,1);
             my ($errtext,$fatal) = &mapread($coursenum,$coursedom,
                                             $folder.'.'.$container);
         }
@@ -1454,7 +1494,7 @@ sub print_paste_buffer {
             }
             $pasteitems .= '<label><input type="checkbox" name="pasting" id="pasting_'.$suffix.'" value="'.$suffix.'" '.$onclick.'/>'.$buffer.'</label>';
             if ($nopaste) {
-                 $pasteitems .= $nopaste;   
+                 $pasteitems .= ' <span class="LC_cusr_emph">'.$nopaste.'</span>';   
             } else {
                 if ($othercrs) {
                     $pasteitems .= $othercrs;
@@ -2759,6 +2799,15 @@ sub apply_fixups {
             $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/;
         }
         my $mapcontent = &Apache::lonnet::getfile($key);
+        if (($mapcontent eq '-1') && ($before{'map'} eq 'supplemental') &&
+            ($after{'map'} eq 'default') &&
+            ($key =~ m{^/uploaded/$match_domain/$match_courseid/supplemental_\d+\.sequence$})) {
+            $mapcontent = '<map>'."\n".
+                          '<resource id="1" src="" type="start" />'."\n".
+                          '<link from="1" to="2" index="1" />'."\n".
+                          '<resource id="2" src="" type="finish" />'."\n".
+                          '</map>';
+        }
         if ($mapcontent eq '-1') {
             if (ref($errors) eq 'HASH') {
                 $errors->{$key} = 1;
@@ -3228,11 +3277,28 @@ sub editor {
         return $errtext if ($fatal);
     }
 
+    my (%supphidden,%suppids,$suppmapid);
+
     if ($#LONCAPA::map::order<1) {
 	my $idx=&LONCAPA::map::getresidx();
 	if ($idx<=0) { $idx=1; }
        	$LONCAPA::map::order[0]=$idx;
         $LONCAPA::map::resources[$idx]='';
+    } elsif ($supplementalflag && !$allowed) {
+        my ($supplemental) = &Apache::lonnet::get_supplemental($coursenum,$coursedom);
+        if (ref($supplemental) eq 'HASH') {
+            if (ref($supplemental->{'hidden'}) eq 'HASH') {
+                %supphidden = %{$supplemental->{'hidden'}};
+            }
+            if (ref($supplemental->{'ids'}) eq 'HASH') {
+                %suppids = %{$supplemental->{'ids'}};
+            }
+        }
+        if ($folder eq 'supplemental') {
+            $suppmapid = 0;
+        } elsif ($folder =~ /^supplemental_(\d+)$/) {
+            $suppmapid = $1;
+        }
     }
 
 # ------------------------------------------------------------ Process commands
@@ -3516,11 +3582,15 @@ sub editor {
             push(@allmapidx,$res);
         }
 
+        if (($supplementalflag) && (!$allowed) && (!$env{'request.role.adv'})) {
+            next if ($supphidden{$suppmapid.':'.$res});
+        }
         $output .= &entryline($idx,$name,$url,$folder,$allowed,$res,
                               $coursenum,$coursedom,$crstype,
                               $pathitem,$supplementalflag,$container,
                               \%filters,\%curr_groups,$ltitoolsref,$canedit,
-                              $isencrypted,$navmapref,$hostname);
+                              $isencrypted,$navmapref,$hostname,
+                              \%supphidden,\%suppids,$suppmapid);
         $idx++;
         $shown++;
     }
@@ -3529,10 +3599,14 @@ sub editor {
     my $need_save;
     if ($allowed || ($supplementalflag && $folder eq 'supplemental')) {
         my $toolslink;
-        if ($allowed) {
+        if ($allowed || $canedit) {
+            my $helpitem = 'Navigation_Screen';
+            if (!$allowed) {
+                $helpitem = 'Supplemental_Navigation';
+            }
             $toolslink = '<table><tr><td>'
                        .&Apache::loncommon::help_open_menu('Navigation Screen',
-                                                           'Navigation_Screen',undef,'RAT')
+                                                           $helpitem,undef,'RAT')
                        .'</td><td class="LC_middle">'.&mt('Tools:').'</td>'
                        .'<td align="left"><ul id="LC_toolbar">'
                        .'<li><a href="/adm/coursedocs?forcesupplement=1&amp;command=editsupp" '
@@ -3548,11 +3622,9 @@ sub editor {
                           .&Apache::loncommon::start_data_table_header_row()
                           .'<th colspan="2">'.&mt('Move').'</th>'
                           .'<th colspan="3">'.&mt('Actions').'</th>'
-                          .'<th>'.&mt('Document').'</th>';
-                if ($folder !~ /^supplemental/) {
-                    $to_show .= '<th colspan="2">'.&mt('Settings').'</th>';
-                }
-                $to_show .= &Apache::loncommon::end_data_table_header_row();
+                          .'<th>'.&mt('Document').'</th>'
+                          .'<th colspan="2">'.&mt('Settings').'</th>'
+                          .&Apache::loncommon::end_data_table_header_row();
                 if ($folder !~ /^supplemental/) {
                     $lists{'canhide'} = join(',',@allidx);
                     $lists{'canrandomlyorder'} = join(',',@allmapidx);
@@ -3900,7 +3972,8 @@ sub is_supplemental_title {
 sub entryline {
     my ($index,$title,$url,$folder,$allowed,$residx,$coursenum,$coursedom,
         $crstype,$pathitem,$supplementalflag,$container,$filtersref,$currgroups,
-        $ltitoolsref,$canedit,$isencrypted,$navmapref,$hostname)=@_;
+        $ltitoolsref,$canedit,$isencrypted,$navmapref,$hostname,
+        $supphidden,$suppids,$suppmapid)=@_;
     my ($foldertitle,$renametitle,$oldtitle);
     if (&is_supplemental_title($title)) {
 	($title,$foldertitle,$renametitle) = &Apache::loncommon::parse_supplemental_title($title);
@@ -3927,7 +4000,7 @@ sub entryline {
     my $line=&Apache::loncommon::start_data_table_row();
     my ($form_start,$form_end,$form_common,$form_param);
 # Edit commands
-    my ($esc_path, $path, $symb, $curralias);
+    my ($esc_path, $path, $symb, $shownsymb, $curralias);
     if ($env{'form.folderpath'}) {
 	$esc_path=&escape($env{'form.folderpath'});
 	$path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
@@ -4194,41 +4267,16 @@ 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;
                 }
             }
-            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/;
-                    }
-                    if ($container eq 'page') {
-                        $url = &Apache::lonnet::clutter($url);
-                    }
-                }
-                unless ($env{'request.role.adv'}) {
-                    if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) {
-                        $url = '';
-                    }
-                    if (&Apache::lonnet::EXT('resource.0.hiddenresource',$symb) =~ /^yes$/i) {
-                        $url = '';
-                        $hiddenres = 1;
-                    }
-                }
-                if ($url ne '') {
-                    $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($shownsymb);
-                }
-            } elsif (!$env{'request.role.adv'}) {
-                my $checkencrypt;
+            my ($checkencrypt,$shownurl);
+            if (!$env{'request.role.adv'}) {
                 if (((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i) ||
-                      $isencrypted || (&Apache::lonnet::EXT('resource.0.encrypturl',$symb) =~ /^yes$/i)) {
+                    ($isencrypted) || (&Apache::lonnet::EXT('resource.0.encrypturl',$symb) =~ /^yes$/i)) {
                     $checkencrypt = 1;
                 } elsif (ref($navmapref)) {
                     unless (ref($$navmapref)) {
@@ -4236,26 +4284,43 @@ END
                     }
                     if (ref($$navmapref)) {
                         if (lc($$navmapref->get_mapparam($symb,undef,"0.encrypturl")) eq 'yes') {
-                            $checkencrypt = 1;       
+                            $checkencrypt = 1;
                         }
                     }
                 }
-                if ($checkencrypt) {
-                    my $shownsymb = &Apache::lonenc::encrypted($symb);
-                    my $shownurl = &Apache::lonenc::encrypted($url);
-                    if (&Apache::lonnet::symbverify($shownsymb,$shownurl)) {
-                        $url = $shownurl.(($shownurl=~/\?/)?'&':'?').'symb='.&escape($shownsymb);
-                        if ($env{'request.enc'} ne '') {
-                            delete($env{'request.enc'});
-                        }
-                    } else {
-                        $url='';
-                    }
+            }
+            if ($checkencrypt) {
+                my $currenc = $env{'request.enc'};
+                $env{'request.enc'} = 1;
+                $shownsymb = &Apache::lonenc::encrypted($symb);
+                $shownurl = &Apache::lonenc::encrypted($url);
+                if (&Apache::lonnet::symbverify($symb,$url)) {
+                    $url = $shownurl;
                 } else {
-                    $url='';
+                    $url = '';
                 }
-            } else {
-                $url='';
+                $env{'request.enc'} = $currenc;
+            } elsif (&Apache::lonnet::symbverify($symb,$url)) {
+                $shownsymb = $symb;
+                if ($isexternal) {
+                    $url =~ s/\#[^#]+$//;
+                    if ($container eq 'page') {
+                        $url = &Apache::lonnet::clutter($url);
+                    }
+                }
+                $shownurl = $url;
+            }
+            unless ($env{'request.role.adv'}) {
+                if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) {
+                    $url = '';
+                }
+                if (&Apache::lonnet::EXT('resource.0.hiddenresource',$symb) =~ /^yes$/i) {
+                    $url = '';
+                    $hiddenres = 1;
+                }
+            }
+            if ($url ne '') {
+                $url = $shownurl.(($shownurl=~/\?/)?'&':'?').'symb='.&escape($shownsymb);
             }
 	}
     } elsif ($supplementalflag) {
@@ -4264,7 +4329,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;
                         }
@@ -4276,7 +4341,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;
                     }
@@ -4295,6 +4360,11 @@ END
         if (!$allowed && $supplementalflag) {
             $folderpath.=$containerarg.'&'.$foldername;
             $url.='folderpath='.&escape($folderpath);
+            if (ref($supphidden) eq 'HASH') {
+                if ($supphidden->{$suppmapid.':'.$residx}) {
+                    $hiddenfolder = 1;
+                }
+            }
         } else {
             my $rpicknum = (&LONCAPA::map::getparameter($orderidx,
                                                         'parameter_randompick'))[0];
@@ -4388,6 +4458,11 @@ $form_end;
         if ($anchor ne '') {
             $url .= '&amp;anchor='.&HTML::Entities::encode($anchor,'"<>&');
         }
+        if (ref($supphidden) eq 'HASH') {
+            if ($supphidden->{$suppmapid.':'.$residx}) {
+                $hiddenres = 1;
+            }
+        }
     }
     my ($tdalign,$tdwidth);
     if ($allowed) {
@@ -4415,7 +4490,7 @@ $form_end;
                     &Apache::lonhtmlcommon::jump_to_editres($cfile,$home,
                                                             $switchserver,
                                                             $forceedit,
-                                                            undef,$symb,
+                                                            undef,$symb,$shownsymb,
                                                             &escape($env{'form.folderpath'}),
                                                             $renametitle,$hostname,
                                                             '','',1,$suppanchor);
@@ -4476,6 +4551,17 @@ $form_end;
     $line.='</span></td><td'.$tdwidth.'>';
     if (($url=~m{/adm/(coursedocs|supplemental)}) || (!$allowed && $url)) {
        $line.='<a href="'.$url.'">'.$title.'</a>';
+       if (!$allowed && $supplementalflag && $canedit && $isfolder) {
+           my $editicon = &Apache::loncommon::lonhttpdurl('/res/adm/pages').'/editmap.png';
+           my $editurl = $url;
+           $editurl =~ s{^\Q/adm/supplemental?\E}{/adm/coursedocs?command=direct&amp;forcesupplement=1&amp;};
+           $line .= '&nbsp;'.'<a href="'.$editurl.'">'.
+                    '<img src="'.$editicon.'" alt="'.&mt('Edit Content').'" title="'.&mt('Edit Content').'" />'.
+                    '</a>';
+       }
+       if ((($hiddenfolder) || ($hiddenres)) && (!$allowed) && ($supplementalflag))  {
+           $line.= ' <span class="LC_warning">('.&mt('hidden').')</span> ';
+       }
     } elsif ($url) {
        if ($nomodal) {
            $line.='<a href="#" onclick="javascript:window.open('."'$link','syllabuspreview','height=400,width=500,scrollbars=1,resizable=1,menubar=0,location=1')".'; return false;" />'.
@@ -4496,32 +4582,37 @@ $form_end;
     $line .= '</td>';
     $rand_pick_text = '&nbsp;' if ($rand_pick_text eq '');
     $rand_order_text = '&nbsp;' if ($rand_order_text eq '');
-    if (($allowed) && ($folder!~/^supplemental/)) {
- 	my %lt=&Apache::lonlocal::texthash(
- 			      'hd' => 'Hidden',
- 			      'ec' => 'URL hidden');
-        my ($enctext,$hidtext);
-        if ((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i) {
-            $enctext = ' checked="checked"';
-            if (($ishash) && (ref($filtersref->{'encrypturl'}) eq 'ARRAY')) {
-                push(@{$filtersref->{'encrypturl'}},$orderidx);
-            }
-        }
+    if ($allowed) {
+        my %lt=&Apache::lonlocal::texthash(
+                              'hd' => 'Hidden',
+                              'ec' => 'URL hidden');
+        my ($enctext,$hidtext,$formhidden,$formurlhidden);
         if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) {
             $hidtext = ' checked="checked"';
             if (($ishash) && (ref($filtersref->{'randomorder'}) eq 'ARRAY')) {
                 push(@{$filtersref->{'hiddenresource'}},$orderidx);
             }
         }
-        my $formhidden = 'edit_hiddenresource_'.$orderidx;
-        my $formurlhidden = 'edit_encrypturl_'.$orderidx;
-	$line.=(<<ENDPARMS);
+        $formhidden = 'edit_hiddenresource_'.$orderidx;
+        $line.=(<<ENDPARMS);
   <td class="LC_docs_entry_parameter">
     <form action="/adm/coursedocs" method="post" name="$formhidden">
     $form_param
     $form_common
     <label><input type="checkbox" name="hiddenresource_$orderidx" id="hiddenresource_$orderidx" onclick="checkForSubmit(this.form,'hiddenresource','settings');" $hidtext $disabled /> $lt{'hd'}</label>
     $form_end
+ENDPARMS
+        if ($folder =~/^supplemental/) {
+            $line.= "\n    <td>";
+        } else {
+            if ((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i) {
+                $enctext = ' checked="checked"';
+                if (($ishash) && (ref($filtersref->{'encrypturl'}) eq 'ARRAY')) {
+                    push(@{$filtersref->{'encrypturl'}},$orderidx);
+                }
+            }
+            $formurlhidden = 'edit_encrypturl_'.$orderidx;
+	    $line.=(<<ENDPARMS);
     <br />
     <form action="/adm/coursedocs" method="post" name="$formurlhidden">
     $form_param
@@ -4532,6 +4623,7 @@ $form_end;
   <td class="LC_docs_entry_parameter">$rand_pick_text<br />
                                       $rand_order_text</td>
 ENDPARMS
+        }
     }
     $line.=&Apache::loncommon::end_data_table_row();
     return $line;
@@ -4865,7 +4957,7 @@ sub short_urls {
         $r->rflush();
         my $readonly;
         if ($canedit) {
-            my ($numnew,$errors) = &Apache::loncommon::make_short_symbs($cdom,$cnum,$navmap);
+            my ($numnew,$errors) = &Apache::loncommon::get_requested_shorturls($cdom,$cnum,$navmap);
             if ($numnew) {
                 $r->print('<p class="LC_info">'.&mt('Created [quant,_1,URL]',$numnew).'</p>');
             }
@@ -4900,7 +4992,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());
@@ -5387,17 +5479,20 @@ sub handler {
     $help{'Caching'} = &Apache::loncommon::help_open_topic('Caching');
  
     my ($allowed,$canedit,$canview,$noendpage,$disabled);
+# does this user have privileges to modify content.
+    if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) {
 # URI is /adm/supplemental when viewing supplemental docs in non-edit mode.
-    unless ($r->uri eq '/adm/supplemental') {
-        # does this user have privileges to modify content.  
-        if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) {
+        unless ($r->uri eq '/adm/supplemental') {
             $allowed = 1;
-            $canedit = 1;
-            $canview = 1;
-        } elsif (&Apache::lonnet::allowed('cev',$env{'request.course.id'})) {
+        }
+        $canedit = 1;
+        $canview = 1;
+    } elsif (&Apache::lonnet::allowed('cev',$env{'request.course.id'})) {
+# URI is /adm/supplemental when viewing supplemental docs in non-edit mode.
+        unless ($r->uri eq '/adm/supplemental') {
             $allowed = 1;
-            $canview = 1;
         }
+        $canview = 1;
     }
     unless ($canedit) {
         $disabled = ' disabled="disabled"';
@@ -5502,7 +5597,7 @@ sub handler {
 # Get the parameters that may be needed
 #
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
-                                            ['folderpath',
+                                            ['folderpath','title',
                                              'forcesupplement','forcestandard',
                                              'tools','symb','command','supppath']);
 
@@ -5549,35 +5644,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='';
@@ -5636,6 +5707,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
@@ -5796,8 +5870,14 @@ sub handler {
     &Apache::lonhtmlcommon::clear_breadcrumbs();
 
     if ($showdoc) {
-        $r->print(&Apache::loncommon::start_page("$crstype documents",undef,
-                                                {'force_register' => $showdoc,}));
+        my $args;
+        if ($supplementalflag) {
+            my $brcrum = &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$env{'form.title'},1);
+            $args = {'bread_crumbs' => $brcrum};
+        } else {
+            $args = {'force_register' => $showdoc};
+        }
+        $r->print(&Apache::loncommon::start_page("$crstype documents",undef,$args));
     } elsif ($toolsflag) {
         my ($breadtext,$breadtitle);
         $breadtext = "$crstype Editor";
@@ -5815,6 +5895,12 @@ sub handler {
                      $breadtitle)
                  );
     } elsif ($r->uri eq '/adm/supplemental') {
+        unless ($env{'request.role.adv'}) {
+            unless (&Apache::lonnet::has_unhidden_suppfiles($coursenum,$coursedom)) {
+                $r->internal_redirect('/adm/navmaps');
+                return OK;
+            }
+        }
         my $brcrum = &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype);
         $r->print(&Apache::loncommon::start_page("Supplemental $crstype Content",undef,
                                                 {'bread_crumbs' => $brcrum,}));
@@ -6590,13 +6676,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));
 
         my @external = (
@@ -6642,11 +6734,11 @@ my %orderhash = (
                 'bb' => ['Import',$importpubform],
                 'cc' => ['External',$externalform],
                 'dd' => ['Grading',$gradingform],
+                'ff' => ['Other',$specialdocumentsform],
                 );
 unless ($container eq 'page') {
     $orderhash{'00'} = ['Newfolder',$newfolderform];
     $orderhash{'ee'} = ['Collaboration',$communityform];
-    $orderhash{'ff'} = ['Other',$specialdocumentsform];
 }
 
  $hadchanges=0;
@@ -6803,29 +6895,41 @@ my %suporderhash = (
                 'ff' => ['Other',&create_form_ul(&create_list_elements(@specialdocs))]
                 );
         if ($supplementalflag) {
-           my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype,
-                               $supplementalflag,\%suporderhash,$iconpath,$pathitem,
-                               \%ltitools,$canedit,$hostname);
-           if ($error) {
-              $r->print('<p><span class="LC_error">'.$error.'</span></p>');
-           } else {
-               if ($suppchanges) {
-                   my %servers = &Apache::lonnet::internet_dom_servers($coursedom);
-                   my @ids=&Apache::lonnet::current_machine_ids();
-                   foreach my $server (keys(%servers)) {
-                       next if (grep(/^\Q$server\E$/,@ids));
-                       my $hashid=$coursenum.':'.$coursedom;
-                       my $cachekey = &escape('suppcount').':'.&escape($hashid);
-                       &Apache::lonnet::remote_devalidate_cache($server,[$cachekey]);
-                   }
-                   &Apache::lonnet::get_numsuppfiles($coursenum,$coursedom,1);
-                   undef($suppchanges);
-               }
-           }
+            $suppchanges = 0;
+            my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype,
+                                $supplementalflag,\%suporderhash,$iconpath,$pathitem,
+                                \%ltitools,$canedit,$hostname);
+            if ($error) {
+                $r->print('<p><span class="LC_error">'.$error.'</span></p>');
+            }
+            if ($suppchanges) {
+                my %servers = &Apache::lonnet::internet_dom_servers($coursedom);
+                my @ids=&Apache::lonnet::current_machine_ids();
+                foreach my $server (keys(%servers)) {
+                    next if (grep(/^\Q$server\E$/,@ids));
+                    my $hashid=$coursenum.':'.$coursedom;
+                    my $cachekey = &escape('showsupp').':'.&escape($hashid);
+                    &Apache::lonnet::remote_devalidate_cache($server,[$cachekey]);
+                }
+                &Apache::lonnet::has_unhidden_suppfiles($coursenum,$coursedom,1);
+                &Apache::lonnet::count_supptools($coursenum,$coursedom,1);
+                my $now = time;
+                if ($env{'request.course.id'} eq $coursedom.'_'.$coursenum) {
+                    &Apache::lonnet::appenv({'request.course.suppupdated' => $now});
+                }
+                &Apache::lonnet::put('environment',{'internal.supplementalchange' => $now},
+                                     $coursedom,$coursenum);
+                &Apache::lonnet::appenv(
+                    {'course.'.$coursedom.'_'.$coursenum.'.internal.supplementalchange' => $now});
+                &Apache::lonnet::do_cache_new('suppchange',$coursedom.'_'.$coursenum,$now,600);
+                &Apache::lonnet::get_numsuppfiles($coursenum,$coursedom,1);
+                undef($suppchanges);
+            }
         }
     } elsif ($supplementalflag) {
         my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype,
-                            $supplementalflag,'',$iconpath,$pathitem,'','',$hostname);
+                            $supplementalflag,'',$iconpath,$pathitem,'',$canedit,
+                            $hostname);
         if ($error) {
             $r->print('<p><span class="LC_error">'.$error.'</span></p>');
         }
@@ -7303,7 +7407,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;
                             }
@@ -7312,7 +7416,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;
                             }
@@ -7331,7 +7435,12 @@ sub editing_js {
     } elsif ($env{'docs.exit.'.$env{'request.course.id'}} eq '/adm/menu') {
         $backtourl = '/adm/menu';
     } elsif ($supplementalflag) {
-        $backtourl = '/adm/supplemental';
+        if (($env{'request.role.adv'}) ||
+            (&Apache::lonnet::has_unhidden_suppfiles($coursenum,$coursedom))) {
+            $backtourl = '/adm/supplemental';
+        } else {
+            $backtourl = '/adm/navmaps';
+        }
     } else {
         $backtourl = '/adm/navmaps';
     }
@@ -7358,7 +7467,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();
     }
 }
@@ -7366,7 +7475,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();
     }
 }
@@ -7375,7 +7484,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();
    }
 }
@@ -7384,7 +7493,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();
    }
 }
@@ -7399,7 +7508,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();
    }
 }
@@ -7408,7 +7517,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();
    }
 }
@@ -7417,7 +7526,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();
    }
 }
@@ -7426,7 +7535,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();
    }
 }
@@ -8550,7 +8659,7 @@ function validImportCrsRes() {
         url += fname;
     }
     var title = document.crsresimportform.crsrestitle.value;
-    document.crsresimportform.importdetail.value=escape(title)+'='+escape(url);
+    document.crsresimportform.importdetail.value=encodeURIComponent(title)+'='+encodeURIComponent(url);
     return true;
 }