--- loncom/interface/londocs.pm 2012/07/13 13:36:24 1.491 +++ loncom/interface/londocs.pm 2012/07/22 04:01:24 1.492 @@ -1,7 +1,7 @@ # The LearningOnline Network # Documents # -# $Id: londocs.pm,v 1.491 2012/07/13 13:36:24 raeburn Exp $ +# $Id: londocs.pm,v 1.492 2012/07/22 04:01:24 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -69,10 +69,14 @@ sub mapread { } sub storemap { - my ($coursenum,$coursedom,$map)=@_; + my ($coursenum,$coursedom,$map,$contentchg)=@_; + my $report; + if (($contentchg) && ($map =~ /^default/)) { + $report = 1; + } my ($outtext,$errtext)= &LONCAPA::map::storemap('/uploaded/'.$coursedom.'/'.$coursenum.'/'. - $map,1); + $map,1,$report); if ($errtext) { return ($errtext,2); } $hadchanges=1; @@ -305,7 +309,7 @@ sub group_import { join(':', ($name, $url, $ext, 'normal', 'res')); } } - return &storemap($coursenum, $coursedom, $folder.'.'.$container); + return &storemap($coursenum, $coursedom, $folder.'.'.$container,1); } sub breadcrumbs { @@ -612,7 +616,7 @@ sub docs_change_log { } sub update_paste_buffer { - my ($coursenum,$coursedom) = @_; + my ($coursenum,$coursedom,$folder) = @_; return if (!defined($env{'form.markcopy'})); return if (!defined($env{'form.copyfolder'})); @@ -633,75 +637,211 @@ sub update_paste_buffer { } $url=~s{http(:|:)//https(:|:)//}{https$2//}; - &Apache::lonnet::appenv({'docs.markedcopy_title' => $title, - 'docs.markedcopy_url' => $url}); + (my $cmd,undef)=split('_',$env{'form.cmd'}); + + my %addtoenv = ( + 'docs.markedcopy_title' => $title, + 'docs.markedcopy_url' => $url, + 'docs.markedcopy_cmd' => $cmd, + ); + &Apache::lonnet::delenv('docs.markedcopy_nested'); + &Apache::lonnet::delenv('docs.markedcopy_nestednames'); + if ($url =~ m{^/uploaded/$match_domain/$match_courseid/(default|supplemental)_?(\d*)\.(page|sequence)$}) { + my $prefix = $1; + my $subdir =$2; + if ($subdir eq '') { + $subdir = $prefix; + } + my (%addedmaps,%removefrommap,%removeparam,%hierarchy,%titles,%allmaps); + &contained_map_check($url,$folder,\%removefrommap,\%removeparam,\%addedmaps, + \%hierarchy,\%titles,\%allmaps); + if (ref($hierarchy{$url}) eq 'HASH') { + my ($nested,$nestednames); + &recurse_uploaded_maps($url,$subdir,\%hierarchy,\%titles,\$nested,\$nestednames); + $nested =~ s/\&$//; + $nestednames =~ s/\Q___&&&___\E$//; + if ($nested ne '') { + $addtoenv{'docs.markedcopy_nested'} = $nested; + } + if ($nestednames ne '') { + $addtoenv{'docs.markedcopy_nestednames'} = $nestednames; + } + } + } + &Apache::lonnet::appenv(\%addtoenv); delete($env{'form.markcopy'}); } +sub recurse_uploaded_maps { + my ($url,$dir,$hierarchy,$titlesref,$nestref,$namesref) = @_; + if (ref($hierarchy->{$url}) eq 'HASH') { + my @maps = map { $hierarchy->{$url}{$_}; } sort { $a <=> $b } (keys(%{$hierarchy->{$url}})); + my @titles = map { $titlesref->{$url}{$_}; } sort { $a <=> $b } (keys(%{$titlesref->{$url}})); + my (@uploaded,@names,%shorter); + for (my $i=0; $i<@maps; $i++) { + my ($inner) = ($maps[$i] =~ m{^/uploaded/$match_domain/$match_courseid/(?:default|supplemental)_(\d+)\.(?:page|sequence)$}); + if ($inner ne '') { + push(@uploaded,$inner); + push(@names,&escape($titles[$i])); + $shorter{$maps[$i]} = $inner; + } + } + $$nestref .= "$dir:".join(',',@uploaded).'&'; + $$namesref .= "$dir:".(join(',',@names)).'___&&&___'; + foreach my $map (@maps) { + if ($shorter{$map} ne '') { + &recurse_uploaded_maps($map,$shorter{$map},$hierarchy,$titlesref,$nestref,$namesref); + } + } + } + return; +} + sub print_paste_buffer { - my ($r,$container,$folder) = @_; + my ($r,$container,$folder,$coursedom,$coursenum) = @_; return if (!defined($env{'docs.markedcopy_url'})); - my $is_external; + my ($is_external,$othercourse,$fromsupp,$is_uploaded_map,$parent); my $extension = (split(/\./,$env{'docs.markedcopy_url'}))[-1]; if ($env{'docs.markedcopy_url'} =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) { $is_external = 1; } - my $canpaste; + my ($canpaste,$nopaste,$othercrs,$areachange,$is_uploaded_map); if ($folder =~ /^supplemental/) { - $canpaste = &supp_pasteable($env{'docs.markedcopy_url'}); + $canpaste = &supp_pasteable($env{'docs.markedcopy_url'}); + unless ($canpaste) { + $nopaste = &mt('Paste into Supplemental Content unavailable for this type of content.'); + } } else { $canpaste = 1; } - my $pasteinfo; if ($canpaste) { - $pasteinfo = '
' - .' '; - } else { - $pasteinfo = &mt('Paste buffer contains:').' '; + if ($env{'docs.markedcopy_url'} =~ m{^/uploaded/($match_domain)/($match_courseid)/(.+)$}) { + my $srcdom = $1; + my $srcnum = $2; + my $rem = $3; + if (($srcdom ne $coursedom) || ($srcnum ne $coursenum)) { + $othercourse = 1; + if ($env{"user.priv.cm./$srcdom/$srcnum"} =~ /\Q:mdc&F\E/) { + if ($canpaste) { + $othercrs = '
'.&mt('(from another course).'); + } + } else { + $canpaste = 0; + $nopaste = &mt('Paste from another course unavailable.') + } + } + if ($rem =~ m{^(default|supplemental)_?(\d*)\.(?:page|sequence)$}) { + my $prefix = $1; + $parent = $2; + if ($folder !~ /^\Q$prefix\E/) { + $areachange = 1; + } + $is_uploaded_map = 1; + } + } } $r->print('
' - .''.&mt('Clipboard').'' - .$pasteinfo - ); - - my $type; + .''.&mt('Clipboard').''); + my ($type,$buffer); if ($is_external) { - $type = &mt('External Resource'); - $r->print($type.': '. - &LONCAPA::map::qtescape($env{'docs.markedcopy_title'}).' ('. - &LONCAPA::map::qtescape($env{'docs.markedcopy_url'}).')'); + $type = &mt('External Resource'); + $buffer = $type.': '. + &LONCAPA::map::qtescape($env{'docs.markedcopy_title'}).' ('. + &LONCAPA::map::qtescape($env{'docs.markedcopy_url'}).')'; } else { - my $icon = &Apache::loncommon::icon($extension); - if ($extension eq 'sequence' && - $env{'docs.markedcopy_url'} =~ m{/default_\d+\.sequence$ }x) { - $icon = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL')); - $icon .= '/navmap.folder.closed.gif'; - } - $icon = ''; - $r->print($icon.$type.': '. &Apache::loncommon::parse_supplemental_title(&LONCAPA::map::qtescape($env{'docs.markedcopy_title'}))); + my $icon = &Apache::loncommon::icon($extension); + if ($extension eq 'sequence' && + $env{'docs.markedcopy_url'} =~ m{/default_\d+\.sequence$ }x) { + $icon = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL')); + $icon .= '/navmap.folder.closed.gif'; + } + $icon = ''; + $buffer = $icon.$type.': '. &Apache::loncommon::parse_supplemental_title(&LONCAPA::map::qtescape($env{'docs.markedcopy_title'})); } if ($canpaste) { + $r->print(''.$buffer); + if (($is_uploaded_map) && (!$areachange)) { + if ((!$othercourse) && ($env{'docs.markedcopy_cmd'} eq 'cut')) { + $r->print((' 'x 4).''. + ''. + &mt('Show Paste Options').'
'. + '
'.(' 'x 4). + ''.(' ' x2). + '
'); + if ($env{'docs.markedcopy_nested'}) { + $r->print('
'.&mt('Folder to paste contains sub-folders'). + '
'); + my @pastemaps = split(/\&/,$env{'docs.markedcopy_nested'}); + my @titles = split(/\Q___&&&___\E/,$env{'docs.markedcopy_nestednames'}); + my $lastdir = $parent; + my %depths = ( + $lastdir => 0, + ); + my (%display,%deps); + for (my $i=0; $i<@pastemaps; $i++) { + ($lastdir,my $subfolderstr) = split(/\:/,$pastemaps[$i]); + my ($namedir,$esctitlestr) = split(/\:/,$titles[$i]); + my @subfolders = split(/,/,$subfolderstr); + $deps{$lastdir} = \@subfolders; + my @subfoldertitles = map { &unescape($_); } split(/,/,$esctitlestr); + my $depth = $depths{$lastdir} + 1; + my $offset = int($depth * 4); + my $indent = (' ' x $offset); + for (my $j=0; $j<@subfolders; $j++) { + $depths{$subfolders[$j]} = $depth; + $display{$subfolders[$j]} = + ''. + ''; + } + } + &recurse_print($r,$parent,\%deps,\%display); + $r->print('
'.$indent.$subfoldertitles[$j].' '.(' ' x2). + ''. + '
'); + } + $r->print('
'); + } + } + $r->print('
'.$othercrs); if ($container eq 'page') { - $r->print(' - - + $r->print(' + + '); } else { - $r->print(' + $r->print(' '); } $r->print(''); } else { - $r->print('

'.&mt('Paste into Supplemental Content unavailable for this type of content.').'

'); + $r->print(&mt('Paste buffer contains:').' '.$buffer. + '

'.$nopaste.'

'); } $r->print('
'); } +sub recurse_print { + my ($r,$dir,$deps,$display) = @_; + $r->print($display->{$dir}."\n"); + if (ref($deps->{$dir}) eq 'ARRAY') { + foreach my $subdir (@{$deps->{$dir}}) { + &recurse_print($r,$subdir,$deps,$display); + } + } +} + sub supp_pasteable { my ($url) = @_; if (($url =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//}) || @@ -714,18 +854,53 @@ sub supp_pasteable { return; } +sub paste_popup_js { + my %lt = &Apache::lonlocal::texthash( + show => 'Show Paste Options', + hide => 'Hide Paste Options', + ); + return <<"END"; + +function showPasteOptions() { + document.getElementById('pasteoptions').style.display='block'; + document.getElementById('pasteoptions').style.textAlign='left'; + document.getElementById('pasteoptions').style.textFace='normal'; + document.getElementById('pasteoptionstext').innerHTML ='$lt{'hide'}
'; + return; +} + +function hidePasteOptions() { + document.getElementById('pasteoptions').style.display='none'; + document.getElementById('pasteoptionstext').innerHTML ='$lt{'show'}'; + return; +} + +END + +} + + sub do_paste_from_buffer { - my ($coursenum,$coursedom,$folder,$errors) = @_; + my ($coursenum,$coursedom,$folder,$container,$errors) = @_; +# Early out if paste buffer is empty if (!$env{'form.pastemarked'}) { - return; + return (); } -# Preparing to paste resource at end of list +# Supplemental content may only include certain types of content +# Early out if pasted content is not supported in Supplemental area + if ($folder =~ /^supplemental/) { + unless (&supp_pasteable($env{'docs.markedcopy_url'})) { + return (&mt('Paste failed: content type is not supported within Supplemental Content')); + } + } + +# Prepare to paste resource at end of list my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url'}); my $title=&LONCAPA::map::qtescape($env{'docs.markedcopy_title'}); - my ($is_map,$srcdom,$srcnum,$prefixchg,%before,%after,%mapchanges); + my ($is_map,$srcdom,$srcnum,$prefixchg,%before,%after,%mapchanges,%tomove); if ($url=~/\.(page|sequence)$/) { $is_map = 1; } @@ -733,11 +908,16 @@ sub do_paste_from_buffer { $srcdom = $1; $srcnum = $2; my $oldprefix = $3; +# When paste buffer was populated using an active role in a different course +# check for mdc privilege in the course from which the resource was pasted if (($srcdom ne $coursedom) || ($srcnum ne $coursenum)) { unless ($env{"user.priv.cm./$srcdom/$srcnum"} =~ /\Q:mdc&F\E/) { - return &mt('Paste failed: Item is from a different course which you do not have rights to edit.'); + return (&mt('Paste failed: Item is from a different course which you do not have rights to edit.')); } } +# When pasting content from Main Content to Supplemental Content and vice versa +# URLs will contain different paths (which depend on whether pasted item is +# a folder/page or a document. if (($folder =~ /^supplemental/) && (($oldprefix =~ /^default/) || ($oldprefix eq 'docs'))) { $prefixchg = 1; %before = ( map => 'default', @@ -751,27 +931,42 @@ sub do_paste_from_buffer { %after = ( map => 'default', doc => 'docs'); } - } -# Supplemental content may only include certain types of content - if ($folder =~ /^supplemental/) { - unless (&supp_pasteable($env{'docs.markedcopy_url'})) { - return &mt('Paste failed: content type is not supported within Supplemental Content'); +# If pasting an uploaded map, get list of contained uploaded maps. + my @nested; + if ($env{'docs.markedcopy_nested'}) { + my ($type) = ($oldprefix =~ /^(default|supplemental)/); + my @items = split(/\&/,$env{'docs.markedcopy_nested'}); + my @deps = map { /\d+:([\d,]+$)/ } @items; + foreach my $dep (@deps) { + if ($dep =~ /,/) { + push(@nested,split(/,/,$dep)); + } else { + push(@nested,$dep); + } + } + foreach my $item (@nested) { + if ($env{'form.docs.markedcopy_'.$item} eq 'move') { + $tomove{$type.'_'.$item} = 1; + } + } } } # Maps need to be copied first - my ($oldurl,%removefrommap,%addedmaps,%rewrites,%retitles,%copies,%dbcopies,%zombies, - %params,%docmoves,%mapmoves); + my ($oldurl,%removefrommap,%removeparam,%addedmaps,%rewrites,%retitles,%copies, + %dbcopies,%zombies,%params,%docmoves,%mapmoves,%newsubdir,%newurls); $oldurl = $url; if ($is_map) { -# If pasting a map, check if map contains other maps - my %allmaps; - &contained_map_check($url,$folder,\%removefrommap,\%addedmaps); if ($folder =~ /^default/) { - if (keys(%addedmaps) > 0) { - &reinit_role($coursedom,$coursenum,$env{"course.$env{'request.course.id'}.home"}); + my $lastchange = &Apache::lonnet::get_coursechange($coursedom,$coursenum); + if ($lastchange > $env{'request.course.tied'}) { + &reinit_role($coursedom,$coursenum,$env{"course.$env{'request.course.id'}.home"}); } + } +# If pasting a map, check if map contains other maps + my (%allmaps,%hierarchy,%titles); + if ($folder =~ /^default/) { my $navmap = Apache::lonnavmaps::navmap->new(); if (defined($navmap)) { foreach my $res ($navmap->retrieveResources(undef,sub { $_[0]->is_map() },1,0,1)) { @@ -779,84 +974,47 @@ sub do_paste_from_buffer { } } } + &contained_map_check($url,$folder,\%removefrommap,\%removeparam, + \%addedmaps,\%hierarchy,\%titles,\%allmaps); if ($url=~ m{^/uploaded/}) { - $title=&mt('Copy of').' '.$title; - } - my $now = time; - my $suffix=$$.int(rand(100)).$now; - my ($oldid,$ext) = ($url=~/^(.+)\.(\w+)$/); - if ($oldid =~ m{^(/uploaded/$match_domain/$match_courseid/)(\D+)(\d+)$}) { - my $path = $1; - my $prefix = $2; - my $ancestor = $3; - if (length($ancestor) > 10) { - $ancestor = substr($ancestor,-10,10); - } - my ($newurl,$newid); - if ($prefixchg) { - if ($folder =~ /^supplemental/) { - $prefix =~ s/^default/supplemental/; - } else { - $prefix =~ s/^supplemental/default/; - } - } - if (($srcdom eq $coursedom) && ($srcnum eq $coursenum)) { - $newurl = $path.$prefix.$ancestor.$suffix.'.'.$ext; - } else { - $newurl = "/uploaded/$coursedom/$coursenum/$prefix".$now.'.'.$ext; - } - my $counter = 0; - my $is_unique = &uniqueness_check($newurl); - if ($folder =~ /^default/) { - if ($allmaps{$newurl}) { - $is_unique = 0; - } - } - while (!$is_unique && $allmaps{$newurl} && $counter < 100) { - $counter ++; - $suffix ++; - if (($srcdom eq $coursedom) && ($srcnum eq $coursenum)) { - $newurl = $path.$prefix.$ancestor.$suffix.'.'.$ext; - } else { - $newurl = "/uploaded/$coursedom/$coursenum/$prefix".$ancestor.$suffix.'.'.$ext; - } - $is_unique = &uniqueness_check($newurl); - } - if ($is_unique) { - if ($newurl ne $oldurl) { - $mapchanges{$oldurl} = 1; - } - if (($srcdom ne $coursedom) || ($srcnum ne $coursenum) || ($prefixchg)) { - &url_paste_fixups($url,$prefixchg,$coursedom,$coursenum,\%allmaps, - \%rewrites,\%retitles,\%copies,\%dbcopies,\%zombies, - \%params,\%mapmoves,\%mapchanges); - } - } else { - if ($url=~/\.page$/) { - return &mt('Paste failed: an error occurred creating a unique URL for the composite page'); - } else { - return &mt('Paste failed: an error occurred creating a unique URL for the folder'); + my $newurl; + unless ($env{'form.docs.markedcopy_options'} eq 'move') { + ($newurl,my $error) = + &get_newmap_url($url,$folder,$prefixchg,$coursedom,$coursenum, + $srcdom,$srcnum,\$title,\%allmaps,\%newurls); + if ($error) { + return ($error); + } + if ($newurl ne '') { + if ($newurl ne $url) { + if ($newurl =~ /(?:default|supplemental)_(\d+).(?:sequence|page)$/) { + $newsubdir{$url} = $1; + } + $mapchanges{$url} = 1; + } } } - my $storefn=$newurl; - $storefn=~s{^/\w+/$match_domain/$match_username/}{}; - my $paste_map_result = - &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn, - &Apache::lonnet::getfile($url)); - if ($paste_map_result eq '/adm/notfound.html') { - if ($url=~/\.page$/) { - return &mt('Paste failed: an error occurred saving the composite page.'); - } else { - return &mt('Paste failed: an error occurred saving the folder.'); - } + if (($srcdom ne $coursedom) || ($srcnum ne $coursenum) || ($prefixchg) || + (($newurl ne '') && ($newurl ne $url))) { + unless (&url_paste_fixups($url,$folder,$prefixchg,$coursedom,$coursenum, + \%allmaps,\%rewrites,\%retitles,\%copies,\%dbcopies, + \%zombies,\%params,\%mapmoves,\%mapchanges,\%tomove, + \%newsubdir,\%newurls)) { + $mapmoves{$url} = 1; + } + $url = $newurl; + } elsif ($env{'docs.markedcopy_nested'}) { + &url_paste_fixups($url,$folder,$prefixchg,$coursedom,$coursenum,\%allmaps,\%rewrites, + \%retitles,\%copies,\%dbcopies,\%zombies,\%params,\%mapmoves, + \%mapchanges,\%tomove,\%newsubdir,\%newurls); } - $url = $newurl; } elsif ($url=~m {^/res/}) { # published maps can only exists once, so remove it from paste buffer when done &Apache::lonnet::delenv('docs.markedcopy'); - if ($folder =~ /^default/) { +# if pasting published map (main content are only) check map is not already in course + if ($folder =~ /^default/) { if ($allmaps{$url}) { - return &mt('Paste failed: only one instance of a particular published sequence or page is allowed within each course.'); + return (&mt('Paste failed: only one instance of a particular published sequence or page is allowed within each course.')); } } } @@ -874,7 +1032,7 @@ sub do_paste_from_buffer { $url =~ s{/(\d*)/smppg$ }{/$now/smppg}x; $title=&mt('Copy of').' '.$title; } else { - return &mt('Paste failed: An error occurred when copying the simple page.'); + return (&mt('Paste failed: An error occurred when copying the simple page.')); } } } @@ -882,33 +1040,34 @@ sub do_paste_from_buffer { my $ext='false'; if ($url=~m{^http(|s)://}) { $ext='true'; } $url = &LONCAPA::map::qtunescape($url); -# Now insert the URL at the bottom - my $newidx = &LONCAPA::map::getresidx($url); # For uploaded files (excluding pages/sequences) path in copied file is changed # if paste is from Main to Supplemental (or vice versa), or if pasting between # courses. + my $newidx; unless ($is_map) { +# Now insert the URL at the bottom + $newidx = &LONCAPA::map::getresidx($url); if ($url =~ m{^/uploaded/$match_domain/$match_courseid/(?:docs|supplemental)/(.+)$}) { my $relpath = $1; if ($relpath ne '') { my ($prefix,$subdir,$rem) = ($relpath =~ m{^(default|\d+)/(\d+)/(.+)$}); - my ($newloc,$newsubdir) = ($folder =~ /^(default|supplemental)_?(\d*)/); + my ($newloc,$newdocsdir) = ($folder =~ /^(default|supplemental)_?(\d*)/); my $newprefix = $newloc; if ($newloc eq 'default') { $newprefix = 'docs'; } - if ($newsubdir eq '') { - $newsubdir = 'default'; + if ($newdocsdir eq '') { + $newdocsdir = 'default'; } if (($prefixchg) || ($srcdom ne $coursedom) || ($srcnum ne $coursenum)) { - my $newpath = "$newprefix/$newsubdir/$newidx/$rem"; + my $newpath = "$newprefix/$newdocsdir/$newidx/$rem"; $url = &Apache::lonclonecourse::writefile($env{'request.course.id'},$newpath, &Apache::lonnet::getfile($oldurl)); if ($url eq '/adm/notfound.html') { - return &mt('Paste failed: an error occurred saving the file.'); + return (&mt('Paste failed: an error occurred saving the file.')); } else { my ($newsubpath) = ($newpath =~ m{^(.*/)[^/]*$}); $newsubpath =~ s{/+$}{/}; @@ -918,15 +1077,29 @@ sub do_paste_from_buffer { } } } - my $result = - &apply_fixups($is_map,$prefixchg,$coursedom,$coursenum,$oldurl,$url, - \%removefrommap,\%rewrites,\%retitles,\%copies,\%dbcopies, - \%zombies,\%params,\%docmoves,\%mapmoves,$errors,\%before,\%after); +# Apply any changes to maps, or copy dependencies for uploaded HTML pages + my ($result,$save_err); + $result = + &apply_fixups($folder,$is_map,$prefixchg,$coursedom,$coursenum,$oldurl, + $url,\%removefrommap,\%removeparam,\%rewrites,\%retitles, + \%copies,\%dbcopies,\%zombies,\%params,\%docmoves, + \%mapmoves,\%newsubdir,$errors,\%before,\%after); if ($result eq 'ok') { + if ($is_map) { + my ($errtext,$fatal) = &mapread($coursenum,$coursedom, + $folder.'.'.$container); + return $errtext if ($fatal); + + if ($#LONCAPA::map::order<1) { + my $idx=&LONCAPA::map::getresidx(); + if ($idx<=0) { $idx=1; } + $LONCAPA::map::order[0]=$idx; + $LONCAPA::map::resources[$idx]=''; + } + $newidx = &LONCAPA::map::getresidx($url); + } if ($env{'docs.markedcopy_supplemental'}) { - if ($folder =~ /^supplemental/) { - $title = $env{'docs.markedcopy_supplemental'}; - } else { + if ($folder !~ /^supplemental/) { (undef,undef,$title) = &Apache::loncommon::parse_supplemental_title($env{'docs.markedcopy_supplemental'}); } @@ -938,8 +1111,81 @@ sub do_paste_from_buffer { } $LONCAPA::map::resources[$newidx]= $title.':'.$url.':'.$ext.':normal:res'; push(@LONCAPA::map::order, $newidx); + +# Store the result + my ($errtext,$fatal) = + &storemap($coursenum,$coursedom,$folder.'.'.$container,1); + if ($fatal) { + $save_err = $errtext; + } + } + + if ($env{'form.docs.markedcopy_options'} eq 'move') { + &Apache::lonnet::delenv('docs.markedcopy'); + &Apache::lonnet::delenv('docs.markedcopy_nested'); + &Apache::lonnet::delenv('docs.markedcopy_nestednames'); + } + return ($result,$save_err); +} + +sub get_newmap_url { + my ($url,$folder,$prefixchg,$coursedom,$coursenum,$srcdom,$srcnum, + $titleref,$allmaps,$newurls) = @_; + my $newurl; + if ($url=~ m{^/uploaded/}) { + $$titleref=&mt('Copy of').' '.$$titleref; + } + my $now = time; + my $suffix=$$.int(rand(100)).$now; + my ($oldid,$ext) = ($url=~/^(.+)\.(\w+)$/); + if ($oldid =~ m{^(/uploaded/$match_domain/$match_courseid/)(\D+)(\d+)$}) { + my $path = $1; + my $prefix = $2; + my $ancestor = $3; + if (length($ancestor) > 10) { + $ancestor = substr($ancestor,-10,10); + } + my $newid; + if ($prefixchg) { + if ($folder =~ /^supplemental/) { + $prefix =~ s/^default/supplemental/; + } else { + $prefix =~ s/^supplemental/default/; + } + } + if (($srcdom eq $coursedom) && ($srcnum eq $coursenum)) { + $newurl = $path.$prefix.$ancestor.$suffix.'.'.$ext; + } else { + $newurl = "/uploaded/$coursedom/$coursenum/$prefix".$now.'.'.$ext; + } + my $counter = 0; + my $is_unique = &uniqueness_check($newurl); + if ($folder =~ /^default/) { + if ($allmaps->{$newurl}) { + $is_unique = 0; + } + } + while ((!$is_unique || $allmaps->{$newurl} || $newurls->{$newurl}) && ($counter < 100)) { + $counter ++; + $suffix ++; + if (($srcdom eq $coursedom) && ($srcnum eq $coursenum)) { + $newurl = $path.$prefix.$ancestor.$suffix.'.'.$ext; + } else { + $newurl = "/uploaded/$coursedom/$coursenum/$prefix".$ancestor.$suffix.'.'.$ext; + } + $is_unique = &uniqueness_check($newurl); + } + if ($is_unique) { + $newurls->{$newurl} = 1; + } else { + if ($url=~/\.page$/) { + return (undef,&mt('Paste failed: an error occurred creating a unique URL for the composite page')); + } else { + return (undef,&mt('Paste failed: an error occurred creating a unique URL for the folder')); + } + } } - return $result; + return ($newurl); } sub dbcopy { @@ -974,7 +1220,8 @@ sub uniqueness_check { } sub contained_map_check { - my ($url,$folder,$removefrommap,$addedmaps) = @_; + my ($url,$folder,$removefrommap,$removeparam,$addedmaps,$hierarchy,$titles, + $allmaps) = @_; my $content = &Apache::lonnet::getfile($url); unless ($content eq '-1') { my $parser = HTML::TokeParser->new(\$content); @@ -986,21 +1233,33 @@ sub contained_map_check { my $ressrc = $token->[2]->{'src'}; if ($folder =~ /^supplemental/) { unless (&supp_pasteable($ressrc)) { - $removefrommap->{$url}{$token->[2]->{'id'}}; + $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc; next; } } - if ($ressrc =~ /\.(sequence|page)$/) { - if (ref($addedmaps->{$ressrc}) eq 'ARRAY') { - push(@{$addedmaps->{$ressrc}},$url); + if ($ressrc =~ m{^/(res|uploaded)/.+\.(sequence|page)$}) { + if ($1 eq 'uploaded') { + $hierarchy->{$url}{$token->[2]->{'id'}} = $ressrc; + $titles->{$url}{$token->[2]->{'id'}} = $token->[2]->{'title'}; } else { - $addedmaps->{$ressrc} = [$url]; + if ($allmaps->{$ressrc}) { + $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc; + } elsif (ref($addedmaps->{$ressrc}) eq 'ARRAY') { + $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc; + } else { + $addedmaps->{$ressrc} = [$url]; + } } - &contained_map_check($ressrc,$folder,$removefrommap,$addedmaps); + &contained_map_check($ressrc,$folder,$removefrommap,$removeparam, + $addedmaps,$hierarchy,$titles,$allmaps); } - } elsif ($token->[1] !~ /^resource|map|link$/) { + } elsif ($token->[1] eq 'param') { if ($folder =~ /^supplemental/) { - $removefrommap->{$url}{$token->[1]}; + if (ref($removeparam->{$url}{$token->[2]->{'to'}}) eq 'ARRAY') { + push(@{$removeparam->{$url}{$token->[2]->{'to'}}},$token->[2]->{'name'}); + } else { + $removeparam->{$url}{$token->[2]->{'to'}} = [$token->[2]->{'name'}]; + } } } } @@ -1018,13 +1277,20 @@ sub reinit_role { } sub url_paste_fixups { - my ($oldurl,$prefixchg,$cdom,$cnum,$allmaps,$rewrites,$retitles,$copies, - $dbcopies,$zombies,$params,$mapmoves,$mapchanges) = @_; + my ($oldurl,$folder,$prefixchg,$cdom,$cnum,$allmaps,$rewrites,$retitles,$copies, + $dbcopies,$zombies,$params,$mapmoves,$mapchanges,$tomove,$newsubdir,$newurls) = @_; my $checktitle; if (($prefixchg) && - ($oldurl =~ m{^/uploaded/($match_domain)/($match_courseid)/supplemental})) { + ($oldurl =~ m{^/uploaded/$match_domain/$match_courseid/supplemental})) { $checktitle = 1; } + my $skip; + if ($oldurl =~ m{^\Q/uploaded/$cdom/$cnum/\E(default|supplemental)(_?\d*)\.(?:page|sequence)$}) { + my $mapid = $1.$2; + if ($tomove->{$mapid}) { + $skip = 1; + } + } my $file = &Apache::lonnet::getfile($oldurl); return if ($file eq '-1'); my $parser = HTML::TokeParser->new(\$file); @@ -1036,29 +1302,54 @@ sub url_paste_fixups { my $ressrc = $token->[2]->{'src'}; next if ($ressrc eq ''); my $id = $token->[2]->{'id'}; + my $title = $token->[2]->{'title'}; if ($checktitle) { - my $title = $token->[2]->{'title'}; if ($title =~ m{\d+\Q___&&&___\E$match_username\Q___&&&___\E$match_domain\Q___&&&___\E(.+)$}) { $retitles->{$oldurl}{$ressrc} = $id; - } } next if ($token->[2]->{'type'} eq 'external'); if ($token->[2]->{'type'} eq 'zombie') { + next if ($skip); $zombies->{$oldurl}{$ressrc} = $id; $changed = 1; } elsif ($ressrc =~ m{^/uploaded/($match_domain)/($match_courseid)/(.+)$}) { - my $srccdom = $1; - my $srccnum = $2; + my $srcdom = $1; + my $srcnum = $2; my $rem = $3; - if (($srccdom ne $cdom) || ($srccnum ne $cnum) || ($prefixchg) || - ($mapchanges->{$oldurl})) { + my $newurl; + my $mapname; + if ($rem =~ /^(default|supplemental)(_?\d*).(sequence|page)$/) { + my $prefix = $1; + $mapname = $prefix.$2; + if ($tomove->{$mapname}) { + &url_paste_fixups($ressrc,$folder,$prefixchg,$cdom,$cnum,$allmaps, + $rewrites,$retitles,$copies,$dbcopies,$zombies, + $params,$mapmoves,$mapchanges,$tomove,$newsubdir, + $newurls); + next; + } else { + ($newurl,my $error) = + &get_newmap_url($ressrc,$folder,$prefixchg,$cdom,$cnum, + $srcdom,$srcnum,\$title,$allmaps,$newurls); + if ($newurl =~ /(?:default|supplemental)_(\d+)\.(?:sequence|page)$/) { + $newsubdir->{$ressrc} = $1; + } + if ($error) { + next; + } + } + } + if (($srcdom ne $cdom) || ($srcnum ne $cnum) || ($prefixchg) || + ($mapchanges->{$oldurl}) || (($newurl ne '') && ($newurl ne $oldurl))) { + if ($rem =~ /^(default|supplemental)(_?\d*).(sequence|page)$/) { $rewrites->{$oldurl}{$ressrc} = $id; $mapchanges->{$ressrc} = 1; - unless (&url_paste_fixups($ressrc,$prefixchg,$cdom,$cnum,$allmaps, + unless (&url_paste_fixups($ressrc,$folder,$prefixchg,$cdom,$cnum,$allmaps, $rewrites,$retitles,$copies,$dbcopies,$zombies, - $params,$mapmoves,$mapchanges)) { + $params,$mapmoves,$mapchanges,$tomove,$newsubdir, + $newurls)) { $mapmoves->{$ressrc} = 1; } $changed = 1; @@ -1069,27 +1360,30 @@ sub url_paste_fixups { } } } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/(.+)$}) { - my $srccdom = $1; - my $srccnum = $2; - if (($srccdom ne $cdom) || ($srccnum ne $cnum)) { + next if ($skip); + my $srcdom = $1; + my $srcnum = $2; + if (($srcdom ne $cdom) || ($srcnum ne $cnum)) { $rewrites->{$oldurl}{$ressrc} = $id; $dbcopies->{$oldurl}{$ressrc} = $id; $changed = 1; } } elsif ($ressrc =~ m{^/public/($match_domain)/($match_courseid)/(.+)$}) { - my $srccdom = $1; - my $srccnum = $2; - if (($srccdom ne $cdom) || ($srccnum ne $cnum)) { + next if ($skip); + my $srcdom = $1; + my $srcnum = $2; + if (($srcdom ne $cdom) || ($srcnum ne $cnum)) { $rewrites->{$oldurl}{$ressrc} = $id; $dbcopies->{$oldurl}{$ressrc} = $id; $changed = 1; } } } elsif ($token->[1] eq 'param') { + next if ($skip); my $to = $token->[2]->{'to'}; if ($to ne '') { if (ref($params->{$oldurl}{$to}) eq 'ARRAY') { - push (@{$params->{$oldurl}{$to}},$token->[2]->{'name'}); + push(@{$params->{$oldurl}{$to}},$token->[2]->{'name'}); } else { @{$params->{$oldurl}{$to}} = ($token->[2]->{'name'}); } @@ -1100,25 +1394,9 @@ sub url_paste_fixups { } sub apply_fixups { - my ($is_map,$prefixchg,$cdom,$cnum,$oldurl,$url,$removefrommap,$rewrites, - $retitles,$copies,$dbcopies,$zombies,$params,$docmoves,$mapmoves,$errors, - $before,$after) = @_; - my ($oldsubdir,$newsubdir,$subdirchg); - if ($is_map) { - ($oldsubdir) = - ($oldurl =~ m{^/uploaded/$match_domain/$match_courseid/(?:default|supplemental)_?(\d*)}); - if ($oldsubdir eq '') { - $oldsubdir = 'default'; - } - ($newsubdir) = - ($url =~ m{^/uploaded/$match_domain/$match_courseid/(?:default|supplemental)_?(\d*)}); - if ($newsubdir eq '') { - $newsubdir = 'default'; - } - if ($oldsubdir ne $newsubdir) { - $subdirchg = 1; - } - } + my ($folder,$is_map,$prefixchg,$cdom,$cnum,$oldurl,$url,$removefrommap, + $removeparam,$rewrites,$retitles,$copies,$dbcopies,$zombies,$params, + $docmoves,$mapmoves,$newsubdir,$errors,$before,$after) = @_; foreach my $key (keys(%{$copies}),keys(%{$docmoves})) { my @allcopies; if (ref($copies->{$key}) eq 'HASH') { @@ -1140,8 +1418,8 @@ sub apply_fixups { } if (@allcopies > 0) { foreach my $item (@allcopies) { - my ($relpath,$fname) = - ($item =~ m{^(/uploaded/$match_domain/$match_courseid/(?:docs|supplemental)/(?:default|\d+)/.*/)([^/]+)$}); + my ($relpath,$oldsubdir,$fname) = + ($item =~ m{^(/uploaded/$match_domain/$match_courseid/(?:docs|supplemental)/(default|\d+)/.*/)([^/]+)$}); if ($fname ne '') { my $content = &Apache::lonnet::getfile($item); unless ($content eq '-1') { @@ -1154,8 +1432,8 @@ sub apply_fixups { if ($prefixchg) { $storefn =~ s/^\Q$before->{'doc'}\E/$after->{'doc'}/; } - if (($key eq $oldurl) && ($subdirchg)) { - $storefn =~ s{^(docs|supplemental)/\Q$oldsubdir\E/}{$1/$newsubdir/}; + if ($newsubdir->{$key}) { + $storefn =~ s#^(docs|supplemental)/\Q$oldsubdir\E/#$1/$newsubdir->{$key}#; } } ©_dependencies($item,$storefn,$relpath,$errors,\$content); @@ -1180,6 +1458,9 @@ sub apply_fixups { if ($prefixchg) { $storefn =~ s/^\Q$before->{'map'}\E/$after->{'map'}/; } + if ($newsubdir->{$key}) { + $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir->{$key}/; + } my $mapcontent = &Apache::lonnet::getfile($key); if ($mapcontent eq '-1') { if (ref($errors) eq 'HASH') { @@ -1199,22 +1480,25 @@ sub apply_fixups { my %updates; if ($is_map) { foreach my $key (keys(%{$rewrites})) { - $updates{$key} = 1; + $updates{$key} = 1; } foreach my $key (keys(%{$zombies})) { - $updates{$key} = 1; + $updates{$key} = 1; } foreach my $key (keys(%{$removefrommap})) { - $updates{$key} = 1; - } + $updates{$key} = 1; + } + foreach my $key (keys(%{$removeparam})) { + $updates{$key} = 1; + } foreach my $key (keys(%{$dbcopies})) { - $updates{$key} = 1; + $updates{$key} = 1; } foreach my $key (keys(%{$retitles})) { - $updates{$key} = 1; + $updates{$key} = 1; } foreach my $key (keys(%updates)) { - my (%torewrite,%toretitle,%toremove,%zombie,%newdb); + my (%torewrite,%toretitle,%toremove,%remparam,%currparam,%zombie,%newdb); if (ref($rewrites->{$key}) eq 'HASH') { %torewrite = %{$rewrites->{$key}}; } @@ -1224,6 +1508,9 @@ sub apply_fixups { if (ref($removefrommap->{$key}) eq 'HASH') { %toremove = %{$removefrommap->{$key}}; } + if (ref($removeparam->{$key}) eq 'HASH') { + %remparam = %{$removeparam->{$key}}; + } if (ref($zombies->{$key}) eq 'HASH') { %zombie = %{$zombies->{$key}}; } @@ -1232,69 +1519,72 @@ sub apply_fixups { $newdb{$item} = &dbcopy($item); } } - my $map = &Apache::lonnet::getfile($key); - my $newcontent; - if ($map eq '-1') { - return &mt('Paste failed: an error occurred reading a folder or page: [_1].',$key); - } else { - my $parser = HTML::TokeParser->new(\$map); - $parser->attr_encoded(1); - while (my $token = $parser->get_token) { - if ($token->[0] eq 'S') { - if ($token->[2]->{'type'} eq 'zombie') { - next if (($token->[2]->{'src'} ne '') && - ($zombie{$token->[2]->{'src'}} eq $token->[2]->{'id'})); - } - if ($token->[1] eq 'resource') { - my $src = $token->[2]->{'src'}; - my $id = $token->[2]->{'id'}; - my $title = $token->[2]->{'title'}; - my $changed; - if ((exists($toretitle{$src})) && ($toretitle{$src} eq $id)) { - if ($title =~ m{^\d+\Q___&&&___\E$match_username\Q___&&&___\E$match_domain\Q___&&&___\E(.+)$}) { - $token->[2]->{'title'} = $1; - $changed = 1; - } + if (ref($params->{$key}) eq 'HASH') { + %currparam = %{$params->{$key}}; + } + my ($errtext,$fatal) = &LONCAPA::map::mapread($key); + if ($fatal) { + return $errtext; + } + for (my $i=0; $i<@LONCAPA::map::zombies; $i++) { + if (defined($LONCAPA::map::zombies[$i])) { + my ($title,$src,$ext,$type)=split(/\:/,$LONCAPA::map::zombies[$i]); + if ($zombie{$src} eq $i) { + undef($LONCAPA::map::zombies[$i]); + } + } + } + for (my $i=0; $i<@LONCAPA::map::resources; $i++) { + if (defined($LONCAPA::map::resources[$i])) { + my $changed; + my ($title,$src,$ext,$type)=split(/\:/,$LONCAPA::map::resources[$i]); + if ($toremove{$src} eq $i) { + splice(@LONCAPA::map::order,$i,1); + if (ref($currparam{$i}) eq 'ARRAY') { + foreach my $name (@{$currparam{$i}}) { + &LONCAPA::map::delparameter($i,'parameter_'.$name); } - if ((exists($torewrite{$src})) && ($torewrite{$src} eq $id)) { - $src =~ s{^/(uploaded|adm|public)/$match_domain/$match_courseid/}{/$1/$cdom/$cnum/}; - if ($src =~ m{^/uploaded/}) { - if ($prefixchg) { - if ($src =~ /\.(page|sequence)$/) { - $src =~ s#^(/uploaded/$match_domain/$match_courseid/)\Q$before->{'map'}\E#$1$after->{'map'}#; - } else { - $src =~ s#^(/uploaded/$match_domain/$match_courseid/)\Q$before->{'doc'}\E#$1$after->{'doc'}#; - } - } - if (($key eq $oldurl) && ($src !~ /\.(page|sequence)$/) && ($subdirchg)) { - $src =~ s{^(/uploaded/$match_domain/$match_courseid/\w+/)\Q$oldsubdir\E}{$1$newsubdir}; - } + } + next; + } + my $origsrc = $src; + if ((exists($toretitle{$src})) && ($toretitle{$src} eq $i)) { + if ($title =~ m{^\d+\Q___&&&___\E$match_username\Q___&&&___\E$match_domain\Q___&&&___\E(.+)$}) { + $changed = 1; + } + } + if ((exists($torewrite{$src})) && ($torewrite{$src} eq $i)) { + $src =~ s{^/(uploaded|adm|public)/$match_domain/$match_courseid/}{/$1/$cdom/$cnum/}; + if ($origsrc =~ m{^/uploaded/}) { + if ($prefixchg) { + if ($src =~ /\.(page|sequence)$/) { + $src =~ s#^(/uploaded/$match_domain/$match_courseid/)\Q$before->{'map'}\E#$1$after->{'map'}#; + } else { + $src =~ s#^(/uploaded/$match_domain/$match_courseid/)\Q$before->{'doc'}\E#$1$after->{'doc'}#; } - $token->[2]->{'src'} = $src; - $changed = 1; - } elsif ($newdb{$src} ne '') { - $token->[2]->{'src'} = $newdb{$src}; - $changed = 1; } - if ($changed) { - $newcontent .= "<$token->[1]"; - foreach my $attr (@{$token->[3]}) { - if ($attr =~ /^\w+$/) { - $newcontent .= ' '.$attr.'="'.$token->[2]->{$attr}.'"'; - } + if ($newsubdir->{$origsrc}) { + if ($src =~ /\.(page|sequence)$/) { + $src =~ s#^(/uploaded/$match_domain/$match_courseid/(?:default|supplemental)_)(\d+)#$1$newsubdir->{$origsrc}#; + } else { + $src =~ s#^(/uploaded/$match_domain/$match_courseid/\w+/)(\d+)#$1$newsubdir->{$origsrc}#; } - $newcontent .= ' />'."\n"; - } else { - $newcontent .= $token->[4]."\n"; } - } elsif (($token->[2]->{'id'} ne '') && - (exists($toremove{$token->[2]->{'id'}}))) { - next; - } else { - $newcontent .= $token->[4]."\n"; } - } elsif ($token->[0] eq 'E') { - $newcontent .= $token->[2]."\n"; + $changed = 1; + } elsif ($newdb{$src} ne '') { + $src = $newdb{$src}; + $changed = 1; + } + if ($changed) { + $LONCAPA::map::resources[$i] = join(':',($title,$src,$ext,$type)); + } + } + } + foreach my $idx (keys(%remparam)) { + if (ref($remparam{$idx}) eq 'ARRAY') { + foreach my $name (@{$remparam{$idx}}) { + &LONCAPA::map::delparameter($idx,'parameter_'.$name); } } } @@ -1308,11 +1598,17 @@ sub apply_fixups { if ($prefixchg) { $storefn =~ s/^\Q$before->{'map'}\E/$after->{'map'}/; } + if ($newsubdir->{$key}) { + $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir->{$key}/; + } } - my $newmapurl = - &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn, - $newcontent); - if ($newmapurl eq '/adm/notfound.html') { + my $report; + if ($folder !~ /^supplemental/) { + $report = 1; + } + my ($outtext,$errtext) = + &LONCAPA::map::storemap("/uploaded/$cdom/$cnum/$storefn",1,$report); + if ($errtext) { return &mt('Paste failed: an error occurred saving the folder or page.'); } } @@ -1496,13 +1792,13 @@ sub editor { if ($env{'form.pastemarked'}) { my %paste_errors; - my $paste_res = - &do_paste_from_buffer($coursenum,$coursedom,$folder,\%paste_errors); - if ($paste_res eq 'ok') { -# Store the result - ($errtext,$fatal) = &storemap($coursenum,$coursedom,$folder.'.'.$container); - return $errtext if ($fatal); - } elsif ($paste_res ne '') { + my ($paste_res,$save_error) = + &do_paste_from_buffer($coursenum,$coursedom,$folder,$container, + \%paste_errors); + if ($save_error ne '') { + return $save_error; + } + if ($paste_res ne 'ok') { $r->print('

'.$paste_res.'

'); } if (keys(%paste_errors) > 0) { @@ -1519,7 +1815,11 @@ sub editor { $r->print($upload_output); if (&handle_edit_cmd()) { - ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container); + my $contentchg; + if ($env{'form.cmd'} =~ /^(del|cut)_/) { + $contentchg = 1; + } + ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container,$contentchg); return $errtext if ($fatal); } # Group import/search @@ -1546,7 +1846,7 @@ sub editor { $LONCAPA::map::order[$#LONCAPA::map::order+1]=$idx; } ($errtext,$fatal)=&storemap($coursenum,$coursedom, - $folder.'.'.$container); + $folder.'.'.$container,1); return $errtext if ($fatal); } else { $r->print('

'.&mt('No map selected.').'

'); @@ -1638,7 +1938,7 @@ sub editor { my $readfile="/uploaded/$coursedom/$coursenum/$folder.$container"; $r->print(&generate_edit_table($tid,$orderhash,$to_show,$iconpath,$jumpto, $readfile)); - &print_paste_buffer($r,$container,$folder); + &print_paste_buffer($r,$container,$folder,$coursedom,$coursenum); } else { if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) { #Function Box for Supplemental Content for users with mdc priv. @@ -1726,7 +2026,7 @@ sub process_file_upload { $comment.':'.$url.':'.$ext.':normal:res'; $LONCAPA::map::order[$#LONCAPA::map::order+1]= $newidx; ($errtext,$fatal)=&storemap($coursenum,$coursedom, - $folder.'.'.$container); + $folder.'.'.$container,1); if ($fatal) { $$upload_output = '
'.$errtext.'
'; return; @@ -1884,19 +2184,9 @@ sub entryline { 'cp' => 'Copy'); my $nocopy=0; my $nocut=0; - if ($url=~/\.(page|sequence)$/) { - if ($url =~ m{/res/}) { - # no copy for published maps - $nocopy = 1; - } else { - foreach my $item (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$url),1)) { - my ($title,$url,$ext,$type)=split(/\:/,$item); - if (($url=~/\.(page|sequence)/) && ($type ne 'zombie')) { - $nocopy=1; - last; - } - } - } + if ($url=~ m{^/res/.+\.(page|sequence)$}) { + # no copy for published maps + $nocopy=1; } if ($url=~/^\/res\/lib\/templates\//) { $nocopy=1; @@ -3047,6 +3337,9 @@ sub handler { onload => "javascript:resize_scrollbox('contentscroll','1','1');", }; } + if ($env{'docs.markedcopy_url'}) { + $script .= &paste_popup_js(); + } } # -------------------------------------------------------------------- Body tag $script = '