--- loncom/interface/londocs.pm	2017/09/05 00:56:42	1.640
+++ loncom/interface/londocs.pm	2020/08/27 16:21:35	1.673
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Documents
 #
-# $Id: londocs.pm,v 1.640 2017/09/05 00:56:42 raeburn Exp $
+# $Id: londocs.pm,v 1.673 2020/08/27 16:21:35 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -45,6 +45,8 @@ 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 GDBM_File;
@@ -52,6 +54,7 @@ use File::MMagic;
 use File::Copy;
 use Apache::lonlocal;
 use Cwd;
+use UUID::Tiny ':std';
 use LONCAPA qw(:DEFAULT :match);
 
 my $iconpath;
@@ -659,7 +662,7 @@ sub group_import {
                 my $marker = $2;
                 my $info = $3;
                 my ($toolid,%toolhash,%toolsettings);
-                my @extras = ('linktext','explanation','crslabel','crstitle');
+                my @extras = ('linktext','explanation','crslabel','crstitle','crsappend');
                 my @toolinfo = split(/:/,$info);
                 if ($residx) {
                     %toolsettings=&Apache::lonnet::dump('exttool_'.$marker,$coursedom,$coursenum);
@@ -669,14 +672,19 @@ sub group_import {
                 }
                 $toolid =~ s/\D//g;
                 ($toolhash{'target'},$toolhash{'width'},$toolhash{'height'},
-                 $toolhash{'linktext'},$toolhash{'explanation'},
-                 $toolhash{'crslabel'},$toolhash{'crstitle'}) = @toolinfo;
+                 $toolhash{'linktext'},$toolhash{'explanation'},$toolhash{'crslabel'},
+                 $toolhash{'crstitle'},$toolhash{'crsappend'},$toolhash{'gradable'}) = @toolinfo;
                 foreach my $item (@extras) {
                     $toolhash{$item} = &unescape($toolhash{$item});
                 }
+                if ($folder =~ /^supplemental/) {
+                    delete($toolhash{'gradable'});
+                } else {
+                    $toolhash{'gradable'} =~ s/\D+//g;
+                }
                 if (ref($ltitoolsref) eq 'HASH') {
-                    my @deleted;
                     if (ref($ltitoolsref->{$toolid}) eq 'HASH') {
+                        my @deleted;
                         $toolhash{'id'} = $toolid;
                         if (($toolhash{'target'} eq 'iframe') || ($toolhash{'target'} eq 'tab') ||
                             ($toolhash{'target'} eq 'window')) {
@@ -751,11 +759,51 @@ sub group_import {
                                 }
                             }
                         }
+                        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 (($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';
+                                }
+                                &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);
                         }
                     }
                 }
@@ -993,6 +1041,7 @@ sub docs_change_log {
 	    'encrypturl'     => 'URL hidden',
 	    'randompick'     => 'Randomly pick',
 	    'randomorder'    => 'Randomly ordered',
+            'gradable'       => 'Grade can be assigned to External Tool',
 	    'set'            => 'set to',
 	    'del'            => 'deleted');
     my $filter = &Apache::loncommon::display_filter('docslog')."\n".
@@ -1100,7 +1149,7 @@ 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>');
-	    foreach my $parameter ('randompick','hiddenresource','encrypturl','randomorder') {
+	    foreach my $parameter ('randompick','hiddenresource','encrypturl','randomorder','gradable') {
 		if ($docslog{$id}{'logentry'}{'parameter_action_'.$parameter}) {
 # FIXME: internationalization seems wrong here
 		    $r->print('<li>'.
@@ -1168,13 +1217,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;
+                }
+            }
         }
     }
 
@@ -1183,7 +1238,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);
@@ -1196,7 +1251,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 '') {
@@ -1741,7 +1802,7 @@ 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.',
                 duplicate => 'Paste failed: only one instance of a particular published sequence or page is allowed within each course.',
             );
 
@@ -1770,14 +1831,7 @@ 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);
 
 # Loop over the items to paste
     foreach my $suffix (@dopaste) {
@@ -1795,6 +1849,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);
@@ -1852,13 +1913,18 @@ sub do_paste_from_buffer {
         }
         if ($url=~ m{/(bulletinboard|smppg|ext\.tool)$}) {
             my $prefix = $1;
-            my $fromothercrs; 
+            my $fromothercrs;
             #need to copy the db contents to a new one, unless this is a move.
             my %info = (
                          src  => $url,
                          cdom => $coursedom,
                          cnum => $coursenum,
                        );
+            if ($prefix eq 'ext.tool') {
+                if ($prefixchg{$suffix} eq 'docstosupp') {
+                    $info{'delgradable'} = 1;
+                }
+            }
             if (($srcdom{$suffix} =~ /^$match_domain$/) && ($srcnum{$suffix} =~ /^$match_courseid$/)) {
                 unless (($srcdom{$suffix} eq $coursedom) && ($srcnum{$suffix} eq $coursenum)) {
                     $fromothercrs = 1;
@@ -1950,6 +2016,18 @@ sub do_paste_from_buffer {
                     &copy_templated_files($url,$srcdom{$suffix},$srcnum{$suffix},$srcmapidx{$suffix},
                                           $coursedom,$coursenum,$template,$newidx,"$folder.$container");
                 }
+            } elsif ($url =~ /ext\.tool$/) {
+                if (($newidx) && ($folder=~/^default/)) {
+                    my $marker = (split(m{/},$url))[4];
+                    my %toolsettings = &Apache::lonnet::dump('exttool_'.$marker,$coursedom,$coursenum);
+                    my $val = 'no';
+                    if ($toolsettings{'gradable'}) {
+                        $val = 'yes';
+                    }
+                    &LONCAPA::map::storeparameter($newidx,'parameter_0_gradable',$val,
+                                                  'string_yesno');
+                    &remember_parms($newidx,'gradable','set',$val);
+                }
             }
             $LONCAPA::map::resources[$newidx]=$title.':'.&LONCAPA::map::qtunescape($url).
                                               ':'.$ext.':normal:res';
@@ -2198,6 +2276,9 @@ sub dbcopy {
                         }
                     }
                     $db_name =~ s{_\d*$ }{_$suffix}x;
+                    if (($prefix eq 'exttool') && ($dbref->{'delgradable'}) && ($contents{'gradable'})) {
+                        delete($contents{'gradable'});
+                    }
                     $result=&Apache::lonnet::put($db_name,\%contents,
                                                  $coursedom,$coursenum);
                     if ($result eq 'ok') {
@@ -2260,7 +2341,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;
@@ -2482,16 +2565,38 @@ sub url_paste_fixups {
                         $changed = 1;
                     }
                 }
-            } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/.+$}) {
+            } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/(.+)$}) {
                 next if ($skip);
                 my $srcdom = $1;
                 my $srcnum = $2;
+                my $rem = $3;
+                my ($is_exttool,$exttoolchg);
+                if ($rem =~ m{\d+/ext\.tool$}) {
+                    $is_exttool = 1;
+                }
                 if (($srcdom ne $cdom) || ($srcnum ne $cnum)) {
                     $rewrites->{$oldurl}{$id} = $ressrc;
                     $dbcopies->{$oldurl}{$id}{'src'} = $ressrc;
                     $dbcopies->{$oldurl}{$id}{'cdom'} = $srcdom;
                     $dbcopies->{$oldurl}{$id}{'cnum'} = $srcnum;
                     $changed = 1;
+                    if ($is_exttool) {
+                        $exttoolchg = 1;
+                    }
+                } elsif (($rem =~ m{\d+/ext\.tool$}) &&
+                         ($env{'form.docs.markedcopy_options'} ne 'move')) {
+                    $dbcopies->{$oldurl}{$id}{'src'} = $ressrc;
+                    $dbcopies->{$oldurl}{$id}{'cdom'} = $srcdom;
+                    $dbcopies->{$oldurl}{$id}{'cnum'} = $srcnum;
+                    $changed = 1;
+                    $exttoolchg = 1;
+                }
+                if (($is_exttool) && ($prefixchg)) {
+                    if ($oldurl =~ m{^/uploaded/$match_domain/$match_courseid/default}) {
+                        if ($exttoolchg) {
+                            $dbcopies->{$oldurl}{$id}{'delgradable'} = 1;
+                        }
+                    }
                 }
             } elsif ($ressrc =~ m{^/adm/$match_domain/$match_username/\d+/(smppg|bulletinboard)$}) {
                 if (($fromcdom ne $cdom) || ($fromcnum ne $cnum) ||
@@ -2712,9 +2817,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'};
@@ -2724,15 +2827,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);
                             }
@@ -2755,7 +2861,8 @@ sub apply_fixups {
                     }
                 }
             }
-            for (my $i=0; $i<@LONCAPA::map::order; $i++) {
+            my $total = scalar(@LONCAPA::map::order) - 1;
+            for (my $i=$total; $i>=0; $i--) {
                 my $idx = $LONCAPA::map::order[$i];
                 if (defined($LONCAPA::map::resources[$idx])) {
                     my $changed;
@@ -2765,7 +2872,7 @@ sub apply_fixups {
                         splice(@LONCAPA::map::order,$i,1);
                         if (ref($currparam{$idx}) eq 'ARRAY') {
                             foreach my $name (@{$currparam{$idx}}) {
-                                &LONCAPA::map::delparameter($idx,'parameter_'.$name);
+                                &LONCAPA::map::delparameter($idx,$name);
                             }
                         }
                         next;
@@ -2807,7 +2914,7 @@ sub apply_fixups {
             foreach my $idx (keys(%remparam)) {
                 if (ref($remparam{$idx}) eq 'ARRAY') {
                     foreach my $name (@{$remparam{$idx}}) {   
-                        &LONCAPA::map::delparameter($idx,'parameter_'.$name);
+                        &LONCAPA::map::delparameter($idx,$name);
                     }
                 }
             }
@@ -4050,11 +4157,19 @@ END
     my ($editlink,$extresform,$anchor,$hiddenres,$nomodal);
     my $orig_url = $url;
     $orig_url=~s{http(&colon;|:)//https(&colon;|:)//}{https$2//};
-    $url=~s{^http(|s)(&colon;|:)//}{/adm/wrapper/ext/};
+    if ($container eq 'page') {
+        $url=~s{^http(|s)(&colon;|:)//}{/ext/};
+    } else {
+        $url=~s{^http(|s)(&colon;|:)//}{/adm/wrapper/ext/};
+    }
     if (!$supplementalflag && $residx && $symb) {
         if ((!$isfolder) && (!$ispage)) {
 	    (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
-	    $url=&Apache::lonnet::clutter($url);
+            if (($url =~ m{^ext/}) && ($container eq 'page')) {
+                $url=&Apache::lonnet::clutter_with_no_wrapper($url);
+            } else {
+                $url=&Apache::lonnet::clutter($url);
+            } 
 	    if ($url=~/^\/*uploaded\//) {
 	        $url=~/\.(\w+)$/;
 	        my $embstyle=&Apache::loncommon::fileembstyle($1);
@@ -4068,7 +4183,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:/)) {
@@ -4079,19 +4194,18 @@ 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()) {
+                        $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;
-                        }
+                    $url =~ s/\#[^#]+$//;
+                    if ($container eq 'page') {
+                        $url = &Apache::lonnet::clutter($url);
                     }
                 }
                 unless ($env{'request.role.adv'}) {
@@ -4104,7 +4218,7 @@ END
                     }
                 }
                 if ($url ne '') {
-                    $url.=(($url=~/\?/)?'&':'?').'symb='.&HTML::Entities::encode($shownsymb,'"<>&');
+                    $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($shownsymb);
                 }
             } elsif (!$env{'request.role.adv'}) {
                 my $checkencrypt;
@@ -4125,7 +4239,7 @@ END
                     my $shownsymb = &Apache::lonenc::encrypted($symb);
                     my $shownurl = &Apache::lonenc::encrypted($url);
                     if (&Apache::lonnet::symbverify($shownsymb,$shownurl)) {
-                        $url = $shownurl.(($shownurl=~/\?/)?'&':'?').'symb='.&HTML::Entities::encode($shownsymb,'"<>&');
+                        $url = $shownurl.(($shownurl=~/\?/)?'&':'?').'symb='.&escape($shownsymb);
                         if ($env{'request.enc'} ne '') {
                             delete($env{'request.enc'});
                         }
@@ -4145,8 +4259,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()) {
+                        if ($hostname ne '') {
+                            $url = 'http://'.$hostname.$url;
+                        }
+                        $url .= (($url =~ /\?/) ? '&amp;':'?').'usehttp=1';
                     }
                     $nomodal = 1;
                 }
@@ -4154,10 +4271,12 @@ 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()) {
+                    if ($hostname ne '') {
+                        $url = 'http://'.$hostname.$url;
+                    }
+                    $url .= (($url =~ /\?/) ? '&amp;':'?').'usehttp=1';
                 }
-                $url .= (($url =~ /\?/) ? '&amp;':'?').'usehttp=1';
                 $nomodal = 1;
             }
         }
@@ -4311,7 +4430,7 @@ $form_end;
         $reinit = &mt('(re-initialize course to access)');
     }
     $line.='<td class="LC_docs_entry_commands"'.$tdalign.'><span class="LC_nobreak">'.$editlink.$renamelink;
-    if ($url =~ /$LONCAPA::assess_re/) {
+    if ($orig_url =~ /$LONCAPA::assess_re/) {
         $line.= '<br />';
         if ($curralias ne '') {
             $line.='<span class="LC_nobreak"><a href="javascript:delalias('."'$esc_path','$orderidx'".');" class="LC_docs_alias">'.
@@ -4338,8 +4457,7 @@ $form_end;
        } else {
            $link = $url;
        }
-       $link = &js_escape($link.(($url=~/\?/)?'&amp;':'?').'inhibitmenu=yes'.
-                                               (($anchor ne '')?$anchor:''));
+       $link = &js_escape($link.(($url=~/\?/)?'&amp;':'?').'inhibitmenu=yes'.$anchor);
        if ($nomodal) {
            $line.='<a href="#" onclick="javascript:window.open('."'$link','syllabuspreview','height=400,width=500,scrollbars=1,resizable=1,menubar=0,location=1')".'; return false;" />'.
                   '<img src="'.$icon.'" alt="" class="LC_icon" border="0" /></a>';
@@ -4721,6 +4839,48 @@ sub list_symbs {
     $r->print(&endContentScreen());
 }
 
+sub short_urls {
+    my ($r,$canedit) = @_;
+    my $crstype = &Apache::loncommon::course_type();
+    my $formname = 'shortenurl';
+    $r->print(&Apache::loncommon::start_page('Display/Set Shortened URLs'));
+    $r->print(&Apache::lonhtmlcommon::breadcrumbs('Shortened URLs'));
+    $r->print(&startContentScreen('tools'));
+    my ($navmap,$errormsg) =
+        &Apache::loncourserespicker::get_navmap_object($crstype,'shorturls');
+    my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+    my (%maps,%resources,%titles);
+    if (!ref($navmap)) {
+        $r->print($errormsg.
+                  &endContentScreen());
+        return '';
+    } else {
+        $r->print('<h4 class="LC_info">'.&mt('Tiny URLs for deep-linking into course').'</h4>'."\n");
+        $r->rflush();
+        my $readonly;
+        if ($canedit) {
+            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>');
+            }
+            if ((ref($errors) eq 'ARRAY') && (@{$errors} > 0)) {
+                $r->print(&mt('The following errors occurred when processing your request to create shortened URLs:').'<br /><ul>');
+                foreach my $error (@{$errors}) {
+                    $r->print('<li>'.$error.'</li>');
+                }
+                $r->print('</ul><br />');
+            }
+        } else {
+            $readonly = 1;
+        }
+        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));
+    }
+    $r->print(&endContentScreen());
+}
+
 sub contentverifyform {
     my ($r) = @_;
     my $crstype = &Apache::loncommon::course_type();
@@ -5091,13 +5251,17 @@ sub changewarning {
     if (!defined($message)) {
 	$message='Changes will become active for your current session after [_1], or the next time you log in.';
     }
+    my $windowname = 'loncapaclient';
+    if ($env{'request.lti.login'}) {
+        $windowname .= 'lti';
+    }
     $r->print("\n\n".
 '<script type="text/javascript">'."\n".
 '// <![CDATA['."\n".
 'function reinit(tf) { tf.submit();'.$postexec.' }'."\n".
 '// ]]>'."\n".
 '</script>'."\n".
-'<form name="reinitform" method="post" action="/adm/roles" target="loncapaclient">'.
+'<form name="reinitform" method="post" action="/adm/roles" target="'.$windowname.'">'.
 '<input type="hidden" name="orgurl" value="'.$url.
 '" /><input type="hidden" name="selectrole" value="1" /><p class="LC_warning">'.
 &mt($message,' <input type="hidden" name="'.
@@ -5256,6 +5420,9 @@ sub handler {
   } elsif ($allowed && $env{'form.listsymbs'}) {
       &init_breadcrumbs('listsymbs','List Content IDs');
       &list_symbs($r);
+  } elsif ($allowed && $env{'form.shorturls'}) {
+      &init_breadcrumbs('shorturls','Set/Display Shortened URLs','Docs_Short_URLs');
+      &short_urls($r,$canedit);
   } elsif ($allowed && $env{'form.docslog'}) {
       &init_breadcrumbs('docslog','Show Log');
       my $folder = $env{'form.folder'};
@@ -5319,6 +5486,8 @@ sub handler {
                       $r->internal_redirect($redirect);
                       return OK;
                   }
+              } else {
+                  $r->internal_redirect($redirect);
               }
           }
       }
@@ -5486,7 +5655,7 @@ sub handler {
             undef($env{'form.folderpath'});
         } else {
             $folderurl = "uploaded/$coursedom/$coursenum/$folder";
-            if ((split(/\:/,$pathitems[-1]))[4]) {
+            if ((split(/\:/,$pathitems[-1]))[5]) {
                 $folderurl .= '.page';
             } else {
                 $folderurl .= '.sequence';
@@ -5580,7 +5749,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');
@@ -5590,7 +5759,7 @@ sub handler {
                 }
             }
             my $tabidstr = join("','",@tabids);
-            %ltitools = &Apache::lonnet::get_domain_ltitools($coursedom);
+            %ltitools = &Apache::lonnet::get_domain_lti($coursedom,'consumer');
             my $posslti = keys(%ltitools);
             my $hostname = $r->hostname();
 	    $script .= &editing_js($udom,$uname,$supplementalflag,$coursedom,$coursenum,$posslti,
@@ -5819,8 +5988,8 @@ 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" />
+	<input type="file" name="uploaddoc" class="LC_flUpload" size="40" $disabled />
+        <input type="hidden" id="LC_free_space" value="$free_space" />
 FIUP
 
 	my $checkbox=(<<CHBO);
@@ -6016,9 +6185,13 @@ HIDDENFORM
        }
        my $postexec='';
        if ($folder eq 'default') {
+           my $windowname = 'loncapaclient';
+           if ($env{'request.lti.login'}) {
+               $windowname .= 'lti';
+           }
            $r->print('<script type="text/javascript">'."\n"
                     .'// <![CDATA['."\n"
-                    .'this.window.name="loncapaclient";'."\n"
+                    .'this.window.name="'.$windowname.'";'."\n"
                     .'// ]]>'."\n"
                     .'</script>'."\n"
        );
@@ -6031,7 +6204,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" />
@@ -6041,7 +6214,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>
@@ -6051,7 +6224,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>
@@ -6062,7 +6235,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>
@@ -6072,7 +6245,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>
@@ -6082,7 +6255,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>
@@ -6092,7 +6265,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" />
@@ -6103,7 +6276,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>
@@ -6112,7 +6285,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" />
@@ -6133,7 +6306,7 @@ 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>
@@ -6316,7 +6489,7 @@ NWEBFORM
         <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
         <span class="LC_nobreak">$lt{'news'}?&nbsp;
@@ -6404,7 +6577,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" />
@@ -6412,24 +6585,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}
+        my @external = (
+        {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="toggleExternal(\'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},
-        );
+            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}
@@ -6460,12 +6641,13 @@ NGFFORM
 my %orderhash = (
                 'aa' => ['Upload',$fileuploadform],
                 'bb' => ['Import',$importpubform],
-                'cc' => ['Grading',$gradingform],
+                'cc' => ['External',$externalform],
+                'dd' => ['Grading',$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;
@@ -6601,15 +6783,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});
+        my @supexternal = (
+            {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="javascript:toggleExternal(\'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\')" />'
+            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},
         );
@@ -6617,7 +6799,8 @@ 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) {
@@ -6845,6 +7028,7 @@ sub generate_admin_menu {
                                          'vc'   => 'Verify Content',
                                          'cv'   => 'Check/Set Resource Versions',
                                          'ls'   => 'List Resource Identifiers',
+                                         'ct'   => 'Display/Set Shortened URLs for Deep-linking',
                                          'imse' => 'Export contents to IMS Archive',
                                          'dcd'  => "Copy $crstype Content to Authoring Space",
             );
@@ -6895,6 +7079,13 @@ sub generate_admin_menu {
                     icon       => 'symbs.png',
                     linktitle  => "List the unique identifier used for each resource instance in your $lc_crstype"
                 },
+                {   linktext   => $lt{'ct'},
+                    url        => "javascript:injectData(document.courseverify,'dummy','shorturls','$lt{'ct'}')",
+                    permission => 'F',
+                    help       => 'Docs_Short_URLs',
+                    icon       => 'shorturls.png',
+                    linktitle  => "Set shortened URLs for a resource or folder in your $lc_crstype for use in deep-linking"
+                },
                 ]
         });
     if ($canedit) {
@@ -7113,14 +7304,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()) {
+                            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()) {
+                            if ($hostname ne '') {
+                                $backtourl = 'http://'.$hostname.$backtourl;
+                            }
+                            $backtourl .= (($backtourl =~ /\?/) ? '&amp;':'?').'usehttp=1';
+                        }
                     }
                 }
                 if ($anchor ne '') {
@@ -7139,20 +7337,22 @@ sub editing_js {
         $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;
@@ -7373,16 +7573,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);
                 }
             }
         }
@@ -7939,6 +8155,7 @@ function showPage(current, pageId, nav,
                 current.className = 'right';
             }
             activeTab = ''; 
+            toggleExternal();
             toggleUpload();
             toggleMap();
             toggleCrsRes();
@@ -7951,6 +8168,7 @@ function showPage(current, pageId, nav,
 	currentData = document.getElementById(pageId);
 	currentData.style.display = 'block';
         activeTab = pageId;
+        toggleExternal();
         toggleUpload();
         toggleMap();
         toggleCrsRes();
@@ -8484,7 +8702,7 @@ sub makenewproblem {
         if ($env{'form.newsubdir'}) {
             if ($env{'form.newsubdirname'} ne '') {
                 $newsubdir = $env{'form.newsubdirname'};
-            }    
+            }
         }
         if ($env{'form.newresourcename'}) {
             $filename = $env{'form.newresourcename'};
@@ -8567,61 +8785,34 @@ END
 <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);
-                                    }
+                                    close($fh);
                                 }
                             }
-                            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 $sourcerights) && (-e "$sourcerights.meta")) {
+                                if (!-e "$docroot/res/$coursedom") {
+                                    mkdir("$docroot/res/$coursedom",0755);
                                 }
-                                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;
+                                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);
+                                }
+                            }
+                            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+$//;
+                                    my $title = $env{'form.newresourcetitle'};
+                                    $title =~ s/^\s+|\s+$//g;
+                                    print $fh <<END;
 
 <abstract></abstract>
 <author>$author</author>
@@ -8647,8 +8838,7 @@ END
 <subject></subject>
 <title>$title</title>
 END
-                                        close($fh);
-                                    }
+                                    close($fh);
                                 }
                             }
                         }
@@ -8676,7 +8866,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;
@@ -8719,6 +8909,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;
 }