--- loncom/interface/londocs.pm	2018/04/14 02:29:44	1.653
+++ loncom/interface/londocs.pm	2025/01/07 21:01:37	1.722
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Documents
 #
-# $Id: londocs.pm,v 1.653 2018/04/14 02:29:44 raeburn Exp $
+# $Id: londocs.pm,v 1.722 2025/01/07 21:01:37 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -45,10 +45,10 @@ use Apache::lontemplate();
 use Apache::lonsimplepage();
 use Apache::lonhomework();
 use Apache::lonpublisher();
-use Apache::lonparmset();
 use Apache::loncourserespicker();
 use HTML::Entities;
 use HTML::TokeParser;
+use HTML::LCParser;
 use GDBM_File;
 use File::MMagic;
 use File::Copy;
@@ -91,7 +91,7 @@ sub storemap {
 
     if ($map =~ /^default/) {
         $hadchanges=1;
-    } else {
+    } elsif ($contentchg) {
         $suppchanges=1;
     }
     return ($errtext,0);
@@ -103,6 +103,7 @@ sub authorhosts {
     my %outhash=();
     my $home=0;
     my $other=0;
+    my @ids=&Apache::lonnet::current_machine_ids();
     foreach my $key (keys(%env)) {
 	if ($key=~/^user\.role\.(au|ca)\.(.+)$/) {
 	    my $role=$1;
@@ -119,7 +120,6 @@ sub authorhosts {
 	    }
 	    my $allowed=0;
 	    my $myhome=&Apache::lonnet::homeserver($ca,$cd);
-	    my @ids=&Apache::lonnet::current_machine_ids();
 	    foreach my $id (@ids) {
                 if ($id eq $myhome) {
                     $allowed=1;
@@ -183,6 +183,64 @@ sub default_folderpath {
     }
 }
 
+sub validate_supppath {
+    my ($coursenum,$coursedom) = @_;
+    my $backto;
+    if ($env{'form.supppath'} ne '') {
+        my @items = split(/\&/,$env{'form.supppath'});
+        my ($badpath,$got_supp,$supppath,%supphidden,%suppids);
+        for (my $i=0; $i<@items; $i++) {
+            my $odd = $i%2;
+            if ((!$odd) && ($items[$i] !~ /^supplemental(|_\d+)$/)) {
+                $badpath = 1;
+                last;
+            } elsif ($odd) {
+                my $suffix;
+                my $idx = $i-1;
+                if ($items[$i] =~ /^([^:]*)::(|1):::$/) {
+                    $backto .= '&'.$1;
+                } elsif ($items[$idx] eq 'supplemental') {
+                    $backto .= '&'.$items[$i];
+                } else {
+                    $backto .= '&'.$items[$i];
+                    my $is_hidden;
+                    unless ($got_supp) {
+                        my ($supplemental) = &Apache::loncommon::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'}};
+                            }
+                        }
+                        $got_supp = 1;
+                    }
+                    if (ref($suppids{"/uploaded/$coursedom/$coursenum/$items[$idx].sequence"}) eq 'ARRAY') {
+                        my $mapid = $suppids{"/uploaded/$coursedom/$coursenum/$items[$idx].sequence"}->[0];
+                        if ($supphidden{$mapid}) {
+                            $is_hidden = 1;
+                        }
+                    }
+                    $suffix = '::'.$is_hidden.':::';
+                }
+                $supppath .= '&'.$items[$i].$suffix;
+            } else {
+                $supppath .= '&'.$items[$i];
+                $backto .= '&'.$items[$i];
+            }
+        }
+        if ($badpath) {
+            delete($env{'form.supppath'});
+        } else {
+            $supppath =~ s/^\&//;
+            $backto =~ s/^\&//;
+            $env{'form.supppath'} = $supppath;
+        }
+    }
+    return $backto;
+}
+
 sub dumpcourse {
     my ($r) = @_;
     my $crstype = &Apache::loncommon::course_type();
@@ -206,11 +264,12 @@ ENDJS
                          add_entries => {'onload' => "hide_searching();"},
                      };
     }
-    $r->print(&Apache::loncommon::start_page('Copy '.$crstype.' Content to Authoring Space',$js,$starthash)."\n".
-              &Apache::lonhtmlcommon::breadcrumbs('Copy '.$crstype.' Content to Authoring Space')."\n");
+    $r->print(&Apache::loncommon::start_page('Copy uploaded content to Authoring Space',$js,$starthash)."\n".
+              &Apache::lonhtmlcommon::breadcrumbs('Copy uploaded content to Authoring Space')."\n");
     $r->print(&startContentScreen('tools'));
     my ($home,$other,%outhash)=&authorhosts();
     unless ($home) {
+        $r->print('<p class="LC_info">'.&mt('No author or co-author roles on this server.').'</p>'); 
         $r->print(&endContentScreen());
         return '';
     }
@@ -219,7 +278,8 @@ ENDJS
     if (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) {
 # Do the dumping
 	unless ($outhash{'home_'.$env{'form.authorspace'}}) {
-            $r->print(&endContentScreen());
+            $r->print('<p class="LC_info">'.&mt('Selected Authoring Space is not on this server.').'</p>'.
+                      &endContentScreen());
             return '';
         }
 	my ($ca,$cd)=split(/\:/,$env{'form.authorspace'});
@@ -515,49 +575,13 @@ $contents{webreferences}.'
         if (!ref($navmap)) {
             $r->print($errormsg);
         } else {
-            $r->print('<div id="searching">'.&mt('Searching ...').'</div>');
-            $r->rflush();
-            my ($preamble,$formname);
-            $formname = 'dumpdoc';
-	    unless ($home==1) {
-	        $preamble = '<div class="LC_left_float">'.
-		            '<fieldset><legend>'.
-                            &mt('Select the Authoring Space').
-                            '</legend><select name="authorspace">';
-	    }
-            my @orderspaces = ();
-	    foreach my $key (sort(keys(%outhash))) {
-                if ($key=~/^home_(.+)$/) {
-                    if ($1 eq $env{'user.name'}.':'.$env{'user.domain'}) {
-                        unshift(@orderspaces,$1);
-                    } else {
-                        push(@orderspaces,$1);
-                    }
-                } 
-            }
-            if ($home>1) {
-                $preamble .= '<option value="" selected="selected">'.&mt('Select').'</option>';
-            }
-            foreach my $user (@orderspaces) {
-		if ($home==1) {
-		    $preamble .= '<input type="hidden" name="authorspace" value="'.$user.'" />';
-		} else {
-		    $preamble .= '<option value="'.$user.'">'.$user.' - '.
-			         &Apache::loncommon::plainname(split(/\:/,$user)).'</option>';
-	        }
-	    }
-	    unless ($home==1) {
-	        $preamble .= '</select></fieldset></div>'."\n";
-	    }
 	    my $title=$origcrsdata{'description'};
 	    $title=~s/[\/\s]+/\_/gs;
 	    $title=&clean($title);
-	    $preamble .= '<div class="LC_left_float">'.
-                         '<fieldset><legend>'.&mt('Folder in Authoring Space').'</legend>'.
-                         '<input type="text" size="50" name="authorfolder" value="'.
-                         $title.'" />'.
-                         '</fieldset></div><div style="padding:0;clear:both;margin:0;border:0"></div>'."\n";
-            my %uploadedfiles;
+	    my $formname = 'dumpdoc';
+	    my $preamble = &authorspace_selector($r,$formname,$home,$title,%outhash).
+                           '<div style="padding:0;clear:both;margin:0;border:0"></div>'."\n";
+	    my %uploadedfiles;
 	    &tiehash();
 	    foreach my $file (&Apache::lonclonecourse::crsdirlist($origcrsid,'userfiles')) {
 	        my ($ext)=($file=~/\.(\w+)$/);
@@ -583,6 +607,48 @@ $contents{webreferences}.'
     $r->print(&endContentScreen());
 }
 
+sub authorspace_selector {
+    my ($r,$formname,$home,$title,%outhash) = @_;
+    $r->print('<div id="searching">'.&mt('Searching ...').'</div>'."\n");
+    $r->rflush();
+    my $preamble;
+    unless ($home==1) {
+        $preamble = '<div class="LC_left_float">'.
+                    '<fieldset><legend>'.
+                    &mt('Select the Authoring Space').
+                    '</legend><select name="authorspace">';
+    }
+    my @orderspaces = ();
+    foreach my $key (sort(keys(%outhash))) {
+        if ($key=~/^home_(.+)$/) {
+            if ($1 eq $env{'user.name'}.':'.$env{'user.domain'}) {
+                unshift(@orderspaces,$1);
+            } else {
+                push(@orderspaces,$1);
+            }
+        }
+    }
+    if ($home>1) {
+        $preamble .= '<option value="" selected="selected">'.&mt('Select').'</option>';
+    }
+    foreach my $user (@orderspaces) {
+        if ($home==1) {
+            $preamble .= '<input type="hidden" name="authorspace" value="'.$user.'" />';
+        } else {
+            $preamble .= '<option value="'.$user.'">'.$user.' - '.
+                         &Apache::loncommon::plainname(split(/\:/,$user)).'</option>';
+        }
+    }
+    unless ($home==1) {
+        $preamble .= '</select></fieldset></div>'."\n";
+    }
+    $preamble .= '<div class="LC_left_float">'.
+                 '<fieldset><legend>'.&mt('Folder in Authoring Space').'</legend>'.
+                 '<input type="text" size="30" name="authorfolder" value="'.$title.'" />'."\n".
+                 '</fieldset></div>'."\n";
+    return $preamble;
+}
+
 sub recurse_html {
     my ($mm,$prefix,$currdirpath,$currurlpath,$container,$item,$replacehash,$deps) = @_;
     return unless ((ref($replacehash) eq 'HASH') && (ref($deps) eq 'HASH'));
@@ -627,6 +693,982 @@ sub recurse_html {
     return;
 }
 
+sub copycrsauthored {
+    my ($r,$coursenum,$coursedom,$coursehome,$readonly) = @_;
+    my ($starthash,$js,$title,$formname);
+    my %origcrsdata=&Apache::lonnet::coursedescription($env{'request.course.id'});
+    $title=$origcrsdata{'description'};
+    $title=~s/[\/\s]+/\_/gs;
+    $title=&clean($title);
+    my ($home,$other,%outhash)=&authorhosts();
+    unless (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) {
+        my %js_lt;
+        $formname = 'copycrsauthored';
+        if ($home) {
+            %js_lt =
+                &Apache::lonlocal::texthash(
+                    yomu => 'You must select an Authoring Space',
+                    whco => 'When Copyright set to "custom", URL of a published rights file is needed.',
+            );
+            &js_escape(\%js_lt);
+        }
+        if ($home > 1) {
+            $js = <<"ENDJS";
+<script type="text/javascript">
+// <![CDATA[
+
+function validCrsCopy() {
+    var dest = document.$formname.authorspace.options[document.$formname.authorspace.selectedIndex].value;
+    if (dest == '') {
+        alert("$js_lt{'yomu'}");
+        return false;
+    }
+    var dist = document.$formname.copyright.options[document.$formname.copyright.selectedIndex].value;
+    if (dist == 'custom') {
+        if (document.$formname.customrights.value == '') {
+            alert("$js_lt{'whco'}");
+            return false;
+        }
+    }
+    return true;
+}
+
+function init_copycrs_form() {
+    document.$formname.authorspace.selectedIndex = "0";
+    document.$formname.authorfolder.value = '$title';
+    document.$formname.copyright.selectedIndex = "0";
+}
+
+// ]]>
+</script>
+
+ENDJS
+        } elsif ($home) {
+            $js = <<"ENDJS";
+<script type="text/javascript">
+// <![CDATA[
+
+function init_copycrs_form() {
+    document.$formname.authorfolder.value = '$title';
+    document.$formname.copyright.selectedIndex = "0";
+}
+
+// ]]>
+</script>
+
+ENDJS
+        }
+        $js .= <<"ENDJS";
+<script type="text/javascript">
+// <![CDATA[
+
+function hide_searching() {
+    if (document.getElementById('searching')) {
+        document.getElementById('searching').style.display = 'none';
+    }
+    return;
+}
+
+function showHideCustom(caller,divid) {
+    if (document.getElementById(divid)) {
+        if (caller.options[caller.selectedIndex].value == 'custom') {
+            document.getElementById(divid).style.display="inline-block";
+        } else {
+            document.getElementById(divid).style.display="none";
+        }
+    }
+    return;
+}
+
+// ]]>
+</script>
+ENDJS
+
+        $js .= "\n".&Apache::lonhtmlcommon::scripttag(&Apache::loncommon::browser_and_searcher_javascript())."\n";
+        $starthash = {
+                         add_entries => {'onload' => "hide_searching(); init_copycrs_form();"},
+                     };
+    }
+    $r->print(&Apache::loncommon::start_page('Copy from Course Authoring to User Authoring',$js,$starthash)."\n".
+              &Apache::lonhtmlcommon::breadcrumbs('Copy from Course Authoring Space')."\n");
+    $r->print(&startContentScreen('tools'));
+    unless ($home) {
+        $r->print('<p class="LC_info">'.&mt('No author or co-author roles on this server.').'</p>');
+        $r->print(&endContentScreen());
+        return '';
+    }
+    my $docroot = $r->dir_config('lonDocRoot');
+    my $is_course_home;
+    my @ids=&Apache::lonnet::current_machine_ids();
+    if (($coursehome ne '') && (grep(/^\Q$coursehome\E$/,@ids))) {
+        $is_course_home = 1;
+    }
+    my $exclude = &Apache::lonnet::priv_exclude();
+    my $srcurl = "/priv/$coursedom/$coursenum";
+    my $srctop = $docroot.$srcurl;
+    my $resurl = "/res/$coursedom/$coursenum";
+    my $res_exclude = &Apache::lonnet::res_exclude();
+    if (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) {
+        $r->print('<h3>'.&mt('Copying Files and/or Sub-directories').'</h3>');
+        if ($readonly) {
+            $r->print('<p class="LC_info">'.
+                      &mt('You do not have permission to copy files and/or directories from Course Authoring Space.').
+                      '</p>'.
+                      &endContentScreen());
+            return '';
+        }
+        unless ($outhash{'home_'.$env{'form.authorspace'}}) {
+            $r->print('<p class="LC_info">'.&mt('Selected Authoring Space is not on this server.').'</p>'.
+                      &endContentScreen());
+            return '';
+        }
+        my ($ca,$cd)=split(/\:/,$env{'form.authorspace'});
+        my $desturl = "/priv/$cd/$ca";
+        my $destresurl = "/res/$cd/$ca";
+        my $desttop = $docroot.$desturl;
+        my $subdir = &clean($env{'form.authorfolder'});
+        $subdir = &cleandir($subdir);
+        if ($subdir eq '') {
+            $r->print('<p class="LC_info">'.&mt('After removal of disallowed characters target sub-directory name was blank.').'</p>'.
+                      &endContentScreen());
+            return '';
+        } elsif ($subdir =~/^_+$/) {
+            $r->print('<p class="LC_info">'.&mt('After replacement of non-alphanumeric characters with _ in target sub-directory name, nothing but underscores was left.').'</p>'.
+                      &endContentScreen());
+            return '';
+        }
+        my (%tocopy,%dirs_to_make,%files_to_copy);
+        map { $tocopy{&unescape($_)} = 1; } &Apache::loncommon::get_env_multiple('form.copytouser');
+        if (keys(%tocopy)) {
+            my (%subdirs,%files);
+            &Apache::lonnet::recursedirs($is_course_home,1,undef,$exclude,0,0,$srcurl,'',\%subdirs,\%files);
+            foreach my $possible (sort(keys(%tocopy))) {
+                if ($possible =~ m{/$}) {
+                    my $possdir = $possible;
+                    $possdir =~ s{^/+|/+$}{}g;
+                    if (exists($subdirs{$possdir})) {
+                        $dirs_to_make{$possdir} = 1;
+                    } else {
+                        delete($tocopy{$possible});
+                    }
+                } else {
+                    my ($path,$fname) = ($possible =~ m{(.*/)([^/]+)$});
+                    my $found = 0;
+                    if ($path eq '/') {
+                        if (ref($files{$path}) eq 'HASH') {
+                            if (exists($files{$path}{$fname})) {
+                                $found = 1;
+                                $files_to_copy{$fname} = 1;
+                            }
+                        }
+                    } else {
+                        $path =~ s{^/+|/+$}{}g;
+                        if (ref($files{$path}) eq 'HASH') {
+                            if (exists($files{$path}{$fname})) {
+                                $dirs_to_make{$path} = 1;
+                                $files_to_copy{"$path/$fname"} = 1;
+                                $found = 1;
+                            }
+                        }
+                    }
+                    unless ($found) {
+                        delete($tocopy{$possible});
+                    }
+                }
+            }
+        } else {
+            $r->print('<p>'.&mt('No files or directories selected for copying').'</p>');
+            $r->print(&endContentScreen());
+            return '';
+        }
+        if (keys(%tocopy)) {
+            my (%resdirs,%resfiles);
+            &Apache::lonnet::recursedirs($is_course_home,1,undef,$res_exclude,0,0,$resurl,'',\%resdirs,\%resfiles);
+            my ($notopdir,%newdir,%newfile,%checkdeps,%newresfile);
+            $r->print('<p>'.&mt('Copy to: [_1]',
+                                '<span class="LC_filename">'.$desturl.'/'.$subdir.'</span>').
+                      '</p>'."\n");
+            if (keys(%dirs_to_make)) {
+                unless (-e $desttop.'/'.$subdir) {
+                    mkdir($desttop.'/'.$subdir,0755);
+                }
+                if (-e $desttop.'/'.$subdir) {
+                    foreach my $dir (sort(keys(%dirs_to_make))) {
+                        my @dirs=split(/\//,$dir);
+                        my $path="$desttop/$subdir";
+                        my $makepath=$path;
+                        my $fail;
+                        for (my $i=0;$i<@dirs;$i++) {
+                            $makepath.='/'.$dirs[$i];
+                            unless (-e $makepath) {
+                                unless (mkdir($makepath,0755)) {
+                                    $fail = 1;
+                                    last;
+                                }
+                                if (($i == scalar(@dirs)-1) && (!$fail))  {
+                                    $newdir{$dir} = 1;
+                                }
+                            }
+                        }
+                        if ($fail) {
+                            $r->print('<p class="LC_warning">'.&mt('Target directory: [_1] does not exist, and could not be created.',
+                                                                   '<span class="LC_filename">'.$desturl.'/'.$subdir.'/'.$dir.'</span>').
+                                      '</p>'."\n");
+                        }
+                    }
+                } else {
+                    $notopdir = 1;
+                }
+            }
+            if (keys(%files_to_copy)) {
+                unless (-e $desttop.'/'.$subdir) {
+                    mkdir($desttop.'/'.$subdir,0755);
+                }
+                if (-e $desttop.'/'.$subdir) {
+                    my $num = 0;
+                    my ($copyright,$customdistfile);
+                    if ($env{'form.copyright'} eq 'default' || $env{'form.copyright'} eq 'domain' || $env{'form.copyright'} eq 'public') {
+                        $copyright = $env{'form.copyright'};
+                    } elsif ($env{'form.copyright'} eq 'custom') {
+                        if ($env{'form.customrights'} =~ m{^/res/$match_domain/$match_username/.+\.rights$}) {
+                            my ($rightsdom,$rightsuname) = ($1,$2);
+                            my $rightshome = &Apache::lonnet::homeserver($rightsdom,$rightsuname);
+                            if (($rightshome eq 'no_host') || ($rightshome eq '')) {
+                                $copyright = 'default';
+                            } elsif (grep(/^\Q$rightshome\E$/,@ids)) {
+                                if (-e $docroot.$env{'form.customrights'}) {
+                                    $copyright = 'custom';
+                                    $customdistfile = $env{'form.customrights'};
+                                } else {
+                                    $copyright = 'default';
+                                }
+                            } else {
+                                my $rightsfile = &Apache::lonnet::filelocation('',$env{'form.customrights'});
+                                unless (&Apache::lonnet::getfile($rightsfile) eq '-1') {
+                                    $customdistfile = $env{'form.customrights'};
+                                }
+                            }
+                        }
+                    }
+                    my $sourceavail;
+                    if ($env{'form.sourceavail'} =~ /^(open|closed)$/) {
+                        $sourceavail = $env{'form.sourceavail'};
+                    }
+                    my $respublish;
+                    if ($env{'form.respublish'}) {
+                        $respublish = 1;
+                    }
+                    my $nokeyref = &Apache::lonpublisher::getnokey($r->dir_config('lonIncludes'));
+                    foreach my $file (keys(%files_to_copy)) {
+                        my ($fail,$dup,$dir_is_file,$src,$dest,$path,$fname);
+                        if ($file =~ m{/}) {
+                            ($path,$fname) = ($file =~ m{^(.+)/([^/]+)$});
+                            if (-d "$desttop/$subdir/$path") {
+                                if (-e "$desttop/$subdir/$path/$fname") {
+                                    $dup = 1;
+                                } else {
+                                    $src = "$srctop/$path/$fname";
+                                    $dest = "$desttop/$subdir/$path/$fname";
+                                }
+                            } elsif (-f "$desttop/$subdir/$path") {
+                                $dir_is_file = 1;
+                            } else {
+                                $fail = 1;
+                            }
+                        } elsif (-e "$desttop/$subdir/$file") {
+                            $dup = 1;
+                        } else {
+                            $src = "$srctop/$file";
+                            $dest = "$desttop/$subdir/$file";
+                            $fname = $file;
+                        }
+                        if ($fail) {
+                            $r->print('<p class="LC_warning">'.&mt('Target directory: [_1] does not exist, and could not be created.',
+                                                                   '<span class="LC_filename">'.$desturl.'/'.$subdir.'/'.$path.'</span>').
+                                      '</p>'."\n");
+                        } elsif ($dup) {
+                            $r->print('<p class="LC_warning">'.&mt('Target file: [_1] already exists -- not overwriting.',
+                                                                   '<span class="LC_filename">'.$desturl.'/'.$subdir.'/'.$file.'</span>').
+                                      '</p>'."\n");
+                        } elsif ($dir_is_file) {
+                            $r->print('<p class="LC_warning">'.&mt('Target directory: [_1] name is already in a use for a file -- not overwriting.',
+                                                                   '<span class="LC_filename">'.$desturl.'/'.$subdir.'/'.$file.'</span>').
+                                      '</p>'."\n");
+                        } elsif (($src ne '') && ($dest ne '')) {
+                            my $ressrc = $docroot.$resurl.'/'.$file;
+                            my $ressrcmeta = $ressrc.'.meta';
+                            my ($ext) = ($file =~ /\.(\w+)$/);
+                            my $embstyle=&Apache::loncommon::fileembstyle($ext);
+                            my ($getres,$getresmeta);
+                            if ($respublish) {
+                                if ($path eq '') {
+                                    if ((ref($resfiles{'/'}) eq 'HASH') &&
+                                        (exists($resfiles{'/'}{$fname}))) {
+                                        $getres = 1;
+                                        $getresmeta = 1;
+                                    }
+                                } elsif ((ref($resfiles{$path}) eq 'HASH') &&
+                                         (exists($resfiles{$path}{$fname}))) {
+                                    $getres = 1;
+                                    $getresmeta = 1;
+                                }
+                            }
+                            if ($is_course_home) {
+                                my ($needpriv,$needprivmeta);
+                                if ($respublish) {
+                                    if ($getres) {
+                                        if (&Apache::londiff::are_different_files($src,$ressrc)) {
+                                            $needpriv = 1;
+                                            if (&File::Copy::copy($ressrc,$dest)) {
+                                                if ($embstyle eq 'ssi') {
+                                                    &crsres_fixup($dest,$coursenum,$coursedom,$ca,$cd);
+                                                }
+                                            }
+                                        } else {
+                                            if (&File::Copy::copy($src,$dest)) {
+                                                $newfile{$file} = $desturl.'/'.$subdir.'/'.$file;
+                                                if ($embstyle eq 'ssi') {
+                                                    &crsres_fixup($dest,$coursenum,$coursedom,$ca,$cd,$subdir);
+                                                }
+                                            }
+                                        }
+                                    } else {
+                                        $needpriv = 1;
+                                    }
+                                    if ($getresmeta) {
+                                        if ((-e $src.'.meta') && (!-e $dest.'.meta')) {
+                                            if (&Apache::londiff::are_different_files($src.'.meta',$ressrc.'.meta')) {
+                                                if (&File::Copy::copy($ressrc.'.meta',$dest.'.meta')) {
+                                                    &crsres_fixup_meta($dest,$coursenum,$coursedom,$ca,$cd,$copyright,
+                                                                       $customdistfile,$sourceavail,\%checkdeps);
+                                                }
+                                                $needprivmeta = 1;
+                                            } else {
+                                                if (&File::Copy::copy($src.'.meta',$dest.'.meta')) {
+                                                    &crsres_fixup_meta($dest,$coursenum,$coursedom,$ca,$cd,$copyright,
+                                                                       $customdistfile,$sourceavail,\%checkdeps);
+                                                }
+                                            }
+                                        }
+                                    }
+                                    if ($getres) {
+                                        my $destresfile = $docroot.$destresurl.'/'.$subdir.'/'.$file;
+                                        if (-e $dest) {
+                                            my $output = &Apache::lonpublisher::batchpublish($r,$dest,$destresfile,$nokeyref,1);
+                                            if (-e $destresfile) {
+                                                $newresfile{$file} = $destresurl.'/'.$subdir.'/'.$file;
+                                            }
+                                        }
+                                    }
+                                } else {
+                                    $needpriv = 1;
+                                    if ((-e $src.'.meta') && (!-e $dest.'.meta')) {
+                                        $needprivmeta = 1;
+                                    }  
+                                }
+                                if ($needpriv) {
+                                    if (&File::Copy::copy($src,$dest)) {
+                                        $newfile{$file} = $desturl.'/'.$subdir.'/'.$file;
+                                        if ($embstyle eq 'ssi') {
+                                            &crsres_fixup($dest,$coursenum,$coursedom,$ca,$cd,$subdir);
+                                        }
+                                    }
+                                }
+                                if ($needprivmeta) {
+                                    if (&File::Copy::copy($src.'.meta',$dest.'.meta')) {
+                                         &crsres_fixup_meta($dest,$coursenum,$coursedom,$ca,$cd,$copyright,
+                                                            $customdistfile,$sourceavail,\%checkdeps);
+                                    }
+                                }
+                            } else {
+                                my ($needpriv,$needprivmeta);
+                                if ($respublish) {
+                                    if ($getres) {
+                                        &Apache::lonnet::repcopy($docroot.$resurl.'/'.$file);
+                                    }
+                                    if ($getresmeta) {
+                                        &Apache::lonnet::repcopy($docroot.$resurl.'/'.$file.'.meta');
+                                    }
+                                    if (-e $docroot.$resurl.'/'.$file) {
+                                        if (&Apache::lonnet::repcopy_crsprivfile($srcurl.'/'.$file,$dest) eq 'ok') {
+                                            if (&Apache::londiff::are_different_files($docroot.$resurl.'/'.$file,$dest)) {
+                                                $needpriv = 1;
+                                                if (&File::Copy::copy($docroot.$resurl.'/'.$file,$dest)) {
+                                                    if ($embstyle eq 'ssi') {
+                                                        &crsres_fixup($dest,$coursenum,$coursedom,$ca,$cd);
+                                                    }
+                                                }
+                                            } else {
+                                                if ($embstyle eq 'ssi') {
+                                                    &crsres_fixup($dest,$coursenum,$coursedom,$ca,$cd,$subdir);
+                                                }
+                                                $newfile{$file} = $desturl.'/'.$subdir.'/'.$file;
+                                            }
+                                        }
+                                    } else {
+                                        $needpriv = 1;
+                                    }
+                                    if (-e $docroot.$resurl.'/'.$file.'.meta') {
+                                        if (&Apache::lonnet::repcopy_crsprivfile($srcurl.'/'.$file.'.meta',$dest.'.meta') eq 'ok') {
+                                            if (&Apache::londiff::are_different_files($docroot.$resurl.'/'.$file.'.meta',$dest.'.meta')) {
+                                                $needprivmeta = 1;
+                                                if (&File::Copy::copy($docroot.$resurl.'/'.$file.'.meta',$dest.'.meta')) {
+                                                    &crsres_fixup_meta($dest,$coursenum,$coursedom,$ca,$cd,$copyright,
+                                                                       $customdistfile,$sourceavail,\%checkdeps);
+                                                }
+                                            } else {
+                                                &crsres_fixup_meta($dest,$coursenum,$coursedom,$ca,$cd,$copyright,
+                                                                   $customdistfile,$sourceavail,\%checkdeps);
+                                            }
+                                        }
+                                    } else {
+                                        if (!-e $dest.'.meta') {
+                                            $needprivmeta = 1;
+                                        }
+                                    }
+                                    if ($getres) {
+                                        my $destresfile = $docroot.$destresurl.'/'.$subdir.'/'.$file;
+                                        if (-e $dest) {
+                                            my $output = &Apache::lonpublisher::batchpublish($r,$dest,$destresfile,$nokeyref,1);
+                                            if (-e $destresfile) {
+                                                $newresfile{$file} = $destresurl.'/'.$subdir.'/'.$file;
+                                            }
+                                        }
+                                    }
+                                } else {
+                                    $needpriv = 1;
+                                    if (!-e $dest.'.meta') {
+                                        $needprivmeta = 1;
+                                    }
+                                }
+                                if ($needpriv) {
+                                    if (&Apache::lonnet::repcopy_crsprivfile($srcurl.'/'.$file,$dest) eq 'ok') {
+                                        if ($embstyle eq 'ssi') {
+                                            &crsres_fixup($dest,$coursenum,$coursedom,$ca,$cd,$subdir);
+                                        }
+                                        $newfile{$file} = $desturl.'/'.$subdir.'/'.$file;
+                                    }
+                                }
+                                if ($needprivmeta) {
+                                    if (&Apache::lonnet::repcopy_crsprivfile($srcurl.'/'.$file.'.meta',$dest.'.meta') eq 'ok') {
+                                        &crsres_fixup_meta($dest,$coursenum,$coursedom,$ca,$cd,$copyright,
+                                                           $customdistfile,$sourceavail,\%checkdeps);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    $notopdir = 1;
+                }
+            }
+            if ($notopdir) {
+                $r->print('<p><span class="LC_info">'.&mt('No files or sub-directories copied').'</span><br />'."\n".
+                          '<span class="LC_warning">'.&mt('Target directory: [_1] does not exist, and could not be created.',
+                                                          '<span class="LC_filename">'.$desturl.'/'.$subdir.'</span>').
+                          '</span></p>'."\n");
+            }
+            if (keys(%newdir)) {
+                 $r->print('<p>'.&mt('Created the following directories in [_1]:','<span class="LC_filename">'.$desturl.'/'.$subdir.'</span>').
+                           '</p>'."\n".
+                           '<ul><li>'.join('</li><li>',sort(keys(%newdir))).'</li></ul></p>'."\n");
+            }
+            if (keys(%newfile)) {
+                $r->print('<p>'.&mt('Copied the following files to [_1]:','<span class="LC_filename">'.$desturl.'/'.$subdir.'</span>').
+                          '</p>'."\n".
+                          '<ul><li>'.join('</li><li>',sort(keys(%newfile))).'</li></ul></p>'."\n");
+                foreach my $file (keys(%newfile)) {
+                    my %storehash = (
+                                      'priv' => $newfile{$file},
+                                      'who'  => $env{'user.name'}.':'.$env{'user.domain'},
+                                    );
+                    if (exists($newresfile{$file})) {
+                        $storehash{'res'} = 1;
+                    }
+                    &Apache::lonnet::store_userdata(\%storehash,$file,'copycourseauthor',$coursedom,$coursenum);
+                }
+            }
+            if (keys(%checkdeps)) {
+                my %missingdep;
+                foreach my $depfile (sort(keys(%checkdeps))) {
+                    unless (-e "$desttop/$depfile") {
+                        $missingdep{$depfile} = 1;
+                    }
+                }
+                if (keys(%missingdep)) {
+                    $r->print('<p>'.&mt('You may also need to copy the following missing dependencies for files copied to [_1]:',
+                                        '<span class="LC_filename">'.$desturl.'/'.$subdir.'</span>').
+                          '</p>'."\n".
+                          '<ul><li>'.join('</li><li>',sort(keys(%missingdep))).'</li></ul></p>'."\n");
+                }
+            }
+        } else {
+            $r->print('<p>'.&mt('No currently existing files or directories in Course Authoring Space selected for copying').'</p>');
+            $r->print(&endContentScreen());
+            return '';
+        }
+    } else {
+        my $chkname = 'copytouser';
+        my $context = 'crsauthored';
+        my (%subdirs,%files,@dirs_by_depth,@files_by_depth,%parent,%children,%hierarchy,@checked_maps);
+        &Apache::lonnet::recursedirs($is_course_home,1,undef,$exclude,0,0,$srcurl,'',\%subdirs,\%files,1);
+        foreach my $key (keys(%subdirs)) {
+            next if (($key eq '/') || ($key eq ''));
+            my @items = split(/\//,$key);
+            my $dir = pop(@items);
+            my $depth = scalar(@items);
+            my $path;
+            if (!$depth) {
+                $path = '/';
+            } else {
+                $path = join('/',@items);
+            }
+            $dirs_by_depth[$depth]{$path}{$dir} = 1;
+        }
+        foreach my $path (keys(%files)) {
+            next if ($path eq '');
+            my $depth;
+            if ($path eq '/') {
+                $depth = 0;
+            } else {
+                $depth = scalar(split(/\//,$path));
+            }
+            if (ref($files{$path}) eq 'HASH') {
+                foreach my $file (keys(%{$files{$path}})) {
+                    $files_by_depth[$depth]{$path}{$file} = $files{$path}{$file};
+                }
+            }
+        }
+        my ($info,$display,$onsubmit,$togglebuttons,$disabled);
+        my (%resdirs,%resfiles);
+        &Apache::lonnet::recursedirs($is_course_home,1,undef,$res_exclude,0,0,$resurl,'',\%resdirs,\%resfiles);
+        my $numpub = 0;
+        if (keys(%resfiles)) {
+            foreach my $dir (keys(%resfiles)) {
+                if (ref($resfiles{$dir}) eq 'HASH') {
+                    foreach my $file (keys(%{$resfiles{$dir}})) {
+                        if (exists($files{$dir}{$file})) {
+                            $numpub ++;
+                        }
+                    }
+                }
+            }
+        }
+        if ($readonly) {
+            $disabled = ' disabled="disabled"';
+        }
+        if ($disabled) {
+            $togglebuttons = '<br />';
+        } else {
+            $togglebuttons = '<input type="button" value="'.&mt('check all').'" '.
+                             'onclick="javascript:checkAll(document.'.$formname.'.'.$chkname.')" />'.
+                             '&nbsp;&nbsp;<input type="button" value="'.&mt('uncheck all').'"'.
+                             ' onclick="javascript:uncheckAll(document.'.$formname.'.'.$chkname.')" />';
+        }
+        my $preamble = &authorspace_selector($r,$formname,$home,$title,%outhash).
+                       &courseresource_options($formname,$numpub).
+                       '<div style="padding:0;clear:both;margin:0;border:0"></div>'."\n";
+        my $display = '<form name="'.$formname.'" action="" method="post" onsubmit="return validCrsCopy();">'."\n".
+                      $preamble."\n".
+                      '<div class="LC_float_left">'."\n".
+                      '<fieldset>'."\n".
+                      '<legend>'.&mt('Content to copy').('&nbsp;'x4).$togglebuttons.'</legend>'."\n".
+                      '<span class="LC_fontsize_medium">'.
+                      &mt('Choose the files and/or folders to copy from Course Authoring to User Authoring').
+                      '</span><br /><br />'."\n";
+        my $count = 0;
+#
+# Warning to developers:
+#
+# If you add or remove form elements which precede the table of items to copy
+# you will need to modify the value for startcount. Form elements include both:
+# <input> and <fieldset> tags.
+# $startcount (set to 9) contains the following:
+# fieldsets with following legends: (a) Folder in Authoring Space, (b) Distribution to set in metadata
+# (c) Content to copy
+# inputs: textbox for destination folder; dropdown lists: (a) Copyright, (b) Source
+# hidden: customrights file;  buttons: (a) check all, (b) uncheck all.
+# authorspace: if more than 1: a fieldset with legend: Select the Authoring Space,
+# or if 1: an input (hidden) with available author/coauthor role.
+# if there are multiple possible author/coauthor roles (i.e., $home > 1),
+# incerement startcount by 1 for the dropdown list uses to select the target.
+#
+# If there are published files, increment startcount by 3:
+# fieldset (legend: Published Resources), and two radio buttons (Yes/No).
+#
+        my $startcount = 9;
+        if ($home > 1) {
+            $startcount ++;
+        }
+        if ($numpub) {
+            $startcount += 3;
+        }
+        my $lastcontainer = $startcount;
+        $display .= &Apache::loncommon::start_data_table()."\n".
+                    &Apache::loncommon::start_data_table_header_row().
+                    '<th>'.&mt('Copy?').'</th>'.
+                    '<th>'.&mt('Name').'</th>'.
+                    '<th>'.&mt('Last modified').'</th>'.
+                    '<th>'.&mt('Published?').'</th>'.
+                    &Apache::loncommon::end_data_table_header_row()."\n";
+        $count = &recurse_crsauthored(0,\@dirs_by_depth,\@files_by_depth,'/',$startcount,
+                                      $count,\$display,\%parent,\%children,$readonly,
+                                      $formname,$chkname,\$lastcontainer,\%resfiles);
+        $display .= &Apache::loncommon::end_data_table().'</fieldset>';
+        unless ($readonly) {
+            $display .= '</div><div style="padding:0;clear:both;margin:0;border:0"></div>'.
+                        '<div>'.
+                        '<input type="submit" name="copyauthored" value="'.&mt("Copy Selected Content").'" />'.
+                        '</div>';
+        }
+        $display .= &Apache::loncourserespicker::respicker_javascript($startcount,$count,$context,$formname,\%children,
+                                                                      \%hierarchy,\@checked_maps,$home,$chkname);
+        $r->print($display);
+    }
+    $r->print(&endContentScreen());
+}
+
+sub recurse_crsauthored {
+    my ($currdepth,$dirs_by_depth,$files_by_depth,$currpath,$startcount,$count,$displayref,
+        $parent,$children,$readonly,$formname,$chkname,$lastcontainerref,$resfilesref) = @_;
+    return $count unless ((ref($dirs_by_depth) eq 'ARRAY') && (ref($files_by_depth) eq 'ARRAY') &&
+                          (ref($resfilesref) eq 'HASH'));
+    my ($disabled,$hasdirs,$hasfiles,%unique,%dirs,%files);
+    if ((ref($dirs_by_depth->[$currdepth]) eq 'HASH') &&
+        (ref($dirs_by_depth->[$currdepth]{$currpath}) eq 'HASH')) {
+        $hasdirs = 1;
+        %dirs = %{$dirs_by_depth->[$currdepth]{$currpath}};
+        map { $unique{$_} = 1; } keys(%dirs);
+    }
+    if ((ref($files_by_depth->[$currdepth]) eq 'HASH') &&
+        (ref($files_by_depth->[$currdepth]{$currpath}) eq 'HASH')) {
+        $hasfiles = 1;
+        %files = %{$files_by_depth->[$currdepth]{$currpath}};
+        map { $unique{$_} = 1; } keys(%files);
+    }
+    if ($readonly) {
+        $disabled = ' disabled="disabled"';
+    }
+    my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons");
+    my $whitespace =
+        '<img src="'.$location.'/whitespace_21.gif" class="LC_docs_spacer" alt="" />';
+    $parent->{$currdepth} = $$lastcontainerref;
+    foreach my $item (sort { lc($a) cmp lc($b) } (keys(%unique))) {
+        next if ($item eq '');
+        my $currelem;
+        if ($hasdirs && exists($dirs{$item})) {
+            $count ++;
+            my $deeper = $currdepth+1;
+            my ($newpath,$showpath);
+            if ($currpath eq '/') {
+                $newpath = $item;
+                $showpath = $currpath.$item.'/';
+            } else {
+                $newpath = $currpath.'/'.$item;
+                $showpath = '/'.$currpath.'/'.$item.'/';
+            }
+            $currelem = $count+$startcount;
+            $$lastcontainerref = $currelem;
+            $children->{$parent->{$currdepth}} .= $currelem.':';
+            my $icon = 'src="'.$location.'/navmap.folder.open.gif" alt="'.&mt('Folder').'"';
+            $$displayref .= &Apache::loncommon::start_data_table_row().
+                            '<td><input type="checkbox" name="'.$chkname.'" value="'.&escape($showpath).'" '.
+                            'onclick="javascript:checkFolder(document.'.$formname.','."'$currelem'".')" '.
+                            $disabled.' /></td><td>';
+            for (my $i=0; $i<$currdepth; $i++) {
+                $$displayref .= "$whitespace\n";
+            }
+            $$displayref .= '<img '.$icon.' />&nbsp;'.$item.'</td><td>&nbsp;</td><td>&nbsp;</td>'.
+                            &Apache::loncommon::end_data_table_row()."\n";
+            $count = &recurse_crsauthored($deeper,$dirs_by_depth,$files_by_depth,$newpath,
+                                          $startcount,$count,$displayref,$parent,$children,
+                                          $readonly,$formname,$chkname,$lastcontainerref,$resfilesref);
+        }
+        if ($hasfiles && exists($files{$item})) {
+            $count ++;
+            $currelem = $count+$startcount;
+            $children->{$parent->{$currdepth}} .= $currelem.':';
+            my $icon = 'src="'.&Apache::loncommon::icon($item).'"';
+            my ($ext) = ($item =~ /\.([^.]+)$/);
+            my $alttext;
+            if (lc($ext) eq 'problem') {
+                $alttext = ' alt="'.&mt('Problem Icon').'"';
+            } elsif ($ext =~ /^x?html?$/i) {
+                $alttext = ' alt="'.&mt('Web Page Icon').'"';
+            } elsif ($ext =~ /^(jpg|gif|png|svg|jpeg)$/) {
+                $alttext = ' alt="'.&mt('Image Icon').'"';
+            } else {
+                $alttext = ' alt="'.&mt('Resource Icon').'"';
+            }
+            my $showpath;
+            if ($currpath eq '/') {
+                $showpath = $currpath;
+            } else {
+                $showpath = "/$currpath/";
+            }
+            my ($published,$lastmod);
+            if ((ref($resfilesref->{$currpath})) && (exists($resfilesref->{$currpath}{$item}))) {
+                $published = '<img src="'.$location.'/navmap.correct.gif" alt="'.&mt('yes').'" />';
+            } else {
+                $published = '<img src="'.$location.'/navmap.wrong.gif" alt="'.&mt('no').'" />';
+            }
+            $$displayref .= &Apache::loncommon::start_data_table_row().
+                            '<td><input type="checkbox" name="'.$chkname.'" value="'.&escape($showpath.$item).'" '.
+                            'onclick="javascript:checkResource(document.'.$formname.','."'$currelem'".')" '.
+                            $disabled.' /></td><td>';
+            for (my $i=0; $i<$currdepth; $i++) {
+                $$displayref .= "$whitespace\n";
+            }
+            $$displayref .= '<img '.$icon.$alttext.' />&nbsp;'.$item.'</td>'.
+                            '<td>'.&Apache::lonlocal::locallocaltime($files{$item}).'</td>'.
+                            '<td style="text-align: center;">'.$published.'</td>'.
+                            &Apache::loncommon::end_data_table_row()."\n";
+        }
+    }
+    $$lastcontainerref = $parent->{$currdepth};
+    return $count;
+}
+
+sub courseresource_options {
+    my ($formname,$numpub) = @_;
+    my %lt = &Apache::lonlocal::texthash(
+                                          'default' => 'System wide - can be used for any courses system wide',
+                                          'domain'  => 'Domain only - use limited to courses in the domain',
+                                          'custom'  => 'Customized right of use ...',
+                                          'public'  => 'Public - no authentication or authorization required for use',
+                                          'closed'  => 'Closed - XML source is closed to everyone',
+                                          'open'    => 'Open - XML source is open to people who want to use it',
+                                          'sel'     => 'Select',
+                                        );
+    my $output;
+    if ($numpub) {
+        $output .= '<div class="LC_left_float">'.
+                   '<fieldset><legend>'.&mt('Published Resources').'</legend>'.
+                   &mt('[quant,_1,file] in Course Authoring Space also exist in Resource Space.',
+                       $numpub).'</br />'.
+                   &mt('Publish copied files in selected Authoring Space?').': '."\n".
+                   '<label><input type="radio" name="respublish" checked="checked" value="1" />'.
+                   &mt('Yes').'</label>'."\n".
+                   '<label><input type="radio" name="respublish" value="0" />'.
+                   &mt('No').'</label>'."\n".
+                   '</fieldset></div>'."\n";
+    }
+    $output .= '<div class="LC_left_float">'.
+               '<fieldset><legend>'.&mt('Distribution to set in metadata').'</legend>'.
+               &mt('Copyright').': '.
+               '<select name="copyright" onchange="showHideCustom(this,'."'LC_customfile'".');">'."\n".
+               '<option value="default" selected="selected">'.$lt{'default'}.'</option>'."\n".
+               '<option value="domain">'.$lt{'domain'}.'</option>'."\n".
+               '<option value="public">'.$lt{'public'}.'</option>'."\n".
+               '<option value="custom">'.$lt{'custom'}.'</option>'."\n".
+               '</select><div id="LC_customfile" style="padding:0;clear:both;margin:0;border:0;display:none">'."\n".
+               '<input type="text" name="customrights" size="60" value="" />'.
+               '<a href="javascript:openbrowser('."'$formname','customrights','rights'".');">'.
+               $lt{'sel'}.'</a></div><br />'."\n".
+               &mt('Source').' :'.
+               '<select name="sourceavail">'."\n".
+               '<option value="closed" selected="selected">'.$lt{'closed'}.'</option>'."\n".
+               '<option value="open">'.$lt{'open'}.'</option>'."\n".
+               '</select><br />'."\n".
+               '</fieldset></div>'."\n";
+    return $output;
+}
+
+sub crsres_fixup_meta {
+    my ($dest,$coursenum,$coursedom,$ca,$cd,$copyright,$customdistfile,$sourceavail,$checkdeps) = @_;
+    return unless (ref($checkdeps) eq 'HASH');
+    if (open(my $fh,'<',$dest.'.meta')) {
+        my ($output,$now,$setsourceavail);
+        $now = time;
+        if (($dest =~ /\.(xml|html|htm|xhtml|xhtm)$/i) || ($dest =~ /$LONCAPA::assess_re/)) {
+            $setsourceavail = 1;
+        }
+        while (my $line=<$fh>) {
+            chomp($line);
+            if ($line eq "<authorspace>$coursenum:$coursedom</authorspace>") {
+                $output .= "<authorspace>$ca:$cd</authorspace>\n";
+            } elsif ($line eq '<copyright>custom</copyright>') {
+                $output .= "<copyright>$copyright</copyright>\n";
+            } elsif ($line =~ m{^<creationdate>\d+</creationdate>$}) {
+                $output .= "<creationdate>$now</creationdate>\n";
+            } elsif ($line eq "<customdistributionfile>/res/$coursedom/$coursenum/default.rights</customdistributionfile>") {
+                $output .= "<customdistributionfile>$customdistfile</customdistributionfile>\n";
+            } elsif ($line =~ m{^<sourceavail>(open|closed)</sourceavail>$}) {
+                if ($setsourceavail) {
+                    $output .= "<sourceavail>$sourceavail</sourceavail>\n";
+                }
+            } elsif ($line eq "<domain>$coursedom</domain>") {
+                $output .= "<domain>$cd</domain>\n";
+            } elsif ($line =~ m{^<lastrevisiondate>\d+</lastrevisiondate>$}) {
+                $output .= "<lastrevisiondate>$now</lastrevisiondate>\n";
+            } elsif ($line =~ m{^<modifyinguser>$match_username:$match_domain</modifyinguser>$}) {
+                $output .= "<modifyinguser>$env{'user.name'}:$env{'user.domain'}</modifyinguser>\n";
+            } elsif ($line eq "<owner>$coursenum:$coursedom</owner>") {
+                $output .= "<owner>$ca:$cd</owner>\n";
+            } elsif ($line =~ m{^<dependencies>(.+)</dependencies>$}) {
+                my @deps = split(/\s*,\s*/,$1);
+                my @newdeps;
+                my $changed = 0;
+                foreach my $dep (@deps) {
+                    if ($dep =~ m{^/res/$coursedom/$coursenum/(.+)$}) {
+                        my $rest = $1;
+                        push(@newdeps,"/res/$cd/$ca/$rest");
+                        $checkdeps->{$rest} = 1;
+                        $changed ++;
+                    } else {
+                        push(@newdeps,$dep);
+                    }
+                }
+                if ($changed) {
+                    $output .= '<dependencies>'.join(',',@newdeps).'</dependencies>'."\n";
+                }
+            } else {
+                $output .= "$line\n";
+            }
+        }
+        close($fh);
+        if (open(my $fh,'>',$dest.'.meta')) {
+            print $fh $output;
+            close($fh);
+        }
+    }
+}
+
+sub crsres_fixup {
+    my ($dest,$coursenum,$coursedom,$ca,$cd,$subdir) = @_;
+    my $outstring='';
+    my $changes = 0;
+    my @parser;
+    $parser[0]=HTML::LCParser->new($dest);
+    $parser[-1]->xml_mode(1);
+    my $token;
+    while (@parser) {
+        while ($token=$parser[-1]->get_token) {
+            if ($token->[0] eq 'S') {
+                my $tag=$token->[1];
+                my $lctag=lc($tag);
+                my %parms=%{$token->[2]};
+                foreach my $type ('src','href','background','bgimg') {
+                    foreach my $key (keys(%parms)) {
+                        if ($key =~ /^$type$/i) {
+                            next if (($lctag eq 'img') && ($type eq 'src') &&
+                                     ($parms{$key} =~ m{^data\:image/gif;base64,}));
+                            if ($parms{$key} =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
+                                $parms{$key} =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/}si;
+                                $changes ++;
+                            }
+                        }
+                    }
+                }
+                # probably a <randomlabel> image type <label>
+                # or a <image> tag inside <imageresponse> or <drawimage>
+                if (($lctag eq 'label' && defined($parms{'description'}))
+                    || ($lctag eq 'image') || ($lctag eq 'import')) {
+                    my $next_token=$parser[-1]->get_token();
+                    if ($next_token->[0] eq 'T') {
+                        $next_token->[1] =~ s/[\n\r\f]+//g;
+                        if ($next_token->[1] =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
+                            $next_token->[1] =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/}si;
+                            $changes ++;
+                        }
+                    }
+                    $parser[-1]->unget_token($next_token);
+                }
+                if ($lctag eq 'applet') {
+                    my $havecodebase=0;
+                    foreach my $key (keys(%parms)) {
+                        if (lc($key) eq 'codebase') {
+                            if ($parms{$key} =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
+                                $parms{$key} =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/}si;
+                                $changes ++;
+                            }
+                            $havecodebase = 1;
+                        }
+                    }
+                    unless ($havecodebase) {
+                        foreach my $key (keys(%parms)) {
+                            if ($key =~ /(archive|code|object)/i) {
+                                if ($parms{$key} =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
+                                    $parms{$key} =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/si};
+                                    $changes ++;
+                                }
+                            }
+                        }
+                    }
+                }
+                my $newparmstring='';
+                my $endtag='';
+                foreach my $parkey (keys(%parms)) {
+                    if ($parkey eq '/') {
+                        $endtag=' /';
+                    } else {
+                        my $quote=($parms{$parkey}=~/\"/?"'":'"');
+                        $newparmstring.=' '.$parkey.'='.$quote.$parms{$parkey}.$quote;
+                    }
+                }
+                if (!$endtag) { if ($token->[4]=~m:/>$:) { $endtag=' /'; }; }
+                $outstring.='<'.$tag.$newparmstring.$endtag.'>';
+                if ($lctag eq 'm' || $lctag eq 'answer' || $lctag eq 'display' ||
+                    $lctag eq 'tex') {
+                    $outstring.=&Apache::lonxml::get_all_text_unbalanced('/'.$lctag,\@parser);
+                } elsif ($lctag eq 'script') {
+                    if ($parms{'type'} eq 'loncapa/perl') {
+                        $outstring.=&Apache::lonxml::get_all_text_unbalanced('/'.$lctag,\@parser);
+                    } else {
+                        my $needsupdate;
+                        my $script = &Apache::lonxml::get_all_text_unbalanced('/'.$lctag,\@parser);
+                        if ($script =~ m{\.addMediaSrc\((["'])((?!\1).+)\1\);}) {
+                            my $src = $2;
+                            if ($src =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
+                                $needsupdate = 1;
+                            }
+                        }
+                        if ($script =~ /\(document,\s*(['"])script\1,\s*\[([^\]]+)\]\);/s) {
+                            my $scriptslist = $2;
+                            my @srcs = split(/\s*,\s*/,$scriptslist);
+                            foreach my $src (@srcs) {
+                                if ($src =~ /(["'])(?:(?!\1).)+\.js\1/) {
+                                    my $quote = $1;
+                                    my ($url) = ($src =~ m/\Q$quote\E([^$quote]+)\Q$quote\E/);
+                                    if ($url =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
+                                        $needsupdate = 1;
+                                    }
+                                }
+                            }
+                        }
+                        if ($script =~ m{loadScript\(\s*(['"])((?:(?!\1).)+\.js)\1,\s*function}is) {
+                            my $src = $2;
+                            if ($src =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
+                                $needsupdate = 1;
+                            }
+                        }
+                        if ($needsupdate) {
+                            $script =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/gsi};
+                            $changes ++;
+                        }
+                        $outstring .= $script;
+                    }
+                }
+            } elsif ($token->[0] eq 'E') {
+                if ($token->[2]) {
+                    unless ($token->[1] eq 'allow') {
+                        $outstring.='</'.$token->[1].'>';
+                    }
+                }
+            } else {
+                $outstring.=$token->[1];
+            }
+        }
+        pop(@parser);
+    }
+    if ($changes) {
+        if (open(my $fh,'>',$dest)) {
+            print $fh $outstring;
+            close($fh);
+        }
+    }
+}
+
 sub group_import {
     my ($coursenum, $coursedom, $folder, $container, $caller, $ltitoolsref, @files) = @_;
     my ($donechk,$allmaps,%hierarchy,%titles,%addedmaps,%removefrommap,
@@ -661,7 +1703,7 @@ sub group_import {
                 $url = $1;
                 my $marker = $2;
                 my $info = $3;
-                my ($toolid,%toolhash,%toolsettings);
+                my ($toolid,$toolprefix,$tooltype,%toolhash,%toolsettings);
                 my @extras = ('linktext','explanation','crslabel','crstitle','crsappend');
                 my @toolinfo = split(/:/,$info);
                 if ($residx) {
@@ -670,6 +1712,12 @@ sub group_import {
                 } else {
                     $toolid = shift(@toolinfo);
                 }
+                if ($toolid =~ /^c/) {
+                    $tooltype = 'crs';
+                    $toolprefix = 'c';
+                } else {
+                    $tooltype = 'dom';
+                }
                 $toolid =~ s/\D//g;
                 ($toolhash{'target'},$toolhash{'width'},$toolhash{'height'},
                  $toolhash{'linktext'},$toolhash{'explanation'},$toolhash{'crslabel'},
@@ -683,127 +1731,130 @@ sub group_import {
                     $toolhash{'gradable'} =~ s/\D+//g;
                 }
                 if (ref($ltitoolsref) eq 'HASH') {
-                    if (ref($ltitoolsref->{$toolid}) eq 'HASH') {
-                        my @deleted;
-                        $toolhash{'id'} = $toolid;
-                        if (($toolhash{'target'} eq 'iframe') || ($toolhash{'target'} eq 'tab') ||
-                            ($toolhash{'target'} eq 'window')) {
-                            if ($toolhash{'target'} eq 'window') {
-                                foreach my $item ('width','height') {
-                                    $toolhash{$item} =~ s/^\s+//;
-                                    $toolhash{$item} =~ s/\s+$//;
-                                    if ($toolhash{$item} =~ /\D/) {
-                                        delete($toolhash{$item});
-                                        if ($residx) {
-                                            if ($toolsettings{$item}) {
-                                                push(@deleted,$item);
+                    if (ref($ltitoolsref->{$tooltype}) eq 'HASH') {
+                        if (ref($ltitoolsref->{$tooltype}->{$toolid}) eq 'HASH') {
+                            my %tools = %{$ltitoolsref->{$tooltype}->{$toolid}};
+                            my @deleted;
+                            $toolhash{'id'} = $toolprefix.$toolid;
+                            if (($toolhash{'target'} eq 'iframe') || ($toolhash{'target'} eq 'tab') ||
+                                ($toolhash{'target'} eq 'window')) {
+                                if ($toolhash{'target'} eq 'window') {
+                                    foreach my $item ('width','height') {
+                                        $toolhash{$item} =~ s/^\s+//;
+                                        $toolhash{$item} =~ s/\s+$//;
+                                        if ($toolhash{$item} =~ /\D/) {
+                                            delete($toolhash{$item});
+                                            if ($residx) {
+                                                if ($toolsettings{$item}) {
+                                                    push(@deleted,$item);
+                                                }
                                             }
                                         }
                                     }
                                 }
-                            }
-                        } elsif ($residx) {
-                            $toolhash{'target'} = $toolsettings{'target'};
-                            if ($toolhash{'target'} eq 'window') {
-                                foreach my $item ('width','height') {
-                                    $toolhash{$item} = $toolsettings{$item};
+                            } elsif ($residx) {
+                                $toolhash{'target'} = $toolsettings{'target'};
+                                if ($toolhash{'target'} eq 'window') {
+                                    foreach my $item ('width','height') {
+                                        $toolhash{$item} = $toolsettings{$item};
+                                    }
+                                }
+                            } elsif (ref($tools{'display'}) eq 'HASH') {
+                                $toolhash{'target'} = $tools{'display'}{'target'};
+                                if ($toolhash{'target'} eq 'window') {
+                                    $toolhash{'width'} = $tools{'display'}{'width'};
+                                    $toolhash{'height'} = $tools{'display'}{'height'};
                                 }
                             }
-                        } elsif (ref($ltitoolsref->{$toolid}->{'display'}) eq 'HASH') {
-                            $toolhash{'target'} = $ltitoolsref->{$toolid}->{'display'}->{'target'};
-                            if ($toolhash{'target'} eq 'window') {
-                                $toolhash{'width'} = $ltitoolsref->{$toolid}->{'display'}->{'width'};
-                                $toolhash{'height'} = $ltitoolsref->{$toolid}->{'display'}->{'height'};
-                            }
-                        }
-                        if ($toolhash{'target'} eq 'iframe') {
-                            foreach my $item ('width','height','linktext','explanation') {
-                                delete($toolhash{$item});
-                                if ($residx) {
-                                    if ($toolsettings{$item}) {
-                                        push(@deleted,$item);
+                            if ($toolhash{'target'} eq 'iframe') {
+                                foreach my $item ('width','height','linktext','explanation') {
+                                    delete($toolhash{$item});
+                                    if ($residx) {
+                                        if ($toolsettings{$item}) {
+                                            push(@deleted,$item);
+                                        }
                                     }
                                 }
-                            }
-                        } elsif ($toolhash{'target'} eq 'tab') {
-                            foreach my $item ('width','height') {
-                                delete($toolhash{$item});
-                                if ($residx) {
-                                    if ($toolsettings{$item}) {
-                                        push(@deleted,$item);
+                            } elsif ($toolhash{'target'} eq 'tab') {
+                                foreach my $item ('width','height') {
+                                    delete($toolhash{$item});
+                                    if ($residx) {
+                                        if ($toolsettings{$item}) {
+                                            push(@deleted,$item);
+                                        }
                                     }
                                 }
                             }
-                        }
-                        if (ref($ltitoolsref->{$toolid}->{'crsconf'}) eq 'HASH') {
-                            foreach my $item ('label','title','linktext','explanation') {
-                                my $crsitem;
-                                if (($item eq 'label') || ($item eq 'title')) {
-                                    $crsitem = 'crs'.$item;
-                                } else {
-                                    $crsitem = $item;
-                                }
-                                if ($ltitoolsref->{$toolid}->{'crsconf'}->{$item}) {
-                                    $toolhash{$crsitem} =~ s/^\s+//;
-                                    $toolhash{$crsitem} =~ s/\s+$//;
-                                    if ($toolhash{$crsitem} eq '') {
+                            if (ref($tools{'crsconf'}) eq 'HASH') {
+                                foreach my $item ('label','title','linktext','explanation') {
+                                    my $crsitem;
+                                    if (($item eq 'label') || ($item eq 'title')) {
+                                        $crsitem = 'crs'.$item;
+                                    } else {
+                                        $crsitem = $item;
+                                    }
+                                    if ($tools{'crsconf'}{$item}) {
+                                        $toolhash{$crsitem} =~ s/^\s+//;
+                                        $toolhash{$crsitem} =~ s/\s+$//;
+                                        if ($toolhash{$crsitem} eq '') {
+                                            delete($toolhash{$crsitem});
+                                        }
+                                    } else {
                                         delete($toolhash{$crsitem});
                                     }
-                                } else {
-                                    delete($toolhash{$crsitem});
-                                }
-                                if (($residx) && (exists($toolsettings{$crsitem}))) {
-                                    unless (exists($toolhash{$crsitem})) {
-                                        push(@deleted,$crsitem);
+                                    if (($residx) && (exists($toolsettings{$crsitem}))) {
+                                        unless (exists($toolhash{$crsitem})) {
+                                            push(@deleted,$crsitem);
+                                        }
                                     }
                                 }
                             }
-                        }
-                        if ($toolhash{'passback'}) {
-                            my $gradesecret = UUID::Tiny::create_uuid_as_string(UUID_V4);
-                            $toolhash{'gradesecret'} = $gradesecret;
-                            $toolhash{'gradesecretdate'} = time;
-                        }
-                        if ($toolhash{'roster'}) {
-                            my $rostersecret = UUID::Tiny::create_uuid_as_string(UUID_V4);
-                            $toolhash{'rostersecret'} = $rostersecret;
-                            $toolhash{'rostersecretdate'} = time;
-                        }
-                        my $changegradable;
-                        if (($residx) && ($folder =~ /^default/)) {
-                            if ($toolsettings{'gradable'}) {
-                                unless (($toolhash{'gradable'}) || (defined($LONCAPA::map::zombies[$residx]))) {
-                                    push(@deleted,'gradable');
-                                    $changegradable = 1;
-                                }
-                            } elsif ($toolhash{'gradable'}) {
-                                $changegradable = 1;
+                            if ($toolhash{'passback'}) {
+                                my $gradesecret = UUID::Tiny::create_uuid_as_string(UUID_V4);
+                                $toolhash{'gradesecret'} = $gradesecret;
+                                $toolhash{'gradesecretdate'} = time;
+                            }
+                            if ($toolhash{'roster'}) {
+                                my $rostersecret = UUID::Tiny::create_uuid_as_string(UUID_V4);
+                                $toolhash{'rostersecret'} = $rostersecret;
+                                $toolhash{'rostersecretdate'} = time;
                             }
-                            if (($caller eq 'londocs') && (defined($LONCAPA::map::zombies[$residx]))) {
-                                $changegradable = 1;
+                            my $changegradable;
+                            if (($residx) && ($folder =~ /^default/)) {
                                 if ($toolsettings{'gradable'}) {
-                                    $toolhash{'gradable'} = 1;
+                                    unless (($toolhash{'gradable'}) || (defined($LONCAPA::map::zombies[$residx]))) {
+                                        push(@deleted,'gradable');
+                                        $changegradable = 1;
+                                    }
+                                } elsif ($toolhash{'gradable'}) {
+                                    $changegradable = 1;
+                                }
+                                if (($caller eq 'londocs') && (defined($LONCAPA::map::zombies[$residx]))) {
+                                    $changegradable = 1;
+                                    if ($toolsettings{'gradable'}) {
+                                        $toolhash{'gradable'} = 1;
+                                    }
                                 }
                             }
-                        }
-                        my $putres = &Apache::lonnet::put('exttool_'.$marker,\%toolhash,$coursedom,$coursenum);
-                        if ($putres eq 'ok') {
-                            if (@deleted) {
-                                &Apache::lonnet::del('exttool_'.$marker,\@deleted,$coursedom,$coursenum);
-                            }
-                            if (($changegradable) && ($folder =~ /^default/)) {
-                                my $val;
-                                if ($toolhash{'gradable'}) {
-                                    $val = 'yes';
-                                } else {
-                                    $val = 'no';
+                            my $putres = &Apache::lonnet::put('exttool_'.$marker,\%toolhash,$coursedom,$coursenum);
+                            if ($putres eq 'ok') {
+                                if (@deleted) {
+                                    &Apache::lonnet::del('exttool_'.$marker,\@deleted,$coursedom,$coursenum);
                                 }
-                                &LONCAPA::map::storeparameter($residx,'parameter_0_gradable',$val,
-                                                              'string_yesno');
-                                &remember_parms($residx,'gradable','set',$val);
+                                if (($changegradable) && ($folder =~ /^default/)) {
+                                    my $val;
+                                    if ($toolhash{'gradable'}) {
+                                        $val = 'yes';
+                                    } else {
+                                        $val = 'no';
+                                    }
+                                    &LONCAPA::map::storeparameter($residx,'parameter_0_gradable',$val,
+                                                                  'string_yesno');
+                                    &remember_parms($residx,'gradable','set',$val);
+                                }
+                            } else {
+                                return (&mt('Failed to save update to external tool.'),1);
                             }
-                        } else {
-                            return (&mt('Failed to save update to external tool.'),1);
                         }
                     }
                 }
@@ -833,26 +1884,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 +1926,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 +1967,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);
         }
@@ -1148,7 +2200,13 @@ sub docs_change_log {
 	}
 	$r->print('</ul>');
 	if ($docslog{$id}{'logentry'}{'parameter_res'}) {
-	    $r->print(&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'parameter_res'}))[0]).':<ul>');
+            my ($title,$url) = split(/\:/,$docslog{$id}{'logentry'}{'parameter_res'},3);
+            if ($title eq '') {
+                ($title) = ($url =~ m{/([^/]+)$});
+            } elsif ($is_supp) {
+                $title = &Apache::loncommon::parse_supplemental_title($title);
+            }
+            $r->print(&LONCAPA::map::qtescape($title).':<ul>');
 	    foreach my $parameter ('randompick','hiddenresource','encrypturl','randomorder','gradable') {
 		if ($docslog{$id}{'logentry'}{'parameter_action_'.$parameter}) {
 # FIXME: internationalization seems wrong here
@@ -1217,13 +2275,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;
+                }
+            }
         }
     }
 
@@ -1232,7 +2296,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);
@@ -1245,7 +2309,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 '') {
@@ -1334,7 +2404,7 @@ sub print_paste_buffer {
     }
 
     my @currpaste = split(/,/,$env{'docs.markedcopies'});
-    my ($pasteitems,@pasteable);
+    my ($pasteitems,@pasteable,$same_institution,$checkedsameinst);
     my $clipboardcount = 0;
 
 # Construct identifiers for current contents of user's paste buffer
@@ -1347,11 +2417,13 @@ sub print_paste_buffer {
             ($url ne '')) {
             $clipboardcount ++;
             my ($is_external,$othercourse,$fromsupp,$is_uploaded_map,$parent,
-                $canpaste,$nopaste,$othercrs,$areachange,$is_exttool);
+                $canpaste,$nopaste,$othercrs,$areachange,$is_exttool,$toolcdom,
+                $toolcnum,$marker);
             my $extension = (split(/\./,$env{'docs.markedcopy_url_'.$suffix}))[-1];
             if ($url =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?:&colon;|:))//} ) {
                 $is_external = 1;
-            } elsif ($url =~ m{^/adm/$match_domain/$match_courseid/\d+/ext\.tool$}) {
+            } elsif ($url =~ m{^/adm/($match_domain)/($match_courseid)/(\d+)/ext\.tool$}) {
+                ($toolcdom,$toolcnum,$marker) = ($1,$2,$3);
                 $is_exttool = 1;
             }
             if ($folder =~ /^supplemental/) {
@@ -1389,17 +2461,56 @@ sub print_paste_buffer {
                     if ($cid ne $env{'request.course.id'}) {
                         my ($srcdom,$srcnum) = split(/_/,$cid);
                         if ($env{"user.priv.cm./$srcdom/$srcnum"} =~ /\Q:mdc&F\E/) {
-                            if (($is_exttool) && ($srcdom ne $coursedom)) {
-                                $canpaste = 0;
-                                $nopaste = &mt('Paste from another domain unavailable.');
-                            } else {
-                                $othercrs = '<br />'.&mt('(from another course)');
+                            if ($is_exttool) {
+                                if ($toolcdom ne $coursedom) {
+                                    $canpaste = 0;
+                                    $nopaste = &mt('Paste from another domain unavailable.');
+                                } elsif ($toolcnum ne $coursenum) {
+                                    my %toolsettings =
+                                        &Apache::lonnet::dump('exttool_'.$marker,$toolcdom,$toolcnum);
+                                    my %tooltypes = &Apache::loncommon::usable_exttools();
+                                    if ((($toolsettings{'id'} =~ /^c\d+$/) && (!$tooltypes{'crs'})) ||
+                                        (($toolsettings{'id'} =~ /^\d+$/) && (!$tooltypes{'dom'}))) {
+                                        $canpaste = 0;
+                                        $nopaste = &mt('Paste from another course unavailable.');
+                                    } elsif ($toolsettings{'id'} =~ /^c\d+$/) {
+                                        unless ($checkedsameinst) {
+                                            my $primary_id = &Apache::lonnet::domain($coursedom,'primary');
+                                            my $intdom = &Apache::lonnet::internet_dom($primary_id);
+                                            if ($intdom ne '') {
+                                                my $internet_names =
+                                                    &Apache::lonnet::get_internet_names($Apache::lonnet::perlvar{'lonHostID'});
+                                                if (ref($internet_names) eq 'ARRAY') {
+                                                    if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
+                                                        $same_institution = 1;
+                                                    }
+                                                }
+                                            }
+                                            $checkedsameinst = 1;
+                                        }
+                                        if ($same_institution) {
+                                            $othercrs = '<br />'.&mt('(from another course)');
+                                        } else {
+                                            $nopaste = &mt('Paste from another course unavailable.');
+                                        }
+                                    } else {
+                                        $othercrs = '<br />'.&mt('(from another course)');
+                                    }
+                                }
                             }
                         } else {
                             $canpaste = 0;
                             $nopaste = &mt('Paste from another course unavailable.');
                         }
                     }
+                } elsif ($url =~ m{/res/($match_domain)/($match_username)/}) {
+                    my ($audom,$auname) = ($1,$2);
+                    unless (($auname eq $coursenum) && ($audom eq $coursedom)) {
+                        if (&Apache::lonnet::is_course($audom,$auname)) {
+                            $canpaste = 0;
+                            $nopaste = &mt('Paste from another course unavailable.');
+                        }
+                    }
                 }
                 if ($canpaste) {
                     push(@pasteable,$suffix);
@@ -1442,7 +2553,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;
@@ -1692,9 +2803,12 @@ sub do_paste_from_buffer {
         return();
     }
 
-    my (%msgs,%before,%after,@dopaste,%is_map,%notinsupp,%notincrs,%notindom,%duplicate,
-        %prefixchg,%srcdom,%srcnum,%srcmapidx,%marktomove,$save_err,$lockerrors,$allresult);
-
+    my (%msgs,%before,%after,@dopaste,%is_map,%notinsupp,%notincrs,%notindom,
+        %othcrstool,%othcrsres,%duplicate,%prefixchg,%srcdom,%srcnum,%srcmapidx,
+        %marktomove,$save_err,$lockerrors,$allresult,%currcrsltitools,
+        %currltititles,$currltimax,$gotcrsltitools);
+    $currltimax = 0;
+    $gotcrsltitools = 0;
     foreach my $suffix (@topaste) {
         my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url_'.$suffix});
         my $cid=&LONCAPA::map::qtescape($env{'docs.markedcopy_crs_'.$suffix});
@@ -1733,13 +2847,53 @@ sub do_paste_from_buffer {
                 }
             }
 # When buffer was populated using an active role in a different course
-# disallow pasting of External Tool if course is in a different domain.
-            if (($url =~ m{/ext\.tool$}) && ($srcd ne $coursedom)) {
-                $notindom{$suffix} = 1;
-                next;
+# disallow pasting of External Tool if course is in a different domain,
+# or if External Tool use is not permitted in this course.
+            if ($url =~ m{^/adm/($match_domain)/($match_courseid)/(\d+)/ext\.tool$}) {
+                my ($toolcdom,$toolcnum,$marker) = ($1,$2,$3);
+                if ($toolcdom ne $coursedom) {
+                    $notindom{$suffix} = 1;
+                    next;
+                } elsif ($toolcnum ne $coursenum) {
+                    my %toolsettings =
+                        &Apache::lonnet::dump('exttool_'.$marker,$toolcdom,$toolcnum);
+                    my %tooltypes = &Apache::loncommon::usable_exttools();
+                    if ((($toolsettings{'id'} =~ /^c\d+$/) && (!$tooltypes{'crs'})) ||
+                        (($toolsettings{'id'} =~ /^\d+$/) && (!$tooltypes{'dom'}))) {
+                        $othcrstool{$suffix} = 1;
+                        next;
+                    }
+                    if ($toolsettings{'id'} =~ /^c\d+$/) {
+                        unless ($gotcrsltitools) {
+                            %currcrsltitools =
+                                &Apache::lonnet::get_course_lti($coursenum,$coursedom,'consumer');
+                            foreach my $item (sort(keys(%currcrsltitools))) {
+                                if (ref($currcrsltitools{$item}) eq 'HASH') {
+                                    $currltimax ++;
+                                    if (ref($currltititles{$currcrsltitools{$item}{'title'}}) eq 'ARRAY') {
+                                        push(@{$currltititles{$currcrsltitools{$item}{'title'}}},$item);
+                                    } else {
+                                        $currltititles{$currcrsltitools{$item}{'title'}} = [$item];
+                                    }
+                                }
+                            }
+                            $gotcrsltitools = 1;
+                        }
+                    }
+                }
             }
             $srcdom{$suffix} = $srcd;
             $srcnum{$suffix} = $srcn;
+        } elsif ($url =~ m{^/res/($match_domain)/($match_courseid)/}) {
+            my ($audom,$auname) = ($1,$2);
+# When buffer was populated using an active role in a different course
+# disallow pasting of published resources from Course Authoring Space
+            unless (($auname eq $coursenum) && ($audom eq $coursedom)) {
+                if (&Apache::lonnet::is_course($audom,$auname)) {
+                    $othcrsres{$suffix} = 1;
+                    next;
+                }
+            }
         }
         $srcmapidx{$suffix} = $mapidx;
         push(@dopaste,$suffix);
@@ -1790,7 +2944,9 @@ sub do_paste_from_buffer {
     %msgs = &Apache::lonlocal::texthash (
                 notinsupp => 'Paste failed: content type is not supported within Supplemental Content',
                 notincrs  => 'Paste failed: Item is from a different course which you do not have rights to edit.',
-                notindom  => 'Paste failed: Item is an external tool from a course in a different donain.', 
+                notindom  => 'Paste failed: Item is an external tool from a course in a different domain.',
+                othcrstool => 'Paste failed: Item is an external tool from a different course, for which use is not allowed in this course.',
+                othcrsres => 'Paste failed: Item is a course-authored resource from a different course',
                 duplicate => 'Paste failed: only one instance of a particular published sequence or page is allowed within each course.',
             );
 
@@ -1819,14 +2975,9 @@ sub do_paste_from_buffer {
 # Retrieve information about all course maps in main content area 
 
     my $allmaps = {};
-    if ($folder =~ /^default/) {
-        $allmaps =
-            &Apache::loncommon::allmaps_incourse($coursedom,$coursenum,
-                                                 $env{"course.$env{'request.course.id'}.home"},
-                                                 $env{'request.course.id'});
-    }
-
-    my (@toclear,%mapurls,%lockerrs,%msgerrs,%results);
+    my (@toclear,%mapurls,%lockerrs,%msgerrs,%results,$donechk,
+        @updatetoolsenc,$updatetoolscache,$checkedsameinst,
+        $same_institution);
 
 # Loop over the items to paste
     foreach my $suffix (@dopaste) {
@@ -1844,6 +2995,13 @@ sub do_paste_from_buffer {
         if ($is_map{$suffix}) {
 # If pasting a map, check if map contains other maps
             my (%hierarchy,%titles);
+            if (($folder =~ /^default/) && (!$donechk)) {
+                $allmaps =
+                    &Apache::loncommon::allmaps_incourse($coursedom,$coursenum,
+                                                         $env{"course.$env{'request.course.id'}.home"},
+                                                         $env{'request.course.id'});
+                $donechk = 1;
+            }
             &contained_map_check($url,$folder,$coursenum,$coursedom,
                                  \%removefrommap,\%removeparam,\%addedmaps,
                                  \%hierarchy,\%titles,$allmaps);
@@ -1909,7 +3067,7 @@ sub do_paste_from_buffer {
                          cnum => $coursenum,
                        );
             if ($prefix eq 'ext.tool') {
-                if ($prefixchg{$suffix} eq 'docstosupp') { 
+                if ($prefixchg{$suffix} eq 'docstosupp') {
                     $info{'delgradable'} = 1;
                 }
             }
@@ -1918,12 +3076,27 @@ sub do_paste_from_buffer {
                     $fromothercrs = 1;
                     $info{'cdom'} = $srcdom{$suffix};
                     $info{'cnum'} = $srcnum{$suffix};
+                    unless ($checkedsameinst) {
+                        my $primary_id = &Apache::lonnet::domain($coursedom,'primary');
+                        my $intdom = &Apache::lonnet::internet_dom($primary_id);
+                        if ($intdom ne '') {
+                            my $internet_names =
+                                &Apache::lonnet::get_internet_names($Apache::lonnet::perlvar{'lonHostID'});
+                            if (ref($internet_names) eq 'ARRAY') {
+                                if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
+                                    $same_institution = 1;
+                                }
+                            }
+                        }
+                        $checkedsameinst = 1;
+                    }
                 }
             }
             unless (($env{'form.docs.markedcopy_options_'.$suffix} eq 'move') && (!$fromothercrs)) {
                 my (%lockerr,$msg);
                 my ($newurl,$result,$errtext) =
-                    &dbcopy(\%info,$coursedom,$coursenum,\%lockerr);
+                    &dbcopy(\%info,$coursedom,$coursenum,\%lockerr,\%currltititles,
+                            \$currltimax,\@updatetoolsenc,\$updatetoolscache,$same_institution);
                 if ($result eq 'ok') {
                     $url = $newurl;
                     $title=&mt('Copy of').' '.$title;
@@ -2005,7 +3178,7 @@ sub do_paste_from_buffer {
                                           $coursedom,$coursenum,$template,$newidx,"$folder.$container");
                 }
             } elsif ($url =~ /ext\.tool$/) {
-                if (($newidx) && ($folder=~/^default/)) { 
+                if (($newidx) && ($folder=~/^default/)) {
                     my $marker = (split(m{/},$url))[4];
                     my %toolsettings = &Apache::lonnet::dump('exttool_'.$marker,$coursedom,$coursenum);
                     my $val = 'no';
@@ -2092,6 +3265,10 @@ sub do_paste_from_buffer {
             }
         }
     }
+    if (($updatetoolscache) || (@updatetoolsenc)) {
+        &update_ltitools_caches($coursedom,$coursenum,$updatetoolscache,
+                                \@updatetoolsenc);
+    }
     &clear_from_buffer(\@toclear,\@currpaste);
     my $msgsarray;
     foreach my $suffix (keys(%msgs)) {
@@ -2140,6 +3317,30 @@ sub clear_from_buffer {
     return $numdel;
 }
 
+sub update_ltitools_caches {
+    my ($coursedom,$coursenum,$updatetoolscache,$updatetoolsenc) = @_;
+    my $hashid=$coursedom.'_'.$coursenum;
+    if ($updatetoolscache) {
+        &Apache::lonnet::devalidate_cache_new('courseltitools',$hashid);
+    }
+    if ((ref($updatetoolsenc) eq 'ARRAY') &&
+        (@{$updatetoolsenc})) {
+        my @ids=&Apache::lonnet::current_machine_ids();
+        my $updatedone;
+        foreach my $lonhost (@{$updatetoolsenc}) {
+            if (grep(/^\Q$lonhost\E$/,@ids)) {
+                unless ($updatedone) {
+                    &Apache::lonnet::devalidate_cache_new('crsltitoolsenc',$hashid);
+                }
+                $updatedone = 1;
+            } else {
+                &Apache::lonnet::remote_devalidate_cache($lonhost,["crsltitoolsenc:$hashid"]);
+            }
+        }
+    }
+    return;
+}
+
 sub get_newmap_url {
     my ($url,$folder,$prefixchg,$coursedom,$coursenum,$srcdom,$srcnum,
         $titleref,$allmaps,$newurls) = @_;
@@ -2201,7 +3402,8 @@ sub get_newmap_url {
 }
 
 sub dbcopy {
-    my ($dbref,$coursedom,$coursenum,$lockerrorsref) = @_;
+    my ($dbref,$coursedom,$coursenum,$lockerrorsref,$currltititles,
+        $currltimax,$updatetoolsenc,$updatetoolscache,$same_institution) = @_;
     my ($url,$result,$errtext);
     if (ref($dbref) eq 'HASH') {
         $url = $dbref->{'src'};
@@ -2245,6 +3447,117 @@ sub dbcopy {
                     my %contents=&Apache::lonnet::dump($db_name,
                                                        $dbref->{'cdom'},
                                                        $dbref->{'cnum'});
+                    my ($toolcopyerror,$toolpassback,$toolroster,%toolinfo,$oldtoolid,$defincrs);
+                    if ($url eq '/adm/'.$dbref->{'cdom'}.'/'.$dbref->{'cnum'}."/$marker/ext.tool") {
+                        if ($contents{'id'} =~ /^(|c)(\d+)$/) {
+                            $oldtoolid = $2;
+                            if ($1 eq 'c') {
+                                $defincrs = 1;
+                                %toolinfo =
+                                    &Apache::lonnet::get('ltitools',[$oldtoolid],$dbref->{'cdom'},$dbref->{'cnum'});
+                            } else {
+                                %toolinfo= &Apache::lonnet::get_domain_lti($dbref->{'cdom'},'consumer');
+                            }
+                            if (ref($toolinfo{$oldtoolid}) eq 'HASH') {
+                                if ($toolinfo{$oldtoolid}{'passback'}) {
+                                    $toolpassback = 1;
+                                }
+                                if ($toolinfo{$oldtoolid}{'roster'}) {
+                                    $toolroster = 1;
+                                }
+                            } else {
+                                $toolcopyerror = 1;
+                                $errtext = &mt('Could not retrieve original settings for pasted external tool.');
+                            }
+                        }
+                        unless (($dbref->{'cnum'} eq $coursenum) && ($dbref->{'cdom'} eq $coursedom)) {
+                            $url = "/adm/$coursedom/$coursenum/$marker/ext.tool";
+                            if ($contents{'crstitle'} ne '') {
+                                $contents{'crstitle'} = $env{'course.'.$coursedom.'_'.$coursenum.'.description'};
+                            }
+                            if (($defincrs) && (!$toolcopyerror)) {
+                                my %newtool;
+                                my $oldcdom = $dbref->{'cdom'};
+                                my $oldcnum = $dbref->{'cnum'};
+                                my $title = $toolinfo{$oldtoolid}{'title'};
+                                if (ref($currltititles) eq 'HASH') {
+                                    if (exists($currltititles->{$title})) {
+                                        $title .= ' (copied from another course)';
+                                    }
+                                }
+                                my ($newid,$iderror) =
+                                    &Apache::lonnet::get_ltitools_id('course',$coursedom,$coursenum,$title);
+                                if ($newid =~ /^\d+$/) {
+                                    %{$newtool{$newid}} = %{$toolinfo{$oldtoolid}};
+                                    $newtool{$newid}{'title'} = $title;
+                                    if (ref($currltimax)) {
+                                        $newtool{$newid}{'order'} = $$currltimax;
+                                    }
+                                    if ($newtool{$newid}{'image'} =~ m{^\Q/uploaded/$oldcdom/$oldcnum/toollogo/$oldtoolid/\E([^/]+)$}) {
+                                        my $fname = $1;
+                                        my $content = &Apache::lonnet::getfile($newtool{$newid}{'image'});
+                                        if ($content eq '-1') {
+                                            delete($newtool{$newid}{'image'});
+                                        } else {
+                                            $env{'form.'.$suffix.'.image'} = $content;
+                                            my $newlogo =
+                                                &Apache::lonnet::finishuserfileupload($coursenum,$coursedom,$suffix.'.image',"toollogo/$newid/$fname");
+                                            delete($env{'form.'.$suffix.'.image'});
+                                            if ($newlogo =~ m{^/uploaded/}) {
+                                                $newtool{$newid}{'image'} = $newlogo;
+                                            } else {
+                                                delete($newtool{$newid}{'image'});
+                                            }
+                                        }
+                                    }
+                                    my $newusable;
+                                    if ($same_institution) {
+                                        my %oldtoolsenc = &Apache::lonnet::eget('nohist_toolsenc',[$oldtoolid],$oldcdom,$oldcnum);
+                                        if (ref($oldtoolsenc{$oldtoolid}) eq 'HASH') {
+                                            my %newtoolsenc;
+                                            %{$newtoolsenc{$newid}} = %{$oldtoolsenc{$oldtoolid}};
+                                            my $putres = &Apache::lonnet::put('nohist_toolsenc',\%newtoolsenc,$coursedom,$coursenum,1);
+                                            if ($putres eq 'ok') {
+                                                if (ref($updatetoolsenc) eq 'ARRAY') {
+                                                    my $newhome = &Apache::lonnet::homeserver($coursenum,$coursedom);
+                                                    unless (grep(/^\Q$newhome\E$/,@{$updatetoolsenc})) {
+                                                        push(@{$updatetoolsenc},$newhome);
+                                                    }
+                                                }
+                                                $newusable = 1;
+                                            }
+                                        }
+                                    }
+                                    if ($newtool{$newid}{'usable'}) {
+                                        unless ($newusable) {
+                                            delete($newtool{$newid}{'usable'});
+                                        }
+                                    }
+                                    my $putres = &Apache::lonnet::put('ltitools',\%newtool,$coursedom,$coursenum);
+                                    if ($putres eq 'ok') {
+                                        $contents{'id'} = "c$newid";
+                                        if (ref($updatetoolscache)) {
+                                            $$updatetoolscache ++;
+                                        }
+                                        if (ref($currltititles->{$title}) eq 'ARRAY') {
+                                            push(@{$currltititles->{$title}},$newid);
+                                        } else {
+                                            $currltititles->{$title} = [$newid];
+                                        }
+                                        if (ref($currltimax)) {
+                                            $$currltimax ++;
+                                        }
+                                    } else {
+                                        $toolcopyerror = 1;
+                                        $errtext = &mt('Unable to save external tool definition in Course Settings.');
+                                    }
+                                } else {
+                                    $toolcopyerror = 1;
+                                    $errtext = &mt('Unable to retrieve new tool ID when adding external tool definition to Course Settings.');
+                                }
+                            }
+                        }
+                    }
                     if (exists($contents{'uploaded.photourl'})) {
                         my $photo = $contents{'uploaded.photourl'};
                         my ($subdir,$fname) =
@@ -2264,13 +3577,40 @@ sub dbcopy {
                         }
                     }
                     $db_name =~ s{_\d*$ }{_$suffix}x;
-                    if (($prefix eq 'exttool') && ($dbref->{'delgradable'}) && ($contents{'gradable'})) {
-                        delete($contents{'gradable'});
+                    if ($prefix eq 'exttool') {
+                        unless ($toolcopyerror) {
+                            foreach my $key ('oldgradesecret','gradesecret','gradesecretdate','oldrostersecret','rostersecret','rostersecretdate') {
+                                if (exists($contents{$key})) {
+                                    delete($contents{$key});
+                                }
+                            }
+                            if ($dbref->{'delgradable'}) {
+                                if (exists($contents{'gradable'})) {
+                                    delete($contents{'gradable'});
+                                }
+                            }
+                            if ($toolpassback) {
+                                if ($contents{'gradable'}) {
+                                    my $gradesecret = UUID::Tiny::create_uuid_as_string(UUID_V4);
+                                    $contents{'gradesecret'} = $gradesecret;
+                                    $contents{'gradesecretdate'} = time;
+                                }
+                            }
+                            if ($toolroster) {
+                                my $rostersecret = UUID::Tiny::create_uuid_as_string(UUID_V4);
+                                $contents{'rostersecret'} = $rostersecret;
+                                $contents{'rostersecretdate'} = time;
+                            }
+                        }
                     }
-                    $result=&Apache::lonnet::put($db_name,\%contents,
-                                                 $coursedom,$coursenum);
-                    if ($result eq 'ok') {
-                        $url =~ s{/(\d*)/(smppg|bulletinboard|ext\.tool)$}{/$suffix/$2}x;
+                    if (($prefix eq 'exttool') && ($toolcopyerror)) {
+                        $result = 'error';
+                    } else {
+                        $result=&Apache::lonnet::put($db_name,\%contents,
+                                                     $coursedom,$coursenum);
+                        if ($result eq 'ok') {
+                            $url =~ s{/(\d*)/(smppg|bulletinboard|ext\.tool)$}{/$suffix/$2}x;
+                        }
                     }
                 }
                 if (($freedlock ne 'ok') && (ref($lockerrorsref) eq 'HASH')) {
@@ -2329,7 +3669,9 @@ sub copy_templated_files {
         my @simpleprobqtypes = qw(radio option string essay numerical);
         my $qtype=$srcparms{$srcprefix.'questiontype'};
         if (grep(/^\Q$qtype\E$/,@simpleprobqtypes)) {
-            my %newdata;
+            my %newdata = (
+                $newprefix.'questiontype' => $qtype,
+            );
             foreach my $type (@simpleprobqtypes) {
                 if ($type eq $qtype) {
                     $newdata{"$weightprefix.$type.weight"}=1;
@@ -2423,18 +3765,37 @@ sub contained_map_check {
             if ($token->[1] eq 'resource') {
                 next if ($token->[2]->{'type'} eq 'zombie');
                 my $ressrc = $token->[2]->{'src'};
-                if ($ressrc =~ m{^/adm/($match_domain)/$match_courseid/\d+/ext\.tool$}) {
-                    my $srcdom = $1;
+                if ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/(\d+)/ext\.tool$}) {
+                    my ($srcdom,$srcnum,$marker) = ($1,$2,$3);
                     unless ($srcdom eq $coursedom) {
                         $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc;
                         next;
                     }
+                    unless ($srcnum eq $coursenum) {
+                        my %toolsettings =
+                            &Apache::lonnet::dump('exttool_'.$marker,$srcdom,$srcnum);
+                        my %tooltypes = &Apache::loncommon::usable_exttools();
+                        if ((($toolsettings{'id'} =~ /^c\d+$/) && (!$tooltypes{'crs'})) ||
+                            (($toolsettings{'id'} =~ /^\d+$/) && (!$tooltypes{'dom'}))) {
+                            $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc;
+                            next;
+                        }
+                    }
                 } elsif ($folder =~ /^supplemental/) {
                     unless (&supp_pasteable($ressrc)) {
                         $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc;
                         next;
                     }
                 }
+                if ($ressrc =~ m{^/res/($match_domain)/($match_courseid)/}) {
+                    my ($srcdom,$srcnum) = ($1,$2);
+                    unless (($srcnum eq $coursenum) && ($srcdom eq $coursedom)) {
+                        if (&Apache::lonnet::is_course($srcdom,$srcnum)) {
+                            $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc;
+                            next;
+                        }
+                    }
+                }
                 if ($ressrc =~ m{^/(res|uploaded)/.+\.(sequence|page)$}) {
                     if ($1 eq 'uploaded') {
                         $hierarchy->{$url}{$token->[2]->{'id'}} = $ressrc;
@@ -2558,7 +3919,7 @@ sub url_paste_fixups {
                 my $rem = $3;
                 my ($is_exttool,$exttoolchg);
                 if ($rem =~ m{\d+/ext\.tool$}) {
-                    $is_exttool = 1;     
+                    $is_exttool = 1;
                 }
                 if (($srcdom ne $cdom) || ($srcnum ne $cnum)) {
                     $rewrites->{$oldurl}{$id} = $ressrc;
@@ -2569,7 +3930,7 @@ sub url_paste_fixups {
                     if ($is_exttool) {
                         $exttoolchg = 1;
                     }
-                } elsif (($rem =~ m{\d+/ext\.tool$}) &&
+                } elsif (($is_exttool) &&
                          ($env{'form.docs.markedcopy_options'} ne 'move')) {
                     $dbcopies->{$oldurl}{$id}{'src'} = $ressrc;
                     $dbcopies->{$oldurl}{$id}{'cdom'} = $srcdom;
@@ -2629,7 +3990,9 @@ sub apply_fixups {
         $oldurl,$url,$caller) = @_;
     my (%rewrites,%zombies,%removefrommap,%removeparam,%dbcopies,%retitles,
         %params,%newsubdir,%before,%after,%copies,%docmoves,%mapmoves,@msgs,
-        %resdatacopy,%lockerrors,$lockmsg);
+        %resdatacopy,%lockerrors,$lockmsg,%currcrsltitools,$gotcrsltitools,
+        %currltititles,$currltimax);
+    $currltimax = 0;
     if (ref($updated) eq 'HASH') {
         if (ref($updated->{'rewrites'}) eq 'HASH') {
             %rewrites = %{$updated->{'rewrites'}};
@@ -2745,6 +4108,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;
@@ -2771,6 +4143,7 @@ sub apply_fixups {
                 }
             }
         }
+        my ($updatetoolscache,@updatetoolsenc,$same_institution,$checkedsameinst);
         foreach my $key (keys(%updates)) {
             my (%torewrite,%toretitle,%toremove,%remparam,%currparam,%zombie,%newdb);
             if (ref($rewrites{$key}) eq 'HASH') {
@@ -2791,10 +4164,63 @@ sub apply_fixups {
             if (ref($dbcopies{$key}) eq 'HASH') {
                 foreach my $idx (keys(%{$dbcopies{$key}})) {
                     if (ref($dbcopies{$key}{$idx}) eq 'HASH') {
+                        my $oldurl = $dbcopies{$key}{$idx}{'src'};
+                        my $oldcdom = $dbcopies{$key}{$idx}{'cdom'};
+                        my $oldcnum = $dbcopies{$key}{$idx}{'cnum'};
+                        my $oldmarker;
+                        if ($oldurl =~ m{^\Q/adm/$oldcdom/$oldcnum/\E(\d+)/ext\.tool$}) {
+                            $oldmarker = $1;
+                            unless (($gotcrsltitools) ||
+                                    (($oldcnum eq $cnum) && ($oldcdom eq $cdom))) {
+                                my %oldtoolsettings=&Apache::lonnet::dump('exttool_'.$oldmarker,$oldcdom,$oldcnum);
+                                if ($oldtoolsettings{'id'} =~ /^c\d+$/) {
+                                    unless ($gotcrsltitools) {
+                                        %currcrsltitools =
+                                            &Apache::lonnet::get_course_lti($cnum,$cdom,'consumer');
+                                        foreach my $item (sort(keys(%currcrsltitools))) {
+                                            if (ref($currcrsltitools{$item}) eq 'HASH') {
+                                                $currltimax ++;
+                                                if (ref($currltititles{$currcrsltitools{$item}{'title'}}) eq 'ARRAY') {
+                                                    push(@{$currltititles{$currcrsltitools{$item}{'title'}}},$item);
+                                                } else {
+                                                    $currltititles{$currcrsltitools{$item}{'title'}} = [$item];
+                                                }
+                                            }
+                                        }
+                                        $gotcrsltitools = 1;
+                                    }
+                                    unless ($checkedsameinst) {
+                                        my $primary_id = &Apache::lonnet::domain($cdom,'primary');
+                                        my $intdom = &Apache::lonnet::internet_dom($primary_id);
+                                        if ($intdom ne '') {
+                                            my $internet_names =
+                                                &Apache::lonnet::get_internet_names($Apache::lonnet::perlvar{'lonHostID'});
+                                            if (ref($internet_names) eq 'ARRAY') {
+                                                if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
+                                                    $same_institution = 1;
+                                                }
+                                            }
+                                        }
+                                        $checkedsameinst = 1;
+                                    }
+                                }
+                            }
+                        }
                         my ($newurl,$result,$errtext) =
-                            &dbcopy($dbcopies{$key}{$idx},$cdom,$cnum,\%lockerrors);
+                            &dbcopy($dbcopies{$key}{$idx},$cdom,$cnum,\%lockerrors,\%currltititles,
+                                    \$currltimax,\@updatetoolsenc,\$updatetoolscache,$same_institution);
                         if ($result eq 'ok') {
                             $newdb{$idx} = $newurl;
+                            if ($newurl =~ /ext\.tool$/) {
+                                if ($torewrite{$idx} eq "/adm/$oldcdom/$oldcnum/$oldmarker/ext.tool") {
+                                    if ($newurl =~ m{^\Q/adm/$cdom/$cnum/\E(\d+)/ext.tool$}) {
+                                        my $newmarker = $1;
+                                        unless ($oldmarker eq $newmarker) {
+                                            $torewrite{$idx} = "/adm/$oldcdom/$oldcnum/$newmarker/ext.tool";
+                                        }
+                                    }
+                                }
+                            }
                         } elsif (ref($errors) eq 'HASH') {
                             $errors->{$key} = 1;
                         }
@@ -2803,9 +4229,7 @@ sub apply_fixups {
                 }
             }
             if (ref($resdatacopy{$key}) eq 'HASH') {
-                if ($newsubdir{$key}) {
-
-                }
+                my ($gotnewmapname,$newmapname,$srcfolder,$srccontainer);
                 foreach my $idx (keys(%{$resdatacopy{$key}})) {
                     if (ref($resdatacopy{$key}{$idx}) eq 'HASH') {
                         my $srcurl = $resdatacopy{$key}{$idx}{'src'};
@@ -2815,15 +4239,18 @@ sub apply_fixups {
                                 ($resdatacopy{$key}{$idx}{'cnum'} =~ /^$match_courseid$/)) {
                                 my $srcdom = $resdatacopy{$key}{$idx}{'cdom'};
                                 my $srcnum = $resdatacopy{$key}{$idx}{'cnum'};
-                                my ($newmapname) = ($key =~ m{/([^/]+)$});
-                                my ($srcfolder,$srccontainer) = split(/\./,$newmapname);
+                                unless ($gotnewmapname) {
+                                    ($newmapname) = ($key =~ m{/([^/]+)$});
+                                    ($srcfolder,$srccontainer) = split(/\./,$newmapname);
+                                    if ($newsubdir{$key}) {
+                                        $newmapname =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/;
+                                    }
+                                    $gotnewmapname = 1;
+                                }
                                 my $srcmapinfo = $srcfolder.':'.$idx;
                                 if ($srccontainer eq 'page') {
                                     $srcmapinfo .= ':1';
                                 }
-                                if ($newsubdir{$key}) {
-                                    $newmapname =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/;
-                                }
                                 &copy_templated_files($srcurl,$srcdom,$srcnum,$srcmapinfo,$cdom,
                                                       $cnum,$template,$idx,$newmapname);
                             }
@@ -2932,6 +4359,10 @@ sub apply_fixups {
                 }
             }
         }
+        if (($updatetoolscache) || (@updatetoolsenc)) {
+            &update_ltitools_caches($cdom,$cnum,$updatetoolscache,
+                                    \@updatetoolsenc);
+        }
     }
     return ('ok',\@msgs,$lockmsg);
 }
@@ -3026,7 +4457,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;
@@ -3478,6 +4909,21 @@ sub editor {
         $r->print('</div>');
     }
 
+    if ((!$allowed) && ($folder =~ /^supplemental_\d+$/)) {
+        my ($supplemental) = &Apache::loncommon::get_supplemental($coursenum,$coursedom);
+        if (ref($supplemental) eq 'HASH') {
+            if ((ref($supplemental->{'hidden'}) eq 'HASH') &&
+                (ref($supplemental->{'ids'}) eq 'HASH')) {
+                if (ref($supplemental->{'ids'}->{"/uploaded/$coursedom/$coursenum/$folder.$container"}) eq 'ARRAY') {
+                    my $mapnum = $supplemental->{'ids'}->{"/uploaded/$coursedom/$coursenum/$folder.$container"}->[0];
+                    if ($supplemental->{'hidden'}->{$mapnum}) {
+                        $ishidden = 1;
+                    }
+                }
+            }
+        }
+    }
+
     my ($to_show,$output,@allidx,@allmapidx,%filters,%lists,%curr_groups);
     %filters =  (
                   canremove      => [],
@@ -3501,11 +4947,17 @@ sub editor {
             push(@allmapidx,$res);
         }
 
+        if (($supplementalflag) && (!$allowed) && (!$env{'request.role.adv'})) {
+            if (($ishidden) || ((&LONCAPA::map::getparameter($res,'parameter_hiddenresource'))[0]=~/^yes$/i)) {
+                $idx++;
+                next;
+            }
+        }
         $output .= &entryline($idx,$name,$url,$folder,$allowed,$res,
                               $coursenum,$coursedom,$crstype,
                               $pathitem,$supplementalflag,$container,
                               \%filters,\%curr_groups,$ltitoolsref,$canedit,
-                              $isencrypted,$navmapref,$hostname);
+                              $isencrypted,$ishidden,$navmapref,$hostname);
         $idx++;
         $shown++;
     }
@@ -3514,10 +4966,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" '
@@ -3533,11 +4989,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);
@@ -3633,7 +5087,7 @@ sub multiple_check_form {
     return unless (ref($listsref) eq 'HASH');
     my $disabled;
     unless ($canedit) {
-        $disabled = 'disabled="disabled"'; 
+        $disabled = ' disabled="disabled"';
     }
     my $output =
     '<form action="/adm/coursedocs" method="post" name="togglemult'.$caller.'">'.
@@ -3671,7 +5125,7 @@ sub multiple_check_form {
             '</label></span></td>'."\n".
             '<td class="LC_docs_entry_parameter">'.
             '<span class="LC_nobreak LC_docs_copy">'.
-            '<label><input type="checkbox" name="copyall" id="copyall" onclick="propagateState(this.form,'."'copy'".')"'. $disabled.' />'.&mt('Copy').
+            '<label><input type="checkbox" name="copyall" id="copyall" onclick="propagateState(this.form,'."'copy'".')"'.$disabled.' />'.&mt('Copy').
             '</label></span></td>'.
             '</tr></table>'."\n";
     }
@@ -3885,12 +5339,14 @@ 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)=@_;
-    my ($foldertitle,$renametitle,$oldtitle);
+        $ltitoolsref,$canedit,$isencrypted,$ishidden,$navmapref,$hostname)=@_;
+    my ($foldertitle,$renametitle,$oldtitle,$encodedtitle);
     if (&is_supplemental_title($title)) {
 	($title,$foldertitle,$renametitle) = &Apache::loncommon::parse_supplemental_title($title);
+        $encodedtitle=$title;
     } else {
 	$title=&HTML::Entities::encode($title,'"<>&\'');
+        $encodedtitle=$title;
 	$renametitle=$title;
 	$foldertitle=$title;
     }
@@ -3912,7 +5368,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'},'<>&"');
@@ -4117,6 +5573,7 @@ END
     my $ispage;
     my $containerarg;
     my $folderurl;
+    my $plainurl;
     if ($uploaded) {
         if (($extension eq 'sequence') || ($extension eq 'page')) {
             $url=~/\Q$coursenum\E\/([\/\w]+)\.\Q$extension\E$/;
@@ -4135,18 +5592,26 @@ END
                 $url='/adm/supplemental?';
             }
 	} else {
-	    &Apache::lonnet::allowuploaded('/adm/coursedoc',$url);
+	    $plainurl = $url;
 	}
     }
 
     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);
@@ -4160,7 +5625,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:/)) {
@@ -4171,37 +5636,16 @@ END
             } elsif ($url eq "/public/$coursedom/$coursenum/syllabus") {
                 if (($ENV{'SERVER_PORT'} == 443) &&
                     ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {
-                    $url .= '?usehttp=1';
+                    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;
-                        if ($symb =~ m{^([^#]+)\Q#$anchor\E$}) {
-                            $shownsymb = $1.&escape('#').$anchor;
-                        }
-                    }
-                }
-                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;
+            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)) {
@@ -4209,26 +5653,44 @@ 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);
+                my $shownurl = &Apache::lonenc::encrypted($url);
+                if (&Apache::lonnet::symbverify($symb,$url)) {
+                    $url = $shownurl;
                 } else {
-                    $url='';
+                    $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);
+                    }
                 }
             } else {
-                $url='';
+                $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 '') && ($shownsymb ne '')) {
+                $url .= (($url=~/\?/)?'&':'?').'symb='.&escape($shownsymb);
             }
 	}
     } elsif ($supplementalflag) {
@@ -4237,8 +5699,11 @@ END
                 $url = $1;
                 $anchor = $2;
                 if (($url =~ m{^(|/adm/wrapper)/ext/(?!https:)}) && ($ENV{'SERVER_PORT'} == 443)) {
-                    if ($hostname ne '') {
-                        $url = 'http://'.$hostname.$url;
+                    unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) {
+                        if ($hostname ne '') {
+                            $url = 'http://'.$hostname.$url;
+                        }
+                        $url .= (($url =~ /\?/) ? '&amp;':'?').'usehttp=1';
                     }
                     $nomodal = 1;
                 }
@@ -4246,12 +5711,30 @@ END
         } elsif ($url =~ m{^\Q/public/$coursedom/$coursenum/syllabus\E}) {
             if (($ENV{'SERVER_PORT'} == 443) &&
                 ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {
-                if ($hostname ne '') {
-                    $url = 'http://'.$hostname.$url;
+                unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) {
+                    if ($hostname ne '') {
+                        $url = 'http://'.$hostname.$url;
+                    }
+                    $url .= (($url =~ /\?/) ? '&amp;':'?').'usehttp=1';
                 }
-                $url .= (($url =~ /\?/) ? '&amp;':'?').'usehttp=1';
                 $nomodal = 1;
             }
+        } elsif (($uploaded) && ($url ne '/adm/supplemental?') && ($url ne '/adm/coursedocs?')) {
+            my $embstyle=&Apache::loncommon::fileembstyle($extension);
+            unless ($embstyle eq 'ssi') {
+                if (($embstyle eq 'img')
+                 || ($embstyle eq 'emb')
+                 || ($embstyle eq 'wrp')) {
+                    $url='/adm/wrapper'.$url;
+                } elsif ($url !~ /\.(sequence|page)$/) {
+                    $url='/adm/coursedocs/showdoc'.$url;
+                }
+            }
+        }
+        unless ($allowed && $env{'request.role.adv'}) {
+            if ($ishidden || (&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) {
+                $hiddenres = 1;
+            }
         }
     }
     my ($rand_pick_text,$rand_order_text,$hiddenfolder);
@@ -4263,6 +5746,9 @@ END
         if (!$allowed && $supplementalflag) {
             $folderpath.=$containerarg.'&'.$foldername;
             $url.='folderpath='.&escape($folderpath);
+            if ($ishidden || (&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) {
+                $hiddenfolder = 1;
+            }
         } else {
             my $rpicknum = (&LONCAPA::map::getparameter($orderidx,
                                                         'parameter_randompick'))[0];
@@ -4339,7 +5825,7 @@ $form_common."\n".
 '<span class="LC_nobreak"><label><input type="checkbox" name="randomorder_'.$orderidx.'" id="randomorder_'.$orderidx.'" onclick="checkForSubmit(this.form,'."'randomorder','settings'".');" '.$ro_set.$disabled.' /> '.&mt('Random Order').' </label></span>'.
 $form_end; 
         }
-    } elsif ($supplementalflag && !$allowed) {
+    } elsif ($supplementalflag) {
         my $isexttool;
         if ($url=~m{^/adm/$coursedom/$coursenum/\d+/ext\.tool$}) {
             $url='/adm/wrapper'.$url;
@@ -4348,7 +5834,7 @@ $form_end;
         $url .= ($url =~ /\?/) ? '&amp;':'?';
         $url .= 'folderpath='.&HTML::Entities::encode($esc_path,'<>&"');
         if ($title) {
-            $url .= '&amp;title='.&HTML::Entities::encode($renametitle,'<>&"');
+            $url .= '&amp;title='.$encodedtitle;
         }
         if ((($isexternal) || ($isexttool)) && $orderidx) {
             $url .= '&amp;idx='.$orderidx;
@@ -4383,7 +5869,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);
@@ -4402,7 +5888,7 @@ $form_end;
     } else {
         $reinit = &mt('(re-initialize course to access)');
     }
-    $line.='<td class="LC_docs_entry_commands"'.$tdalign.'><span class="LC_nobreak">'.$editlink.$renamelink;
+    $line.='<td class="LC_docs_entry_commands"'.$tdalign.'><span class="LC_nobreak">'.$editlink.$renamelink.'</span>';
     if ($orig_url =~ /$LONCAPA::assess_re/) {
         $line.= '<br />';
         if ($curralias ne '') {
@@ -4413,10 +5899,19 @@ $form_end;
                    $lt{'sa'}.'</a></span>';
         }
     }
-    $line.='</td><td>';
-    my $link;
+    $line.='</td><td><span class="LC_nobreak">';
+    my ($link,$nolink);
     if (($url=~m{/adm/(coursedocs|supplemental)}) || (!$allowed && $url)) {
-       $line.='<a href="'.$url.'"><img src="'.$icon.'" alt="" class="LC_icon" /></a>';
+        if ($allowed && !$env{'request.role.adv'} && !$isfolder && !$ispage) {
+            if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) {
+                $nolink = 1;
+            }
+        }
+        if ($nolink) {
+            $line .= '<img src="'.$icon.'" alt="" class="LC_icon" /></a>';
+        } else {
+            $line.='<a href="'.$url.'"><img src="'.$icon.'" alt="" class="LC_icon" /></a>';
+        }
     } elsif ($url) {
        if ($anchor ne '') {
            if ($supplementalflag) {
@@ -4425,14 +5920,28 @@ $form_end;
                $anchor = '#'.&HTML::Entities::encode($anchor,'"<>&');
            }
        }
-       if ((!$supplementalflag) && ($nomodal) && ($hostname ne '')) {
+       if (($nomodal) && ($hostname ne '')) {
            $link = 'http://'.$hostname.$url;
        } else {
            $link = $url;
        }
-       $link = &js_escape($link.(($url=~/\?/)?'&amp;':'?').'inhibitmenu=yes'.
-                                               (($anchor ne '')?$anchor:''));
-       if ($nomodal) {
+       my $inhibitmenu;
+       if ((($supplementalflag) && ($allowed) && ($url =~ m{^/adm/wrapper/})) ||
+           (($allowed) && (($url =~ m{^/adm/(viewclasslist|$match_domain/$match_username/aboutme)(\?|$)}) ||
+                           ($url =~ m{^/public/$match_domain/$match_courseid/syllabus(\?|$)})))) {
+           $inhibitmenu = 'only_body=1';
+       } else {
+           $inhibitmenu = 'inhibitmenu=yes';
+       }
+       $link = &js_escape($link.(($url=~/\?/)?'&amp;':'?').$inhibitmenu.$anchor);
+       if ($allowed && !$env{'request.role.adv'} && !$isfolder && !$ispage && !$uploaded) {
+           if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) {
+               $nolink = 1;
+           }
+       }
+       if ($nolink) {
+           $line.='<img src="'.$icon.'" alt="" class="LC_icon" />';
+       } elsif ($nomodal) {
            $line.='<a href="#" onclick="javascript:window.open('."'$link','syllabuspreview','height=400,width=500,scrollbars=1,resizable=1,menubar=0,location=1')".'; return false;" />'.
                   '<img src="'.$icon.'" alt="" class="LC_icon" border="0" /></a>';
        } else {
@@ -4444,9 +5953,26 @@ $form_end;
     }
     $line.='</span></td><td'.$tdwidth.'>';
     if (($url=~m{/adm/(coursedocs|supplemental)}) || (!$allowed && $url)) {
-       $line.='<a href="'.$url.'">'.$title.'</a>';
+       if ($nolink) {
+           $line.=$title;
+       } else {
+           $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) {
+       if ($nolink) {
+           $line.=$title;
+       } elsif ($nomodal) {
            $line.='<a href="#" onclick="javascript:window.open('."'$link','syllabuspreview','height=400,width=500,scrollbars=1,resizable=1,menubar=0,location=1')".'; return false;" />'.
                   $title.'</a>';
        } else {
@@ -4465,32 +5991,42 @@ $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 ($uploaded && $url && !$isfolder && !$ispage) {
+        if (($plainurl ne '') && ($env{'request.role.adv'} || $allowed || !$hiddenres)) {
+            &Apache::lonnet::allowuploaded('/adm/coursedoc',$plainurl);
         }
+    }
+    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')) {
+            if (($ishash) && (ref($filtersref->{'hiddenresource'}) 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
@@ -4501,6 +6037,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;
@@ -4834,7 +6371,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>');
             }
@@ -4850,7 +6387,7 @@ sub short_urls {
         }
         my %currtiny = &Apache::lonnet::dump('tiny',$cdom,$cnum);
         $r->print(&Apache::loncourserespicker::create_picker($navmap,'shorturls',$formname,$crstype,undef,
-                                                             undef,undef,undef,undef,undef,\%currtiny,$readonly));
+                                                             undef,undef,undef,undef,undef,\%currtiny,undef,$readonly));
     }
     $r->print(&endContentScreen());
 }
@@ -4869,7 +6406,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());
@@ -5325,6 +6862,7 @@ sub handler {
     my $crstype = &Apache::loncommon::course_type();
     my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'};
     my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'};
+    my $coursehome=$env{'course.'.$env{'request.course.id'}.'.home'};
 
 # get docroot
     my $londocroot = $r->dir_config('lonDocRoot');
@@ -5340,7 +6878,9 @@ sub handler {
 	               'Load_Map','Supplemental','Score_Upload_Form',
 	               'Adding_Pages','Importing_LON-CAPA_Resource',
 	               'Importing_IMS_Course','Uploading_From_Harddrive',
-                       'Course_Roster','Web_Page','Dropbox','Simple_Problem') {
+                       'Course_Roster','Web_Page','Dropbox','Simple_Problem',
+                       'Standard_Problem','Course_Resources',
+                       'Search_LON-CAPA_Resource','Import_Stored_Links') {
 	$help{$topic}=&Apache::loncommon::help_open_topic('Docs_'.$topic);
     }
     # Composite help files
@@ -5356,17 +6896,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"';
@@ -5408,8 +6951,15 @@ sub handler {
       &init_breadcrumbs('versions','Check/Set Resource Versions','Docs_Check_Resource_Versions');
       &checkversions($r,$canedit);
   } elsif ($canedit && $env{'form.dumpcourse'}) {
-      &init_breadcrumbs('dumpcourse','Copy '.&Apache::loncommon::course_type().' Content to Authoring Space');
+      &init_breadcrumbs('dumpcourse','Copy uploaded content to Authoring Space');
       &dumpcourse($r);
+  } elsif (($canedit || $canview) && ($env{'form.copyauthored'})) {
+      &init_breadcrumbs('copyauthored','Copy from Course Authoring to User Authoring');
+      my $readonly;
+      if (!$canedit) {
+          $readonly = 1;
+      }
+      &copycrsauthored($r,$coursenum,$coursedom,$coursehome,$readonly);
   } elsif ($canedit && $env{'form.exportcourse'}) {
       &init_breadcrumbs('exportcourse','IMS Export');
       &Apache::imsexport::exportcourse($r);
@@ -5460,6 +7010,8 @@ sub handler {
                       $r->internal_redirect($redirect);
                       return OK;
                   }
+              } else {
+                  $r->internal_redirect($redirect);
               }
           }
       }
@@ -5469,7 +7021,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']);
 
@@ -5510,40 +7062,22 @@ sub handler {
     }
     if ($env{'form.forcesupplement'}) { $supplementalflag=1; }
     if ($env{'form.forcestandard'})   { $supplementalflag=0; }
-    unless ($allowed) { $supplementalflag=1; }
-    unless ($standard) { $supplementalflag=1; }
+    unless (($supplementalflag) ||
+            ($r->uri =~ m{^/adm/coursedocs/showdoc/uploaded/\Q$coursedom\E/\Q$coursenum\E/docs/})) {
+        unless ($allowed) { $supplementalflag=1; }
+        unless ($standard) { $supplementalflag=1; }
+    }
     my $toolsflag=0;
     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'});
-        }
+        &Apache::loncommon::validate_folderpath($supplementalflag,$allowed,$coursenum,$coursedom);
     }
 
+    my $backto_supppath;
     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'});
+        if ($supplementalflag && $allowed) {
+            $backto_supppath = &validate_supppath($coursenum,$coursedom);
         }
     }
 
@@ -5554,6 +7088,7 @@ sub handler {
     my $containertag;
     my $pathitem;
     my %ltitools;
+    my $posslti;
     my $hiddentop;
     my $navmap;
     my $filterFunc = sub { my $res = shift; return (!$res->randomout() && !$res->is_map()) };
@@ -5565,10 +7100,10 @@ sub handler {
                &Apache::loncommon::symb_to_docspath($env{'form.symb'},\$navmap);
            &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} =>
                $env{'form.command'}.'_'.$env{'form.symb'}});
-       } elsif ($env{'form.supppath'} ne '') {
+       } elsif (($env{'form.supppath'} ne '') && $supplementalflag && $allowed) {
            $env{'form.folderpath'}=$env{'form.supppath'};
            &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} =>
-               $env{'form.command'}.'_'.$env{'form.supppath'}});
+               $env{'form.command'}.'_'.$backto_supppath});
        }
    } elsif ($env{'form.command'} eq 'editdocs') {
        $env{'form.folderpath'} = &default_folderpath($coursenum,$coursedom,\$navmap);
@@ -5603,10 +7138,13 @@ sub handler {
         } else {
             undef($env{'form.folderpath'});
         }
+        if ($env{'form.folderpath'} ne '') {
+            &Apache::loncommon::validate_folderpath($supplementalflag,$allowed,$coursenum,$coursedom);
+        }
     }
-   
-# If we are not allowed to make changes, all we can see are supplemental docs
-    if (!$allowed) {
+
+# Set folderpath if we are not allowed to make changes and this is supplemental content
+    if ((!$allowed) && ($supplementalflag)) {
         unless ($env{'form.folderpath'} =~ /^supplemental/) {
             $env{'form.folderpath'} = &supplemental_base();
         }
@@ -5617,36 +7155,89 @@ sub handler {
                                   .'&'.
                                   $env{'form.folderpath'};
     }
-# If allowed and user's role is not advanced check folderpath is not hidden  
-    if (($allowed) && (!$env{'request.role.adv'}) && 
-        ($env{'form.folderpath'} ne '') && (!$supplementalflag)) {
-        my $folderurl;
+# If allowed and user's role is not advanced check folderpath is not hidden
+    my $hidden_and_empty;
+    if (($allowed) && (!$env{'request.role.adv'}) && ($env{'form.folderpath'} ne '')) {
+        my ($folderurl,$foldername,$hiddenfolder);
         my @pathitems = split(/\&/,$env{'form.folderpath'});
         my $folder = $pathitems[-2];
         if ($folder eq '') {
             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';
             }
-            unless (ref($navmap)) {
-                $navmap = Apache::lonnavmaps::navmap->new();
-            }
-            if (ref($navmap)) {
-                if (lc($navmap->get_mapparam(undef,$folderurl,"0.hiddenresource")) eq 'yes') {
-                    my @resources = $navmap->retrieveResources($folderurl,$filterFunc,1,1);
-                    unless (@resources) {
-                        undef($env{'form.folderpath'});
+            if ($supplementalflag) {
+                ($foldername,$hiddenfolder) = ($pathitems[-1] =~ /^([^:]*)::(|1):::$/);
+                $foldername = &HTML::Entities::decode(&unescape($foldername));
+                my ($supplemental) = &Apache::loncommon::get_supplemental($coursenum,$coursedom);
+                if (ref($supplemental) eq 'HASH') {
+                    my ($suppmap,$suppmapnum);
+                    if ($folder eq 'supplemental') {
+                        $suppmap = 'default';
+                        $suppmapnum = 0;
+                    } elsif ($folder =~ /^supplemental_(\d+)$/) {
+                        $suppmap = $1;
+                        $suppmapnum = $suppmap;
+                    }
+                    if ($hiddenfolder) {
+                        my $hascontent;
+                        foreach my $key (reverse(sort(keys(%{$supplemental->{'ids'}})))) {
+                            if ($key =~ m{^\Q/uploaded/$coursedom/$coursenum/supplemental/$suppmap/\E}) {
+                                $hascontent = 1;
+                            } elsif (ref($supplemental->{'ids'}->{$key}) eq 'ARRAY') {
+                                foreach my $id (@{$supplemental->{'ids'}->{$key}}) {
+                                    if ($id =~ /^$suppmapnum\:/) {
+                                        $hascontent = 1;
+                                        last;
+                                    }
+                                }
+                            }
+                            last if ($hascontent);
+                        }
+                        unless ($hascontent) {
+                            if ($foldername ne '') {
+                                $hidden_and_empty = $foldername;
+                            } else {
+                                $hidden_and_empty = $folder;
+                            }
+                        }
                     }
                 }
+            } else {
+                unless (ref($navmap)) {
+                    $navmap = Apache::lonnavmaps::navmap->new();
+                }
+                ($foldername,$hiddenfolder) = ($pathitems[-1] =~ /^([^:]*):|\d+:|1:(|1):|1:|1$/);
+                $foldername = &HTML::Entities::decode(&unescape($foldername));
+                if (ref($navmap)) {
+                    if ($hiddenfolder ||
+                        (lc($navmap->get_mapparam(undef,$folderurl,"0.hiddenresource")) eq 'yes')) {
+                        my @resources = $navmap->retrieveResources($folderurl,$filterFunc,1,1);
+                        unless (@resources) {
+                            if ($foldername ne '') {
+                                $hidden_and_empty = $foldername;
+                            } else {
+                                $hidden_and_empty = $folder;
+                            }
+                        }
+                    }
+                }
+            }
+            if ($hidden_and_empty ne '') {
+                splice(@pathitems,-2);
+                if (@pathitems) {
+                    $env{'form.folderpath'} = join('&',@pathitems);
+                } else {
+                    undef($env{'form.folderpath'});
+                }
             }
         }
     }
 
-
 # If after all of this, we still don't have any paths, make them
     unless ($env{'form.folderpath'}) {
        if ($supplementalflag) {
@@ -5721,7 +7312,7 @@ sub handler {
             my $tid = 1;
             my @tabids;
             if ($supplementalflag) {
-                @tabids = ('002','ee2','ff2');
+                @tabids = ('002','dd2','ee2','ff2');
                 $tid = 2;
             } else {
                 @tabids = ('aa1','bb1','cc1','ff1');
@@ -5731,8 +7322,19 @@ sub handler {
                 }
             }
             my $tabidstr = join("','",@tabids);
-            %ltitools = &Apache::lonnet::get_domain_lti($coursedom,'consumer');
-            my $posslti = keys(%ltitools);
+            my (%domtools,%crstools);
+            my %tooltypes = &Apache::loncommon::usable_exttools();
+            if ($tooltypes{'dom'}) {
+                %domtools = &Apache::lonnet::get_domain_lti($coursedom,'consumer');
+            }
+            if ($tooltypes{'crs'}) {
+                %crstools = &Apache::lonnet::get_course_lti($coursenum,$coursedom,'consumer');
+            }
+            %ltitools = (
+                          dom => \%domtools,
+                          crs => \%crstools,
+                        );
+            $posslti = scalar(keys(%domtools)) + scalar(keys(%crstools));
             my $hostname = $r->hostname();
 	    $script .= &editing_js($udom,$uname,$supplementalflag,$coursedom,$coursenum,$posslti,
                                    $londocroot,$canedit,$hostname,\$navmap).
@@ -5740,8 +7342,14 @@ sub handler {
                        &inject_data_js().
                        &Apache::lonhtmlcommon::resize_scrollbox_js('docs',$tabidstr,$tid).
                        &Apache::lonextresedit::extedit_javascript(\%ltitools);
+            my $onload = "javascript:resize_scrollbox('contentscroll','1','1');";
+            if ($hidden_and_empty ne '') {
+                my $alert = &mt("Additional privileges required to edit empty and hidden folder: '[_1]'",
+                                $hidden_and_empty);
+                $onload .= "javascript:alert('".&js_escape($alert)."');";
+            }
             $addentries = {
-                            onload   => "javascript:resize_scrollbox('contentscroll','1','1');",
+                            onload => $onload,
                           };
         }
         $script .= &paste_popup_js(); 
@@ -5763,8 +7371,16 @@ 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 $title = &HTML::Entities::encode($env{'form.title'},'\'"<>&');
+            my $brcrum = &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$title,1);
+            $args = {'bread_crumbs' => $brcrum,
+                     'bread_crumbs_nomenu' => 1};
+        } else {
+            $args = {'force_register' => $showdoc};
+        }
+        $r->print(&Apache::loncommon::start_page("$crstype documents",undef,$args));
     } elsif ($toolsflag) {
         my ($breadtext,$breadtitle);
         $breadtext = "$crstype Editor";
@@ -5782,9 +7398,20 @@ 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);
+        my $args = {'bread_crumbs' => $brcrum};
+        unless (($env{'form.folderpath'} eq '') ||
+                ($env{'form.folder'} eq 'supplemental')) {
+            $args->{'bread_crumbs_nomenu'} = 1;
+        }
         $r->print(&Apache::loncommon::start_page("Supplemental $crstype Content",undef,
-                                                {'bread_crumbs' => $brcrum,}));
+                                                 $args));
     } else {
         my ($breadtext,$breadtitle,$helpitem);
         $breadtext = "$crstype Editor";
@@ -5812,6 +7439,7 @@ sub handler {
   my %codebase = ();
   my ($upload_result,$upload_output,$uploadphase);
   if ($canedit) {
+      undef($suppchanges);
       if (($env{'form.uploaddoc.filename'}) &&
 	  ($env{'form.cmd'}=~/^upload_(\w+)/)) {
           my $context = $1; 
@@ -5823,6 +7451,10 @@ sub handler {
 	  if ($hadchanges) {
 	      &mark_hash_old();
 	  }
+          if ($suppchanges) {
+              &Apache::lonnet::update_supp_caches($coursedom,$coursenum);
+              undef($suppchanges);
+          }
           $r->print($upload_output);
       } elsif ($env{'form.phase'} eq 'upload_embedded') {
           # Process file upload - phase two - upload embedded objects 
@@ -5864,7 +7496,7 @@ sub handler {
 
   if ($allowed && $toolsflag) {
       $r->print(&startContentScreen('tools'));
-      $r->print(&generate_admin_menu($crstype,$canedit));
+      $r->print(&generate_admin_menu($crstype,$canedit,$coursenum,$coursedom));
       $r->print(&endContentScreen());
   } elsif ((!$showdoc) && (!$uploadphase)) {
 # -----------------------------------------------------------------------------
@@ -5872,8 +7504,8 @@ sub handler {
 		'copm' => 'All documents out of a published map into this folder',
                 'upfi' => 'Upload File',
                 'upld' => 'Upload Content',
-                'srch' => 'Search',
-                'impo' => 'Import',
+                'srch' => 'Search Repository',
+                'impo' => 'Import from Repository',
 		'lnks' => 'Import from Stored Links',
                 'impm' => 'Import from Assembled Map',
                 'imcr' => 'Import from Course Resources',
@@ -5891,6 +7523,7 @@ sub handler {
                 'stpr' => 'Standard Problem',
                 'news' => 'New sub-directory',
                 'crpr' => 'Create Problem',
+                'swit' => 'Switch Server',
                 'drbx' => 'Drop Box',
                 'scuf' => 'External Scores (handgrade, upload, clicker)',
                 'bull' => 'Discussion Board',
@@ -5911,6 +7544,7 @@ sub handler {
                 'dire' => 'Directory:',
                 'cate' => 'Category:',
                 'tmpl' => 'Template:',
+                'empd' => 'No resources found',
                 'comment' => 'Comment',
                 'parse' => 'Upload embedded images/multimedia files if HTML file',
                 'bb5'      => 'Blackboard 5',
@@ -5960,10 +7594,7 @@ sub handler {
 	my $fileupload=(<<FIUP);
         $quotainfo
 	$lt{'file'}:<br />
-	<input type="file" name="uploaddoc" class="flUpload" size="40" $disabled />
-        <input type="hidden" id="free_space" value="$free_space" />
 FIUP
-
 	my $checkbox=(<<CHBO);
 	<!-- <label>$lt{'parse'}?
 	<input type="checkbox" name="parserflag" />
@@ -5983,6 +7614,8 @@ CHBO
         <fieldset id="uploadimsform" style="display: none;">
         <legend>$lt{'imsf'}</legend>
         $fileupload
+        <input type="file" name="uploaddoc" id="uploaddocims" class="LC_flUpload LC_uploaddoc" size="40" $disabled />
+        <input type="hidden" id="LC_free_space_ims" value="$free_space" />
         <br />
         <p>
         $lt{'cms'}:&nbsp; 
@@ -6009,6 +7642,8 @@ IMSFORM
         <legend>$lt{'upfi'}</legend>
 	<input type="hidden" name="active" value="aa" />
     $fileupload
+        <input type="file" name="uploaddoc" class="LC_flUpload" size="40" $disabled />
+        <input type="hidden" id="LC_free_space" value="$free_space" />
 	<br />
 	$lt{'title'}:<br />
 	<input type="text" size="60" name="comment" $disabled />
@@ -6047,28 +7682,56 @@ FUFORM
         </form>
 
 SEDFFORM
-        my $importcrsresform;
-        my ($numdirs,$pickfile) = 
-            &Apache::loncommon::import_crsauthor_form('crsresimportform','coursepath','coursefile',
-                                                      "resize_scrollbox('contentscroll','1','0');",
-                                                      undef,'res');
-        if ($pickfile) {
-            $importcrsresform=(<<CRSFORM);
-        <a class="LC_menubuttons_link" href="javascript:toggleImportCrsres('res','$numdirs');">
+        my ($importcrsresform,$checkcrsres);
+        if ($env{'course.'.$coursedom.'_'.$coursenum.'.internal.crsauthor'}) {
+            $checkcrsres = 1;
+        } elsif ($env{'course.'.$coursedom.'_'.$coursenum.'.internal.crsauthor'} ne '0') {
+            my %domdefs=&Apache::lonnet::get_domain_defaults($coursedom);
+            my $type = lc($env{'course.'.$env{'request.course.id'}.'.type'});
+            unless (($type eq 'community') || ($type eq 'placement')) {
+                $type = 'unofficial';
+                if ($env{'course.'.$env{'request.course.id'}.'internal.coursecode'} ne '') {
+                    $type = 'official';
+                } elsif ($env{'course.'.$env{'request.course.id'}.'internal.textbook'} ne '') {
+                    $type = 'textbook';
+                } else {
+                    $type = 'unofficial';
+                }
+            }
+            if ($domdefs{$type.'crsauthor'}) {
+                $checkcrsres = 1;
+            }
+        }
+        if ($checkcrsres) {
+            my ($numdirs,$pickfile) = 
+                &Apache::loncommon::import_crsauthor_form('coursepath','coursefile',
+                                                          "resize_scrollbox('contentscroll','1','0');",
+                                                          undef,'res');
+            if ($pickfile) {
+                $importcrsresform=(<<CRSFORM);
+        <a class="LC_menubuttons_link" href="javascript:toggleImportCrsres('res');">
         $lt{'imcr'}</a>$help{'Course_Resources'}
         <form action="/adm/coursedocs" method="post" name="crsresimportform" onsubmit="return validImportCrsRes();">
         <fieldset id="importcrsresform" style="display: none;">
         <legend>$lt{'imcr'}</legend>
+        <div id="importcrsrescontent" style="display: none;">
         <input type="hidden" name="active" value="bb" />
         $pickfile
         <p>
-        $lt{'title'}: <input type="textbox" name="crsrestitle" value="" $disabled />
+        $lt{'title'}: <input type="text" name="crsrestitle" value="" $disabled />
         </p>
         <input type="hidden" name="importdetail" value="" />
-        <input type="submit" name="crsres" value="$lt{'impo'}" $disabled />
+        <input type="submit" name="crsres" value="$lt{'impo'}" $disabled /><br />
+        </div>
+        <div id="importcrsresempty" style="display: none;">
+        <p>
+        $lt{'empd'}
+        </p>
+        </div>
         </fieldset>
         </form>
 CRSFORM
+            }
         }
 
         my $fromstoredjs;
@@ -6079,13 +7742,13 @@ CRSFORM
         }
 
 	my @importpubforma = (
-	{ '<img class="LC_noBorder LC_middle" src="/res/adm/pages/src.png" alt="'.$lt{srch}.'"  onclick="javascript:groupsearch()" />' => $pathitem."<a class='LC_menubuttons_link' href='javascript:groupsearch()'>$lt{'srch'}</a>" },
+	{ '<img class="LC_noBorder LC_middle" src="/res/adm/pages/src.png" alt="'.$lt{srch}.'"  onclick="javascript:groupsearch()" />' => $pathitem."<a class='LC_menubuttons_link' href='javascript:groupsearch()'>$lt{'srch'}</a>$help{'Search_LON-CAPA_Resource'}" },
 	{ '<img class="LC_noBorder LC_middle" src="/res/adm/pages/res.png" alt="'.$lt{impo}.'"  onclick="javascript:groupimport();"/>' => "<a class='LC_menubuttons_link' href='javascript:groupimport();'>$lt{'impo'}</a>$help{'Importing_LON-CAPA_Resource'}" },
-	{ '<img class="LC_noBorder LC_middle" src="/res/adm/pages/wishlist.png" alt="'.$lt{lnks}.'" onclick="javascript:'.$fromstoredjs.';" />' => '<a class="LC_menubuttons_link" href="javascript:'.$fromstoredjs.';">'.$lt{'lnks'}.'</a>' },
+	{ '<img class="LC_noBorder LC_middle" src="/res/adm/pages/wishlist.png" alt="'.$lt{lnks}.'" onclick="javascript:'.$fromstoredjs.';" />' => '<a class="LC_menubuttons_link" href="javascript:'.$fromstoredjs.';">'.$lt{'lnks'}.'</a>'.$help{'Import_Stored_Links'} },
         { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/sequence.png" alt="'.$lt{impm}.'" onclick="javascript:toggleMap(\'map\');" />' => $importpubform },
         );
-        if ($pickfile) {
-            push(@importpubforma,{ '<img class="LC_noBorder LC_middle" src="/res/adm/pages/res.png" alt="'.$lt{imcr}.'"  onclick="javascript:toggleImportCrsres(\'res\','."'$numdirs'".');"/>' => $importcrsresform});
+        if ($importcrsresform) {
+            push(@importpubforma,{ '<img class="LC_noBorder LC_middle" src="/res/adm/pages/impcrsau.png" alt="'.$lt{imcr}.'"  onclick="javascript:toggleImportCrsres(\'res\');" />' => $importcrsresform});
 	}
 	$importpubform = &create_form_ul(&create_list_elements(@importpubforma));
         my $extresourcesform =
@@ -6176,7 +7839,7 @@ HIDDENFORM
 
 	my $newnavform=(<<NNFORM);
 	<form action="/adm/coursedocs" method="post" name="newnav">
-	<input type="hidden" name="active" value="ee" />
+	<input type="hidden" name="active" value="ff" />
 	$pathitem
 	<input type="hidden" name="importdetail" 
 	value="$lt{'navc'}=/adm/navmaps" />
@@ -6186,7 +7849,7 @@ HIDDENFORM
 NNFORM
 	my $newsmppageform=(<<NSPFORM);
 	<form action="/adm/coursedocs" method="post" name="newsmppg">
-	<input type="hidden" name="active" value="ee" />
+	<input type="hidden" name="active" value="ff" />
 	$pathitem
 	<input type="hidden" name="importdetail" value="" />
 	<a class="LC_menubuttons_link" href="javascript:makesmppage();"> $lt{'sipa'}</a>
@@ -6196,7 +7859,7 @@ NSPFORM
 
 	my $newsmpproblemform=(<<NSPROBFORM);
 	<form action="/adm/coursedocs" method="post" name="newsmpproblem">
-	<input type="hidden" name="active" value="cc" />
+	<input type="hidden" name="active" value="dd" />
 	$pathitem
 	<input type="hidden" name="importdetail" value="" />
 	<a class="LC_menubuttons_link" href="javascript:makesmpproblem();">$lt{'sipr'}</a>
@@ -6207,7 +7870,7 @@ NSPROBFORM
 
 	my $newdropboxform=(<<NDBFORM);
 	<form action="/adm/coursedocs" method="post" name="newdropbox">
-	<input type="hidden" name="active" value="cc" />
+	<input type="hidden" name="active" value="dd" />
 	$pathitem
 	<input type="hidden" name="importdetail" value="" />
 	<a class="LC_menubuttons_link" href="javascript:makedropbox();">$lt{'drbx'}</a>
@@ -6217,7 +7880,7 @@ NDBFORM
 
 	my $newexuploadform=(<<NEXUFORM);
 	<form action="/adm/coursedocs" method="post" name="newexamupload">
-	<input type="hidden" name="active" value="cc" />
+	<input type="hidden" name="active" value="dd" />
 	$pathitem
 	<input type="hidden" name="importdetail" value="" />
 	<a class="LC_menubuttons_link" href="javascript:makeexamupload();">$lt{'scuf'}</a>
@@ -6227,7 +7890,7 @@ NEXUFORM
 
 	my $newbulform=(<<NBFORM);
 	<form action="/adm/coursedocs" method="post" name="newbul">
-	<input type="hidden" name="active" value="dd" />
+	<input type="hidden" name="active" value="ee" />
 	$pathitem
 	<input type="hidden" name="importdetail" value="" />
 	<a class="LC_menubuttons_link" href="javascript:makebulboard();" >$lt{'bull'}</a>
@@ -6237,7 +7900,7 @@ NBFORM
 
 	my $newaboutmeform=(<<NAMFORM);
 	<form action="/adm/coursedocs" method="post" name="newaboutme">
-	<input type="hidden" name="active" value="dd" />
+	<input type="hidden" name="active" value="ee" />
 	$pathitem
 	<input type="hidden" name="importdetail" 
 	value="$plainname=/adm/$udom/$uname/aboutme" />
@@ -6248,7 +7911,7 @@ NAMFORM
 
 	my $newaboutsomeoneform=(<<NASOFORM);
 	<form action="/adm/coursedocs" method="post" name="newaboutsomeone">
-	<input type="hidden" name="active" value="dd" />
+	<input type="hidden" name="active" value="ee" />
 	$pathitem
 	<input type="hidden" name="importdetail" value="" />
 	<a class="LC_menubuttons_link" href="javascript:makeabout();">$lt{'abou'}</a>
@@ -6257,7 +7920,7 @@ NASOFORM
 
 	my $newrosterform=(<<NROSTFORM);
 	<form action="/adm/coursedocs" method="post" name="newroster">
-	<input type="hidden" name="active" value="dd" />
+	<input type="hidden" name="active" value="ee" />
 	$pathitem
 	<input type="hidden" name="importdetail" 
 	value="$lt{'rost'}=/adm/viewclasslist" />
@@ -6278,143 +7941,73 @@ NROSTFORM
         }
         my $newwebpageform =(<<NWEBFORM);
         <form action="/adm/coursedocs" method="post" name="newwebpage">
-        <input type="hidden" name="active" value="ee" />
+        <input type="hidden" name="active" value="ff" />
         $pathitem
         <input type="hidden" name="importdetail" value="$newwebpage" />
         <a class="LC_menubuttons_link" href="javascript:makewebpage();">$lt{'webp'}</a>
         $help{'Web_Page'}
         </form>
 NWEBFORM
-
+        my $showpath = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
         my @ids=&Apache::lonnet::current_machine_ids();
-        my %select_menus;
-        my $numauthor = 0;
-        my $numcrsdirs = 0;
-        my $toppath = "/priv/$env{'user.domain'}/$env{'user.name'}"; 
+        my $machines_str = "'".join("','",@ids)."'";
+        my (%is_home,%toppath,$rolehomes);
         if ($env{'user.author'}) {
-            $numauthor ++;
-            $select_menus{'author'}->{'text'} = &Apache::lonnet::plaintext('au');
             if (grep(/^\Q$env{'user.home'}\E$/,@ids)) {
-                my $is_home = 1;
-                my %subdirs;
-                &Apache::lonnet::recursedirs($is_home,'priv',$londocroot,$toppath,'',\%subdirs);
-                $select_menus{'author'}->{'default'} = '/'; 
-                $select_menus{'author'}->{'select2'}->{'/'} = '/';
-                my @ordered = ('/');
-                foreach my $relpath (sort { lc($a) cmp lc($b) } (keys(%subdirs))) {
-                    $select_menus{'author'}->{'select2'}->{$relpath} = $relpath;
-                    push(@ordered,$relpath);
-                }
-                $select_menus{'author'}->{'order'} = \@ordered;
-            } else {
-                $select_menus{'author'}->{'select2'}->{'switch'} = &mt('Switch server required');
-                $select_menus{'author'}->{'default'} = 'switch';
-                $select_menus{'author'}->{'order'} = ['switch'];
+                $is_home{'author'} = 1;
             }
+            $rolehomes = '<input type="hidden" id="rolehome_author" name="rolehome_author" value="'.$env{'user.home'}.'" />'."\n";
         }
         my %roleshash = &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},'userroles',
                                                       ['active'],['ca','aa']);
-        my $crshome = $env{'course.'.$env{'request.course.id'}.'.home'};
         my %by_roletype;
         if (keys(%roleshash)) {
             foreach my $entry (keys(%roleshash)) {
                 my ($auname,$audom,$roletype) = split(/:/,$entry);
                 my $key = $entry;
                 $key =~ s/:/___/g;
-                $by_roletype{$roletype}{$auname.'___'.$audom} = 1;
-                $select_menus{$key}->{'text'} = &Apache::lonnet::plaintext($roletype)." ($audom/$auname)";
+                my $author = $auname.'___'.$audom;
+                $by_roletype{$roletype}{$author} = 1;
                 my $rolehome = &Apache::lonnet::homeserver($auname,$audom);
-                if (grep(/^\Q$rolehome\E$/,@ids)) {    
-                    my $is_home = 1;
-                    my (%subdirs,@ordered);
-                    my $toppath="/priv/$audom/$auname";
-                    &Apache::lonnet::recursedirs($is_home,'priv',$londocroot,$toppath,'',\%subdirs);
-                    $select_menus{$key}->{'default'} = '/';
-                    $select_menus{$key}->{'select2'}->{'/'} = '/';
-                    my @ordered = ('/');
-                    foreach my $relpath (sort { lc($a) cmp lc($b) } (keys(%subdirs))) {
-                        $select_menus{$key}->{'select2'}->{$relpath} = $relpath;
-                        push(@ordered,$relpath);
-                    }
-                    $select_menus{$key}->{'order'} = \@ordered;
-                } else {
-                    $select_menus{$key}->{'select2'}->{'switch'} = &mt('Switch server required');
-                    $select_menus{$key}->{'default'} = 'switch';
-                    $select_menus{$key}->{'order'} = ['switch'];
-                }
-                $numauthor ++;
-            }
-        }
-        my ($pickdir,$showtitle);
-        if ($numauthor) {
-            my @order;
-            my $defrole;
-            if ($env{'user.author'}) {
-                push(@order,'author');
-                $defrole = 'author';
-            }
-            if (keys(%by_roletype)) {
-                foreach my $possrole ('ca','aa') {
-                    if (ref($by_roletype{$possrole}) eq 'HASH') {
-                        foreach my $author (sort { lc($a) cmp lc($b) } (keys(%{$by_roletype{$possrole}}))) {
-                            unless ($defrole) {
-                                $defrole = $author;
-                            }
-                            push(@order,$author.'___'.$possrole);
-                        }
-                    }
-                }
-            }
-            $select_menus{'course'}->{'text'} = &mt('Course Resource');
-            if (grep(/^\Q$crshome\E$/,@ids)) {
-                my $is_home = 1;
-                my %subdirs;
-                my $toppath="/priv/$coursedom/$coursenum";
-                &Apache::lonnet::recursedirs($is_home,'priv',$londocroot,$toppath,'',\%subdirs);
-                $numcrsdirs = keys(%subdirs);
-                $select_menus{'course'}->{'default'} = '/';
-                $select_menus{'course'}->{'select2'}->{'/'} = '/';
-                my @ordered = ('/');
-                foreach my $relpath (sort { lc($a) cmp lc($b) } (keys(%subdirs))) {
-                    $select_menus{'course'}->{'select2'}->{$relpath} = $relpath;
-                    push(@ordered,$relpath);
-                }
-                $select_menus{'course'}->{'order'} = \@ordered;
-            } else {
-                $select_menus{'course'}->{'select2'}->{'switch'} = &mt('Switch server required');
-                $select_menus{'course'}->{'default'} = 'switch';
-                $select_menus{'course'}->{'order'} = ['switch'];
-            }
-            push(@order,'course');
-            $pickdir = $lt{'loca'}.
-                       &Apache::loncommon::linked_select_forms('courseresform','<br />'.$lt{'dire'},
-                                                               $defrole,'authorrole','authorpath',
-                                                               \%select_menus,\@order,'toggleCrsResTitle();',
-                                                               '','priv').'<br />';
-            $showtitle = 'none';
-        } else {
-            my $is_home;
-            $showtitle = 'inline';
-            if (grep(/^\Q$crshome\E$/,@ids)) {
-                $is_home = 1;
-                $pickdir .= '<input type="hidden" name="authorrole" value="course" />'; 
-                my $toppath="/priv/$coursedom/$coursenum'}";
-                my %subdirs;
-                &Apache::lonnet::recursedirs($is_home,'priv',$londocroot,$toppath,'',\%subdirs);
-                $numcrsdirs = keys(%subdirs); 
-                if ($numcrsdirs) {
-                    $pickdir .= &mt('Directory: ').'<select name="authorpath">'."\n".
-                                 '<option value="/">/</option>'."\n";
-                    foreach my $key (sort { lc($a) cmp lc($b) } (keys(%subdirs))) {
-                        $pickdir .= '<option value="'.$key.'">'.$key.'</option>'."\n";
+                $toppath{$author} = "/priv/$audom/$auname";
+                if (grep(/^\Q$rolehome\E$/,@ids)) {
+                    $is_home{$author} = 1;
+                }
+                $rolehomes .= '<input type="hidden" id="rolehome_coauthor_'.$roletype.'_'.$audom.'/'.$auname.'" '.
+                              'name="rolehome_coauthor" value="'.$roletype.'='.$audom.'/'.$auname.'='.$rolehome.'" />'."\n";
+            }
+        }
+        my $crshome = $env{'course.'.$env{'request.course.id'}.'.home'};
+        if (grep(/^\Q$crshome\E$/,@ids)) {
+            $is_home{'course'} = 1;
+        }
+        $rolehomes .= '<input type="hidden" id="rolehome_course" name="rolehome_course" value="'.$crshome.'" />'."\n";
+        my $pickdir = $lt{'loca'}.
+                   '<select name="authorrole" onchange="populateDirSelects(this.form,'."'authorrole','authorpath'".',1,1,0);">'."\n".
+                   '<option value="" selected="selected">'.&mt('Select').'</option>'."\n";
+        if ($env{'user.author'}) {
+            $pickdir .= '<option value="author">'.&Apache::lonnet::plaintext('au').'</option>'."\n";
+        }
+        if (keys(%by_roletype)) {
+            foreach my $possrole ('ca','aa') {
+                if (ref($by_roletype{$possrole}) eq 'HASH') {
+                    my $roletitle = &Apache::lonnet::plaintext($possrole);
+                    foreach my $author (sort { lc($a) cmp lc($b) } (keys(%{$by_roletype{$possrole}}))) {
+                        my ($none,$where,$auname,$audom) = split(/\//,$toppath{$author});
+                        $pickdir .= '<option value="'.$author.'___'.$possrole.'">'.
+                                     $roletitle." ($audom/$auname)</option>\n";
                     }
-                    $pickdir .= '</select>';
-                } else {
-                    $pickdir .= '<input type="hidden" name="authorpath" value="/" />'."\n";   
                 }
             }
         }
-
+        if ($checkcrsres) {
+            $pickdir .= '<option value="course">'.&mt('Course Resource').'</option>'."\n";
+        }
+        $pickdir .= '</select><br />'."\n".
+                    $lt{'dire'}.
+                    '<select name="authorpath" onchange="toggleCrsResTitle();">'.
+                    '<option value=""></option>'.
+                    '</select><br />'."\n";
         my %seltemplate_menus;
         my @files = &Apache::lonhomework::get_template_list('problem');
         my @noexamplelink = ('blank.problem','blank.library','script.library');
@@ -6454,16 +8047,21 @@ NWEBFORM
                                                                 "resize_scrollbox('contentscroll','1','0');",
                                                                 "toggleExampleText();",'template').'<br />';
         my $templatepreview =  '<a href="#" target="sample" onclick="javascript:getExample(600,420,\'yes\',true);  return false;">'.
-                               '<span id="newresexample">'.&mt('Example').'<span></a>';
-        my $crsresform=(<<RESFORM);
-        <a class="LC_menubuttons_link" href="javascript:toggleCrsRes('res','$numauthor','$numcrsdirs');">
-        $lt{'stpr'}</a>$help{'Course_Resource'}
+                               '<span id="newresexample">'.&mt('Example').'</span></a>';
+        my $crsresform;
+        if (($env{'user.author'}) || ($checkcrsres)) {
+            $crsresform=(<<RESFORM);
+        <a class="LC_menubuttons_link" href="javascript:toggleCrsRes('res');">
+        $lt{'stpr'}</a>$help{'Standard_Problem'}
         <form action="/adm/coursedocs" method="post" name="courseresform">
         <fieldset id="crsresform" style="display:none;">
         <legend>$lt{'stpr'}</legend>
-        <input type="hidden" name="active" value="ee" />
+        <input type="hidden" name="active" value="bb" />
         <p>
         $pickdir
+        </p>
+        <div id="newstdproblem" style="display:none;">
+        <p>
         <span class="LC_nobreak">$lt{'news'}?&nbsp;
         <label><input type="radio" name="newsubdir" value="0" onclick="toggleNewsubdir(this.form);" checked="checked" $disabled />No</label>
         &nbsp;
@@ -6471,10 +8069,11 @@ NWEBFORM
         </span><span id="newsubdir"></span>
         <input type="hidden" name="newsubdirname" id="newsubdirname" value="" autocomplete="off" />
         </p>
+        </div>
         $lt{'fnam'}
         <input type="text" size="20" name="newresourcename" autocomplete="off" $disabled />
+        <div id="newresource" style="display:none">
         <p>
-        <div id="newresource" style="display:$showtitle">
         $lt{'addp'}
         <label><input type="radio" name="newresourceadd" value="0" checked="checked" onclick="toggleNewInCourse(this.form);" $disabled />
         $lt{'no'}</label>&nbsp;&nbsp;
@@ -6482,27 +8081,32 @@ NWEBFORM
         $lt{'yes'}</label>
         <span id="newrestitle"></span>
         <input type="hidden" size="20" name="newresourcetitle" id="newresourcetitle" autocomplete="off" $disabled />
-        </div>
         </p>
+        </div>
         <p>
         $lt{'uste'}
         <label><input type="radio" name="newresusetemp" value="0" checked="checked" onclick="toggleWithTemplate(this.form);" $disabled />
         $lt{'no'}</label>&nbsp;&nbsp;
         <label><input type="radio" name="newresusetemp" value="1" onclick="toggleWithTemplate(this.form);" $disabled />
         $lt{'yes'}</label>
+        </p>
         <div id="newrestemplate" style="display:none">
         $templates
         $templatepreview
         </div>
-        </p>
         <span class="LC_nobreak">
-        <input type="hidden" name="folderpath" value="$env{'form.folderpath'}" />
+        <input type="hidden" name="folderpath" value="$showpath" />
         <input type="submit" name="newcrs" value="$lt{'crpr'}" $disabled />
         </span>
+        <div id="stdprobswitch" style="display:none;">
+        $rolehomes
+        <input type="button" name="switchfornewprob" value="$lt{'swit'}" onclick="switchForProb();" />
+        </div>
         </fieldset>
         </form>
 
 RESFORM
+        }
 
 my $specialdocumentsform;
 my @specialdocumentsforma;
@@ -6549,7 +8153,7 @@ NSYLFORM
 
 	my $newgroupfileform=(<<NGFFORM);
 	<form action="/adm/coursedocs" method="post" name="newgroupfiles">
-	<input type="hidden" name="active" value="dd" />
+	<input type="hidden" name="active" value="ee" />
 	$pathitem
 	<input type="hidden" name="importdetail"
 	value="$lt{'grpo'}=/adm/$coursedom/$coursenum/aboutme" />
@@ -6557,24 +8161,32 @@ 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 @importdoc = (
-        {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="toggleUpload(\'ext\');" />'=>$extresourcesform}
-        );
-        if (keys(%ltitools)) {
-            push(@importdoc,
-                {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/exttool.png" alt="'.$lt{extt}.'" onclick="toggleUpload(\'tool\');" />'=>$exttoolform},
+        my @external = (
+        {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="toggleExternal(\'ext\');" />'=>$extresourcesform}
         );
+        if ($posslti) {
+            push(@external,
+                 {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/exttool.png" alt="'.$lt{extt}.'" onclick="toggleExternal(\'tool\');" />'=>$exttoolform},
+            );
         }
+        my $externalform = &create_form_ul(&create_list_elements(@external));
+
+        my @importdoc = ();
         unless ($container eq 'page') {
             push(@importdoc,
                 {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/ims.png" alt="'.$lt{imsf}.'" onclick="javascript:toggleUpload(\'ims\');" />'=>$imspform}
@@ -6588,9 +8200,13 @@ NGFFORM
         @gradingforma=(
         {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simpprob.png" alt="'.$lt{sipr}.'" onclick="javascript:makesmpproblem();" />'=>$newsmpproblemform},
         {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/dropbox.png" alt="'.$lt{drbx}.'" onclick="javascript:makedropbox();" />'=>$newdropboxform},
-        {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/scoreupfrm.png" alt="'.$lt{scuf}.'" onclick="javascript:makeexamupload();" />'=>$newexuploadform},
-        {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simpprob.png" alt="'.$lt{stpr}.'" onclick="javascript:toggleCrsRes(\'res\','."'$numauthor','$numcrsdirs'".');" />'=>$crsresform},
+        {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/scoreupfrm.png" alt="'.$lt{scuf}.'" onclick="javascript:makeexamupload();" />'=>$newexuploadform}
         );
+        if ($crsresform) {
+            push(@gradingforma,
+                 {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simpprob.png" alt="'.$lt{stpr}.'" onclick="javascript:toggleCrsRes(\'res\');" />'=>$crsresform}
+            );
+        }
         $gradingform = &create_form_ul(&create_list_elements(@gradingforma));
 
         @communityforma=(
@@ -6604,13 +8220,14 @@ NGFFORM
 
 my %orderhash = (
                 'aa' => ['Upload',$fileuploadform],
-                'bb' => ['Import',$importpubform],
-                'cc' => ['Grading',$gradingform],
+                'bb' => ['External',$externalform],
+                'cc' => ['Import',$importpubform],
+                'dd' => ['Assessment',$gradingform],
+                'ff' => ['Other',$specialdocumentsform],
                 );
 unless ($container eq 'page') {
     $orderhash{'00'} = ['Newfolder',$newfolderform];
-    $orderhash{'dd'} = ['Collaboration',$communityform];
-    $orderhash{'ee'} = ['Other',$specialdocumentsform];
+    $orderhash{'ee'} = ['Collaboration',$communityform];
 }
 
  $hadchanges=0;
@@ -6638,7 +8255,7 @@ unless ($container eq 'page') {
        unless ($supplementalflag) {
 	   $folder='supplemental';
        }
-       if ($folder =~ /^supplemental$/ &&
+       if (($folder eq 'supplemental') &&
 	   (($env{'form.folderpath'} =~ /^default\&/) || ($env{'form.folderpath'} eq ''))) {
           $env{'form.folderpath'} = &supplemental_base();
        } elsif ($allowed) {
@@ -6658,6 +8275,8 @@ unless ($container eq 'page') {
         <legend>$lt{'upfi'}</legend>
 	<input type="hidden" name="active" value="ee" />
 	$fileupload
+        <input type="file" name="uploaddoc" id="uploaddocsupp" class="LC_flUpload LC_uploaddoc" size="40" $disabled />
+        <input type="hidden" id="LC_free_space_supp" value="$free_space" />
 	<br />
 	<br />
 	<span class="LC_nobreak">
@@ -6670,6 +8289,7 @@ unless ($container eq 'page') {
 	$pathitem
 	<input type="hidden" name="cmd" value="upload_supplemental" />
         <input type='submit' value="$lt{'upld'}" />
+        </fieldset>
         </form>
 SUPDOCFORM
 
@@ -6746,15 +8366,15 @@ my @specialdocs = (
                 {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/webpage.png" alt="'.$lt{webp}.'" onclick="javascript:makewebpage('."'supp'".');" />'=>$supwebpageform},
 
 		);
-my @supimportdoc = (
-		{'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="javascript:toggleUpload(\'suppext\')" />'
-            =>$supextform});
-        if (keys(%ltitools)) {
-            push(@supimportdoc,
-                {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/exttool.png" alt="'.$lt{extt}.'" onclick="javascript:toggleUpload(\'supptool\')" />'
+        my @supexternal = (
+            {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="javascript:toggleExternal(\'suppext\')" />'
+             =>$supextform});
+        if ($posslti) {
+            push(@supexternal,
+                 {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/exttool.png" alt="'.$lt{extt}.'" onclick="javascript:toggleExternal(\'supptool\')" />'
             =>$supexttoolform});
         }
-        push(@supimportdoc, 
+        my @supimportdoc = (
             {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/pdfupload.png" alt="'.$lt{upl}.'" onclick="javascript:toggleUpload(\'suppdoc\');" />'
             =>$supupdocform},
         );
@@ -6762,33 +8382,27 @@ my @supimportdoc = (
 $supupdocform =  &create_form_ul(&create_list_elements(@supimportdoc));
 my %suporderhash = (
 		'00' => ['Supnewfolder', $supnewfolderform],
-                'ee' => ['Upload',$supupdocform],
+                'dd' => ['Upload',$supupdocform],
+                'ee' => ['External',&create_form_ul(&create_list_elements(@supexternal))],
                 '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) {
+                &Apache::lonnet::update_supp_caches($coursedom,$coursenum);
+                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>');
         }
@@ -6952,6 +8566,10 @@ sub remove_archive {
             if ($url eq $env{'form.archiveurl'}) {
                 if (&handle_edit_cmd($docuname,$docudom)) {
                     ($errtext,$fatal) = &storemap($docuname,$docudom,$map,1);
+                    if ($suppchanges) {
+                        &Apache::lonnet::update_supp_caches($docudom,$docuname);
+                        undef($suppchanges);
+                    }
                     if ($fatal) {
                         if ($container eq 'page') {
                             $delwarning = &mt('An error occurred updating the contents of the current page.');
@@ -6983,7 +8601,7 @@ sub remove_archive {
 }
 
 sub generate_admin_menu {
-    my ($crstype,$canedit) = @_;
+    my ($crstype,$canedit,$coursenum,$coursedom) = @_;
     my $lc_crstype = lc($crstype);
     my ($home,$other,%outhash)=&authorhosts();
     my %lt= ( # do not translate here
@@ -6991,14 +8609,17 @@ sub generate_admin_menu {
                                          'cv'   => 'Check/Set Resource Versions',
                                          'ls'   => 'List Resource Identifiers',
                                          'ct'   => 'Display/Set Shortened URLs for Deep-linking',
+                                         'ca'   => "Enter $crstype Authoring Space",
                                          'imse' => 'Export contents to IMS Archive',
-                                         'dcd'  => "Copy $crstype Content to Authoring Space",
+                                         'dcd'  => 'Copy uploaded content to Authoring Space',
+                                         'cpc'  => 'Copy from Course Authoring to User Authoring',
             );
-    my ($candump,$dumpurl);
+    my ($candump,$dumpurl,$exportcrsurl);
     if ($home + $other > 0) {
         $candump = 'F';
         if ($home) {
             $dumpurl = "javascript:injectData(document.courseverify,'dummy','dumpcourse','$lt{'dcd'}')";
+            $exportcrsurl = "javascript:injectData(document.courseverify,'dummy','copyauthored','$lt{'cpc'}')";
         } else {
             my @hosts;
             foreach my $aurole (keys(%outhash)) {
@@ -7012,8 +8633,10 @@ sub generate_admin_menu {
                                &HTML::Entities::encode($env{'request.role'},'"<>&').'&amp;origurl='.
                                &HTML::Entities::encode('/adm/coursedocs?dumpcourse=1','"<>&');
                 $dumpurl = "javascript:dump_needs_switchserver('$switchto')";
+                $exportcrsurl = $dumpurl;
             } else {
                 $dumpurl = "javascript:choose_switchserver_window()";
+                $exportcrsurl = $dumpurl;
             }
         }
     }
@@ -7051,6 +8674,33 @@ sub generate_admin_menu {
                 ]
         });
     if ($canedit) {
+        my ($crsauname,$crsaudom,$crshome);
+        if (($coursenum ne '') && ($coursedom ne '')) {
+            my $crsauthorurl = "/priv/$coursedom/$coursenum/";
+            ($crsauname,$crsaudom,$crshome) = &Apache::lonnet::constructaccess($crsauthorurl);
+            if (($crsauname eq $coursenum) && ($crsaudom eq $coursedom)) {
+                my @ids=&Apache::lonnet::current_machine_ids();
+                my $linkurl;
+                if (grep(/^\Q$crshome\E$/,@ids)) {
+                    $linkurl = $crsauthorurl;
+                } else {
+                    my $jscall = &Apache::lonhtmlcommon::jump_to_editres($crsauthorurl,$crshome,1);
+                    if ($jscall) {
+                        $linkurl = 'javascript:'.$jscall;
+                    }
+                }
+                if ((ref($menu[0]) eq 'HASH') && (ref($menu[0]->{'items'}) eq 'ARRAY') && ($linkurl)) {
+                     push(@{$menu[0]->{items}},
+                     {   linktext   => $lt{'ca'},
+                         url        => $linkurl,
+                         permission => 'F',
+                         help       => 'Docs_Course_Authorspace',
+                         icon       => 'impcrsau.png',
+                         linktitle  => $lt{'ca'},
+                     });
+                }
+            }
+        }
         push(@menu,
         {   categorytitle=>'Export',
             items =>[
@@ -7070,6 +8720,18 @@ sub generate_admin_menu {
                 },
                 ]
         });
+        if (($crsauname eq $coursenum) && ($crsaudom eq $coursedom)) {
+            if ((ref($menu[1]) eq 'HASH') && (ref($menu[1]->{'items'}) eq 'ARRAY')) {
+                push(@{$menu[1]->{items}},
+                     {   linktext   => $lt{'cpc'},
+                         url        => $exportcrsurl,
+                         permission => 'F',
+                         help       => 'Docs_Export_Course_Author',
+                         icon       => 'res.png',
+                         linktitle  => $lt{'cpc'},
+                     });
+            }
+        }
     }
     return '<form action="/adm/coursedocs" method="post" name="courseverify">'."\n".
            '<input type="hidden" id="dummy" />'."\n".
@@ -7226,6 +8888,8 @@ sub editing_js {
                                           tinc    => 'Title in course',
                                           sunm    => 'Sub-directory name',
                                           edri    => 'Editing rights unavailable for your current role.',
+                                          sele    => 'Select',
+                                          swit    => 'Switch server required',
                                         );
     &js_escape(\%js_lt);
     my $crstype = &Apache::loncommon::course_type();
@@ -7237,7 +8901,9 @@ sub editing_js {
     my $backtourl;
     my $toplevelmain = &escape(&default_folderpath($coursenum,$coursedom,$navmapref));
     my $toplevelsupp = &supplemental_base();
-
+    my $showfile_js = &Apache::loncommon::show_crsfiles_js();
+    my @ids=&Apache::lonnet::current_machine_ids();
+    my $machines_str = "'".join("','",@ids)."'";
     if ($env{'docs.exit.'.$env{'request.course.id'}} =~ /^direct_(.+)$/) {
         my $caller = $1;
         if ($caller =~ /^supplemental/) {
@@ -7266,14 +8932,21 @@ 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://})) {
-                        if ($hostname ne '') {
-                            $backtourl = 'http://'.$hostname.$backtourl;
+                        unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) {
+                            if ($hostname ne '') {
+                                $backtourl = 'http://'.$hostname.$backtourl;
+                            }
+                            $backtourl .= (($backtourl =~ /\?/) ? '&amp;':'?').'usehttp=1';
                         }
-                        $backtourl .= (($backtourl =~ /\?/) ? '&amp;':'?').'usehttp=1';
                     }
                 } elsif ($backtourl =~ m{^/adm/wrapper/ext/(?!https:)}) {
                     if (($ENV{'SERVER_PORT'} == 443) && ($hostname ne '')) {
-                        $backtourl = 'http://'.$hostname.$backtourl;
+                        unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) {
+                            if ($hostname ne '') {
+                                $backtourl = 'http://'.$hostname.$backtourl;
+                            }
+                            $backtourl .= (($backtourl =~ /\?/) ? '&amp;':'?').'usehttp=1';
+                        }
                     }
                 }
                 if ($anchor ne '') {
@@ -7287,32 +8960,39 @@ 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';
     }
 
-    my $fieldsets = "'ext','doc'";
-    if ($posslti) {
-        $fieldsets .= ",'tool'";
-    }
+    my $fieldsets = "'doc'";
     unless ($main_container_page) {
         $fieldsets .=",'ims'";
     }
+    my $extfieldsets = "'ext'";
+    if ($posslti) {
+        $extfieldsets .= ",'tool'";
+    }
     if ($supplementalflag) {
-        $fieldsets = "'suppext','suppdoc'";
+        $fieldsets = "'suppdoc'";
+        $extfieldsets = "'suppext'";
         if ($posslti) {
-            $fieldsets .= ",'supptool'";
+            $extfieldsets .= ",'supptool'";
         }
     }
-    
+
     my $jsmakefunctions;
     if ($canedit) {
         $jsmakefunctions = <<ENDNEWSCRIPT;
 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();
     }
 }
@@ -7320,7 +9000,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();
     }
 }
@@ -7329,7 +9009,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();
    }
 }
@@ -7338,7 +9018,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();
    }
 }
@@ -7353,7 +9033,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();
    }
 }
@@ -7362,7 +9042,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();
    }
 }
@@ -7371,7 +9051,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();
    }
 }
@@ -7380,7 +9060,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();
    }
 }
@@ -7526,16 +9206,32 @@ function toggleUpload(caller) {
             }
         }
         document.getElementById('upload'+blocks[i]+'form').style.display=disp;
+    }
+    resize_scrollbox('contentscroll','1','1');
+    return;
+}
+
+function toggleExternal(caller) {
+    var blocks = Array($extfieldsets);
+    for (var i=0; i<blocks.length; i++) {
+        var disp = 'none';
+        if (caller == blocks[i]) {
+            var curr = document.getElementById('external'+caller+'form').style.display;
+            if (curr == 'none') {
+                disp='block';
+            }
+        }
+        document.getElementById('external'+blocks[i]+'form').style.display=disp;
         if ((caller == 'tool') || (caller == 'supptool')) {
             if (disp == 'block') {
-                if (document.getElementById('LC_exttoolid')) { 
-                    var toolselector = document.getElementById('LC_exttoolid'); 
+                if (document.getElementById('LC_exttoolid')) {
+                    var toolselector = document.getElementById('LC_exttoolid');
                     var suppflag = 0;
                     if (caller == 'supptool') {
                         suppflag = 1;
                     }
                     currForm = document.getElementById('new'+caller);
-                    updateExttool(toolselector,currForm,suppflag); 
+                    updateExttool(toolselector,currForm,suppflag);
                 }
             }
         }
@@ -7554,32 +9250,33 @@ function toggleMap(caller) {
             }
         }
         document.getElementById('importmapform').style.display=disp;
+        if (disp == 'block') {
+            if (document.getElementById('importcrsresform')) {
+                if (document.getElementById('importcrsresform').style.display == 'block') {
+                    document.getElementById('importcrsresform').style.display = 'none';
+                }
+            }
+        }
         resize_scrollbox('contentscroll','1','1');
     }
     return;
 }
 
-function toggleCrsRes(caller,numauthorrole,numcrsdirs) {
+function toggleCrsRes(caller) {
     var disp = 'none';
     if (document.getElementById('crsresform')) {
         if (caller == 'res') {
-            var curr = document.getElementById('crsresform').style.display;
+            var form = document.getElementById('crsresform');
+            var curr = form.style.display;
             if (curr == 'none') {
                 disp='block';
-                numauthor = parseInt(numauthorrole);
-                if (numauthor > 0) {
-                    document.courseresform.authorrole.selectedIndex = 0;
-                    select1priv_changed();
-                    document.courseresform.authorpath.selectedIndex = 0;
-                    document.courseresform.newresourceadd.selectedIndex = 0;
-                    toggleNewInCourse(document.courseresform);
-                    if (document.getElementById('newresource')) {
-                        document.getElementById('newresource').style.display = 'none';
-                    }
-                } else {
-                    if (numcrsdirs) {
-                        document.courseresform.authorpath.selectedIndex = 0;
-                    }
+                document.courseresform.authorrole.selectedIndex = 0;
+                document.courseresform.authorpath.selectedIndex = 0;
+                document.courseresform.newresourceadd.selectedIndex = 0;
+                populateDirSelects(form,'authorrole','authorpath',1,0,0);
+                toggleNewInCourse(document.courseresform);
+                if (document.getElementById('newresource')) {
+                    document.getElementById('newresource').style.display = 'none';
                 }
                 if (document.courseresform.newresusetemp.length) {
                     document.courseresform.newresusetemp[0].checked = true;
@@ -7633,14 +9330,28 @@ function toggleNewsubdir(form) {
 
 function toggleCrsResTitle() {
     if (document.getElementById('newresource')) {
-        if (document.courseresform.authorrole.options[document.courseresform.authorrole.selectedIndex].value == 'course') {
+        var selloc = document.courseresform.authorrole.options[document.courseresform.authorrole.selectedIndex].value;
+        if (selloc == 'course') {
             document.getElementById('newresource').style.display = 'inline';
             document.courseresform.newresourceadd[0].checked = true;
             toggleNewInCourse(document.courseresform);
         } else {
             document.getElementById('newresource').style.display = 'none';
         }
-    } 
+    }
+    if (document.getElementById('newstdproblem')) {
+        if (document.courseresform.authorpath.options[document.courseresform.authorpath.selectedIndex].value == 'switch') {
+            document.getElementById('newstdproblem').style.display = 'none'; 
+            if (document.getElementById('stdprobswitch')) {
+                document.getElementById('stdprobswitch').style.display = 'block'; 
+            }
+        } else {
+            document.getElementById('newstdproblem').style.display = 'block';
+            if (document.getElementById('stdprobswitch')) {
+                document.getElementById('stdprobswitch').style.display = 'none';
+            }
+        }
+    }
 }
 
 function toggleNewInCourse(form) {
@@ -7720,25 +9431,208 @@ function getExample(width,height,scrolli
     }
 }
 
-function toggleImportCrsres(caller,dircount) {
+function toggleImportCrsres(caller) {
     var disp = 'none';
     if (document.getElementById('importcrsresform')) {
         if (caller == 'res') {
-            var numdirs = parseInt(dircount);
             var curr = document.getElementById('importcrsresform').style.display;
             if (curr == 'none') {
                 disp='block';
-                if (numdirs > 1) {
-                    select1res_changed();
+                populateCrsSelects(document.crsresimportform,'coursepath','coursefile',1,'',1,0,1,1,0);
+                if ((document.getElementById('importcrsrescontent')) &&
+                    (document.getElementById('importcrsresempty'))) {
+                    var selelem = document.crsresimportform.elements['coursepath'];
+                    var numdirs = 0;
+                    if (selelem.options.length) {
+                        numdirs = selelem.options.length - 1;
+                    }
+                    if (numdirs) {
+                        document.getElementById('importcrsrescontent').style.display='block';
+                        document.getElementById('importcrsresempty').style.display='none';
+                    } else {
+                        document.getElementById('importcrsrescontent').style.display='none';
+                        document.getElementById('importcrsresempty').style.display='block';
+                    }
                 }
             }
         }
         document.getElementById('importcrsresform').style.display=disp;
+        if (disp == 'block') {
+            if (document.getElementById('importmapform')) {
+                if (document.getElementById('importmapform').style.display == 'block') {
+                    document.getElementById('importmapform').style.display = 'none';
+                }
+            }
+        }
         resize_scrollbox('contentscroll','1','0');
     }
     return;
 }
 
+$showfile_js
+
+function populateDirSelects(form,locsel,dirsel,setdir,recurse,nonemptydir) {
+    var location = form.elements[locsel].options[form.elements[locsel].selectedIndex].value;
+    if ((setdir) && (dirsel != null) && (dirsel != 'undefined') && (dirsel != '')) {
+        var selelem = form.elements[dirsel];
+        var i, numfiles = selelem.options.length -1;
+        if (numfiles >=0) {
+            for (i = numfiles; i >= 0; i--) {
+                selelem.remove(i);
+            }
+        }
+        if ((location == '') || (location == null) || (location == 'undefined')) {
+             if (selelem.options.length == 0) {
+                 selelem.options[selelem.options.length] = new Option('','');
+                 selelem.selectedIndex = 0;
+             }
+             if (document.getElementById('newstdproblem')) {
+                 document.getElementById('newstdproblem').style.display = 'none';
+             }
+             return;
+        }
+        var machineIds = new Array($machines_str);
+        var athome = 0;
+        var role = location;
+        if ((location == 'author') || (location == 'course')) {
+            if (document.getElementById('rolehome_'+location)) {
+                var currhome = document.getElementById('rolehome_'+location).value;
+                if ((currhome != '') && (currhome != null) && (currhome != 'undefined')) {
+                    if (machineIds.includes(currhome)) {
+                        athome = 1;
+                    }
+                }
+            }
+        } else {
+            const roleinfo = location.split('___');
+            role = encodeURIComponent(roleinfo[0]+'./'+roleinfo[1]);
+            if (document.getElementById('rolehome_coauthor_'+roleinfo[1]+'_'+roleinfo[0])) {
+                var currhome = document.getElementById('rolehome_coauthor_'+roleinfo[1]+'_'+roleinfo[0]).value;
+                if ((currhome != '') && (currhome != null) && (currhome != 'undefined')) {
+                    if (machineIds.includes(currhome)) {
+                        athome = 1;
+                    }
+                }
+            }
+        }
+        var templateradio = document.courseresform.elements['newresusetemp'];
+        if (athome) {
+            if (document.getElementById('stdprobswitch')) {
+                document.getElementById('stdprobswitch').style.display = 'none';
+            }
+            if (document.getElementById('newstdproblem')) {
+                document.getElementById('newstdproblem').style.display = 'none';
+            }
+            var canedit = '$canedit';
+            if (canedit) {
+                if (templateradio.length > 1) {
+                    for (var i=0; i<templateradio.length; i++) {
+                        templateradio[i].disabled = false;
+                    }
+                }
+                document.courseresform.newresourcename.disabled = false;
+                document.courseresform.newcrs.disabled = false;
+            }
+            var http = new XMLHttpRequest();
+            var url = "/adm/courseauthor";
+            var params = "role="+role+"&rec="+recurse+"&nonempty="+nonemptydir+"&addtop=1";
+            http.open("POST", url, true);
+            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+            http.onreadystatechange = function() {
+                if (http.readyState == 4 && http.status == 200) {
+                    var data = JSON.parse(http.responseText);
+                    if (Array.isArray(data.dirs)) {
+                        var len = data.dirs.length;
+                        if (len) {
+                            if (len > 1) {
+                                selelem.options[selelem.options.length] = new Option('$js_lt{sele}','');
+                            }
+                        }
+                        if (len) {
+                            var j;
+                            for (j = 0; j < len; j++) {
+                                selelem.options[selelem.options.length] = new Option(data.dirs[j],data.dirs[j]);
+                            }
+                            selelem.selectedIndex = 0;
+                            if (len == 1) {
+                                toggleCrsResTitle();
+                            }
+                        }
+                    }
+                }
+            }
+            http.send(params);
+        } else {
+            selelem.options[selelem.options.length] = new Option('$js_lt{swit}','switch');
+            selelem.selectedIndex = 0;
+            if (document.getElementById('stdprobswitch')) {
+                document.getElementById('stdprobswitch').style.display = 'block';
+            }
+            if (document.getElementById('newstdproblem')) {
+                document.getElementById('newstdproblem').style.display = 'none';
+            }
+            if (templateradio.length > 1) {
+                for (var i=0; i<templateradio.length; i++) {
+                    templateradio[i].disabled = true;
+                }
+            }
+            document.courseresform.newresourcename.disabled = true;
+            document.courseresform.newcrs.disabled = true;
+        }
+    }
+    return;
+}
+
+function switchForProb() {
+    if (document.courseresform.authorpath.options[document.courseresform.authorpath.selectedIndex].value == 'switch') {
+        var url = '/adm/switchserver?otherserver=';
+        var newhostid = '';
+        var role = '';
+        var selloc = document.courseresform.authorrole.options[document.courseresform.authorrole.selectedIndex].value;
+        if (selloc == 'author') {
+            newhostid = document.courseresform.rolehome_author.value;
+            role = "au./&js_escape($env{'user.domain'})/";
+        } else if (selloc == 'course') {
+            newhostid = document.courseresform.rolehome_course.value;
+            role = "&js_escape($env{'request.role'})";
+        } else {
+            var items = new Array();
+            items = selloc.split('___');
+            var len = document.courseresform.rolehome_coauthor.length;
+            if (null == len) {
+                var currval = document.courseresform.rolehome_coauthor.value;
+                if (null != currval) {
+                    var info = new Array();
+                    info = currval.split('=');
+                    newhostid = info[2];
+                    role = info[0]+'./'+info[1];
+                }
+            } else {
+                for (var i=0; i<len; i++) {
+                    var currval = document.courseresform.rolehome_coauthor[i].value;
+                    if (null != currval) {
+                        var info = new Array();
+                        info = currval.split('=');
+                        if ((info[1] == items[1]+'/'+items[0]) && (info[0] == items[2])) {
+                            newhostid = info[2];
+                            role = info[0]+'./'+info[1];
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        if (newhostid != '') {
+            url += newhostid;
+            if (role != '') {
+                url += '&role='+role;
+            }
+            document.location.href = url;
+        }
+    }
+    return;
+}
+
 function makeims(imsform) {
     if ((imsform.uploaddoc.value == '')  || (!imsform.uploaddoc.value)) {
         alert("$js_lt{'imsfile'}");
@@ -8092,6 +9986,7 @@ function showPage(current, pageId, nav,
                 current.className = 'right';
             }
             activeTab = ''; 
+            toggleExternal();
             toggleUpload();
             toggleMap();
             toggleCrsRes();
@@ -8104,6 +9999,7 @@ function showPage(current, pageId, nav,
 	currentData = document.getElementById(pageId);
 	currentData.style.display = 'block';
         activeTab = pageId;
+        toggleExternal();
         toggleUpload();
         toggleMap();
         toggleCrsRes();
@@ -8486,7 +10382,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;
 }
 
@@ -8533,7 +10429,7 @@ sub dump_switchserver_js {
     );
     my %html_js_lt = &Apache::lonlocal::texthash(
         swit => 'Switch server?',
-        duco => 'Copying Content to Authoring Space',
+        duco => 'Copying uploaded content to Authoring Space',
         yone => 'You need to switch to a server housing an Authoring Space for which you are author or co-author.',
         chos => 'Choose server',
     );
@@ -8637,7 +10533,7 @@ sub makenewproblem {
         if ($env{'form.newsubdir'}) {
             if ($env{'form.newsubdirname'} ne '') {
                 $newsubdir = $env{'form.newsubdirname'};
-            }    
+            }
         }
         if ($env{'form.newresourcename'}) {
             $filename = $env{'form.newresourcename'};
@@ -8674,107 +10570,33 @@ sub makenewproblem {
                         if ($redirect) {
                             my $rightsfile = 'default.rights';
                             my $sourcerights = "$path/$rightsfile";
+                            &Apache::loncommon::crsauthor_rights($rightsfile,$path,$docroot,$coursenum,$coursedom);
                             my $targetrights = $docroot."/res/$coursedom/$coursenum/$rightsfile";
-                            my $now = time;
-                            if (!-e $sourcerights) {
-                                my $cid = $coursedom.'_'.$coursenum;
-                                if (open(my $fh,">$sourcerights")) {
-                                    print $fh <<END;
-<accessrule effect="deny" realm="" type="course" role="" />
-<accessrule effect="allow" realm="$cid" type="course" role="" />
-END
-                                    close($fh);
+                            if ((-e $sourcerights) && (-e "$sourcerights.meta")) {
+                                if (!-e "$docroot/res/$coursedom") {
+                                    mkdir("$docroot/res/$coursedom",0755);
+                                }
+                                if (!-e "$docroot/res/$coursedom/$coursenum") {
+                                    mkdir("$docroot/res/$coursedom/$coursenum",0755);
+                                }
+                                if ((-e "$docroot/res/$coursedom/$coursenum") && (!-e $targetrights)) {
+                                    my $nokeyref = &Apache::lonpublisher::getnokey($r->dir_config('lonIncludes'));
+                                    my $output = &Apache::lonpublisher::batchpublish($r,$sourcerights,$targetrights,$nokeyref,1);
                                 }
                             }
-                            if (!-e "$sourcerights.meta") {
-                                if (open(my $fh,">$sourcerights.meta")) {
+                            my $source = $docroot.$redirect;
+                            if (!-e "$source.meta") {
+                                my $cid = $coursedom.'_'.$coursenum;
+                                my $now = time;
+                                if (open(my $fh,">$source.meta")) {
                                     my $author=$env{'environment.firstname'}.' '.
                                                $env{'environment.middlename'}.' '.
                                                $env{'environment.lastname'}.' '.
                                                $env{'environment.generation'};
                                     $author =~ s/\s+$//;
-                                    print $fh <<"END";
-
-<abstract></abstract>
-<author>$author</author>
-<authorspace>$coursenum:$coursedom</authorspace>
-<copyright>private</copyright>
-<creationdate>$now</creationdate>
-<customdistributionfile></customdistributionfile>
-<dependencies></dependencies>
-<domain>$coursedom</domain>
-<highestgradelevel>0</highestgradelevel>
-<keywords></keywords>
-<language>notset </language>
-<lastrevisiondate>$now</lastrevisiondate>
-<lowestgradelevel>0</lowestgradelevel>
-<mime>rights</mime>
-<modifyinguser>$env{'user.name'}:$env{'user.domain'}</modifyinguser>
-<notes></notes>
-<obsolete></obsolete>
-<obsoletereplacement></obsoletereplacement>
-<owner>$coursenum:$coursedom</owner>
-<rule>deny:::course,allow:$cid::course</rule>
-<sourceavail></sourceavail>
-<standards></standards>
-<subject></subject>
-<title></title>
-END
-                                        close($fh);
-                                }
-                                if ((-e $sourcerights) && (-e "$sourcerights.meta")) {
-                                    if (!-e "$docroot/res/$coursedom") {
-                                        mkdir("$docroot/res/$coursedom",0755);
-                                    }
-                                    if (!-e "$docroot/res/$coursedom/$coursenum") {
-                                        mkdir("$docroot/res/$coursedom/$coursenum",0755);
-                                    }
-                                    if ((-e "$docroot/res/$coursedom/$coursenum") && (!-e $targetrights)) {
-                                        my $nokeyref = &Apache::lonpublisher::getnokey($r->dir_config('lonIncludes'));
-                                        my $output = &Apache::lonpublisher::batchpublish($r,$sourcerights,$targetrights,$nokeyref,1);
-                                    }
-                                }
-                            }
-                            if ($env{'form.newresourceadd'}) {
-                                my $template = $env{'form.template'};
-                                my $source = $docroot.$redirect;
-                                my $target = $redirect;
-                                $target =~ s{^/priv/}{/res/};
-                                $target = $docroot.$target;
-                                if (!-e $source) {
-                                    my $copyfrom; 
-                                    if ($template) {
-                                        my %templates;
-                                        my @files = &Apache::lonhomework::get_template_list('problem');
-                                        foreach my $poss (@files) {
-                                            if (ref($poss) eq 'ARRAY') {
-                                                if ($template eq $poss->[0]) {
-                                                    $templates{$template} = 1;
-                                                    last;
-                                                }
-                                            }
-                                        }
-                                        if ($templates{$template}) {
-                                            $copyfrom = $template;
-                                        }
-                                    }
-                                    unless ($copyfrom) {
-                                        $copyfrom = $r->dir_config('lonIncludes').'/templates/blank.problem';
-                                    }
-                                    &File::Copy::copy($copyfrom,$source);
-                                }
-                                if (!-e "$source.meta") {
-                                    my $cid = $coursedom.'_'.$coursenum;
-                                    my $now = time;
-                                    if (open(my $fh,">$source.meta")) {
-                                        my $author=$env{'environment.firstname'}.' '.
-                                                   $env{'environment.middlename'}.' '.
-                                                   $env{'environment.lastname'}.' '.
-                                                   $env{'environment.generation'};
-                                        $author =~ s/\s+$//;
-                                        my $title = $env{'form.newresourcetitle'};
-                                        $title =~ s/^\s+|\s+$//g;
-                                        print $fh <<END;
+                                    my $title = $env{'form.newresourcetitle'};
+                                    $title =~ s/^\s+|\s+$//g;
+                                    print $fh <<END;
 
 <abstract></abstract>
 <author>$author</author>
@@ -8800,8 +10622,7 @@ END
 <subject></subject>
 <title>$title</title>
 END
-                                        close($fh);
-                                    }
+                                    close($fh);
                                 }
                             }
                         }
@@ -8829,7 +10650,7 @@ END
 }
 
 sub finishnewprob {
-    my ($url,$path,$subdir,$newsubdir,$filename) = @_;
+    my ($url,$path,$subdir,$newsubdir,$filename,$context) = @_;
     unless (-d $path) {
         unless (mkdir($path,02770)) {
             return;
@@ -8872,6 +10693,31 @@ sub finishnewprob {
             $redirect = "$url/$filename";
         }
     }
+    if ((!-e $dest) && ($context ne 'upload')) {
+        my $template = $env{'form.template'};
+        my $copyfrom;
+        if ($template ne '') {
+            my %templates;
+            my @files = &Apache::lonhomework::get_template_list('problem');
+            foreach my $poss (@files) {
+                if (ref($poss) eq 'ARRAY') {
+                    if ($template eq $poss->[0]) {
+                        $templates{$template} = 1;
+                        last;
+                    }
+                }
+            }
+            if ($templates{$template}) {
+                $copyfrom = $template;
+            }
+        }
+        if ($filename =~ /\.problem$/) {
+            unless ($copyfrom) {
+                $copyfrom = $Apache::lonnet::perlvar{'lonIncludes'}.'/templates/blank.problem';
+            }
+            &File::Copy::copy($copyfrom,$dest);
+        }
+    }
     return $redirect;
 }